# LunarLink: an interface testing platform built on HttpRunner and Django

> LunarLink is a self-hosted API testing platform that puts HttpRunner behind a Django and Vue interface, with test case management, traffic recording, scheduled runs and report history. The README is written in Chinese, and the project is a fork of AnotherFasterRunner, which the author credits explicitly as the project that would not exist without it.

**tahitimoon/LunarLink** — An interface automation testing platform based on HttpRunner + Django + Vue + Element UI, production-ready.

- Repository: https://github.com/tahitimoon/LunarLink
- Website: https://docs.lunarlink.top
- Stars: 541 · Forks: 68
- Language: Python
- License: MIT
- Published: 2026-10-22 · Updated: 2026-10-22 · Language: en
- Canonical page: https://hysenlabs.com/projects/tahitimoon-lunarlink

## A web front end over HttpRunner

LunarLink is described as an interface automation testing platform based on HttpRunner, Django, Vue and Element UI, and the README says in one line that it is production usable. The technical stack list makes the shape of it obvious: Django for the application, Django REST framework for the API, Vue.js with Element UI for the front end, Nginx as the reverse proxy, HttpRunner as the test case execution engine, RabbitMQ, Redis, MySQL and Docker.

The point of the architecture is that the test case format and the execution are HttpRunner's, and LunarLink is the management layer around them. The feature list is organised by that boundary. Interface management treats one API as one backend HTTP endpoint, and such an API can be run on its own or used as a step inside a case. Around that core are grouping, parameter extraction, data assertions, variable references, pre- and post-hook functions, interface debugging and log display. Test cases are groups of APIs with dynamic parameter passing between them, and the README is explicit that it does not distinguish between scenario cases and single-interface cases, supports both synchronous and asynchronous batch execution, and generates test reports.

Two entries go beyond managing cases. Interface import synchronises with YApi, and the README notes that because YApi is the intermediary this indirectly supports Swagger, Postman and Har, so there is no manual data entry step. Traffic recording is the other: you open a browser, perform a series of operations, and get a test case out of it, with parameters between interfaces extracted and linked automatically.

The repository layout matches a two-application project, with backend/ and frontend/ directories, a deployment/ directory, a docker-compose.yml at the root, an .env.example, and a screenshots/ directory. The licence is MIT and the last push to the repository was on 2026-10-10, with the recent releases v1.0.6, v1.0.5 and v1.0.4 all from May and April 2024.

## The feature modules, translated from what the README claims

The Chinese feature list is worth working through in English because it defines the product's scope precisely.

Login covers account authentication, user management and permission management. Project management covers creating projects, listing them and operating on them, with a project board showing daily, weekly and monthly data at different granularities. The project overview gives basic project information, an overview of APIs, test cases and task executions, and daily detail.

Configuration management is the piece that makes the platform usable across environments. You define a base_url per configuration, along with common request header parameters, local variables, pre- and post-hook functions and parameterised content, and an API or a case can select a different configuration to run under. Global variables are a separate mechanism, and their values can themselves call functions in the driver code, which is where shared accounts and secrets are meant to live.

Driver code is Python, and it is where the things an interface framework cannot express are written: pre- and post-hook functions, helper functions, and specifically request parameter signing, encryption and decryption of responses. That last capability is the reason a Chinese-market testing platform needs it, since internal APIs frequently sign their requests.

Scheduled tasks follow crontab expressions and can be switched on and off from the interface, with case execution running serially or in parallel, and a test report pushed to WeCom when a run finishes. Report history keeps the reports from scheduled, debugging and asynchronous runs, viewable, filterable and deletable, and the README notes you can also view other people's test reports.

## The four backing services, and why they are there

The preparation section in the README lists the runtime requirements, and they are not light.

The preparation section lists the runtime requirements in this order: Python 3.9.5 or later, with the 3.9.x line recommended, Node 16 or later with the newest advised, MySQL 5.7.0 or later with the 5.7.x line recommended, RabbitMQ 3.x with the management image, which the file says is needed by default and should be the latest version, and Redis 6.2.6 or later.

Python for Django, Node for the Vue build, MySQL for the data, RabbitMQ with the management image for the task queue, and Redis for caching. The version recommendations in the file are the 3.9.x Python line and the 5.7.x MySQL line, with the newest RabbitMQ and Node advised.

The reason for RabbitMQ and Redis becomes clear from the feature list. Scheduled and asynchronous case execution is a queue, and Celery is the worker for it, with django-celery-beat listed in the stack for the crontab scheduling. So the message broker is not decoration, it is how a scheduled run reaches a worker process.

The docker-compose.yml at the repository root spells out the services and their topology, and the network addresses are fixed rather than assigned, which is a decision with consequences. The Django service listens on 8000, the web service on 8081 and mounts an nginx configuration from deployment/web/nginx.conf, the celery service depends on the MySQL service, and the proxy service publishes 7778. Each service also sets TZ to Asia/Shanghai, so a Docker deployment and a local run are on the same clock.

The .env.example file is where those connections are configured, and it is worth reading closely because it is a template that has to be edited before anything works. It sets the database host, port, user, password and name, the RabbitMQ user, password, host and port, and the Redis host, password, port and database index. It also carries the report base URL, the WeCom report title and the WeCom robot webhook address, and a full SMTP block for email with the host, port, sender account, password and the TLS and SSL switches. The proxy configuration at the end turns the traffic recording proxy on and sets its port to 7778, which matches the port published by the proxy service in the compose file.

## Running the front end and the back end

The front end is a Vue application and the README recommends yarn, explaining that the project ships a yarn.lock and that using another package manager tends to cause version dependency problems.

```bash
git clone https://github.com/tahitimoon/LunarLink.git
cd LunarLink/frontend
yarn install --registry=https://registry.npmmirror.com
yarn start
```

The install goes through the npmmirror registry, which is a China-based npm mirror, and the development server runs on port 8888, configurable in config/index.js, with the backend address set in config/dev.env.js and config/prod.env.js left unchanged. A production build is a commented yarn build line in the same block.

The back end is Django, and the sequence is clone, copy the environment file, install requirements, migrate, create an admin, and serve.

```bash
cd LunarLink/backend

mv .env.example .env

pip3 install -r requirements.txt

python3 manage.py makemigrations
python3 manage.py migrate

python3 manage.py createsuperuser

python3 manage.py runserver
```

The last command in that block is the one that is easy to overlook and that the feature list depends on: python3 proxy.py starts the traffic recording proxy. Without it, the recording feature that produces test cases from browser sessions has nothing to record through.

Django's own admin is at http://127.0.0.1:8000/admin/ for setting the account names, the front end is at http://127.0.0.1:8888, and the interface documentation is served at http://127.0.0.1:8000/swagger/. The scheduled and asynchronous task worker is started separately, from the console, with celery -A backend worker -B --loglevel=info, where the -B flag runs the beat scheduler alongside the worker.

## Docker deployment, and the ARM64 caveat

The repository ships a docker-compose.yml and a deployment/ directory with per-service Dockerfiles, one each for django, web, celery and proxy, and the README points at deployment/README.md for the Docker build instructions rather than repeating them.

Two things about the compose file are worth knowing before you use it. The MySQL service carries a comment in Chinese that if you are on an arm64 architecture such as an Apple Silicon Mac, you should change the image to mysql/my, which is the Oracle-provided arm64 build of MySQL. That is a real failure point on the machines most likely to be running a local evaluation of this project, and it is exactly the kind of thing that is easy to miss when the compose file is mostly right.

The second is the fixed IP addressing on the user-defined network, with addresses in the 177.8.0.0 range and restart: always on every service. Fixed addresses are what make the service-to-service hostnames in .env work, and restart policies mean a container comes back after a host reboot, which is what makes the scheduled task feature survive a restart. The cost is that the compose file is not portable to a network that already uses that range, and the timezone is pinned to Asia/Shanghai in every service, so a deployment elsewhere will show the wrong time in reports unless the compose file is edited.

The web service is the one that fronts everything, with nginx mounted in from the deployment directory and port 8081 published, and the report base URL in .env points at http://localhost:8081/api/lunarlink/reports, which is the URL the running front end uses to fetch generated reports.

## Where LunarLink is the wrong choice

Three cases point elsewhere. The first is a team that wants to author test cases in the platform rather than manage cases written elsewhere. The case format and the execution engine are HttpRunner's, and the platform's job is to organise, schedule and report on them. If your team does not already write HttpRunner cases, the learning curve is the framework's, and the platform does not remove it.

The second is a team that wants a lightweight service. Four backing services are required, MySQL, RabbitMQ, Redis and Celery, plus the Django app, the Vue front end and the proxy, and in the local development setup you run the front end dev server, the Django runserver, the proxy and a Celery worker simultaneously. That is a substantial surface for a tool whose job is running HTTP requests. A team with a handful of APIs to check will get more out of a pytest file with httpx and a CI job.

The third is a team outside China that needs the report push. The scheduled-run report goes to a WeCom robot webhook, and the .env.example ships that key empty, and the timezone is Asia/Shanghai in every compose service and in the .env settings. The SMTP block is configured with a Chinese enterprise mail provider, though the keys are generic enough to point elsewhere. None of this is a blocker, but it is a signal about where the project is aimed and about which parts you will be reconfiguring.

The alternative worth weighing is AnotherFasterRunner, the project the author explicitly credits as the foundation, since without it LunarLink would not exist, along with HttpRunner's own command line runner. The difference in approach is that AnotherFasterRunner is the same kind of platform without LunarLink's specific changes, and the HttpRunner command line is a script with no web interface, no schedule, no report history and no project board. If what you need is to run cases from a shell and archive the reports as files, the command line runner is a fraction of the operational cost. If what you need is a shared place where a team can see what was tested, when, and what failed, then a platform with a scheduler, a report history and a permission model is the right shape, and LunarLink is a working MIT licensed instance of that shape with the README and the documentation site at docs.lunarlink.top.

## Conclusion

LunarLink fits a team that already writes HttpRunner test cases and wants a web interface over them, with project grouping, scheduled execution and report history, and that is comfortable running MySQL, RabbitMQ and Redis alongside the application. It does not fit a team that wants a test framework to write cases in, because the case format and execution engine are HttpRunner's, and it does not fit a small team that would rather not maintain four backing services. Before you deploy it, read the deployment/README.md Docker build instructions, rename .env.example to .env and set the database, RabbitMQ and Redis values, since the sample file ships with placeholder credentials and a Chinese enterprise WeChat webhook key.

## FAQ

### What is LunarLink?

It is a self-hosted interface automation testing platform based on HttpRunner, Django, Vue and Element UI, described in the README as production usable. The project is MIT licensed, the documentation site is docs.lunarlink.top, and the author credits AnotherFasterRunner as the project without which LunarLink would not exist.

### What runtime services does LunarLink need?

The README lists Python 3.9.5 or later with the 3.9.x line recommended, Node 16 or later, MySQL 5.7.0 or later, RabbitMQ 3.x with the management image, and Redis 6.2.6 or later. The stack also includes django-celery-beat for scheduled tasks and Nginx as the reverse proxy.

### How do I start the front end and back end of LunarLink?

The front end uses yarn, so yarn install against the npmmirror registry and yarn start, with the browser at http://127.0.0.1:8888 and the port set in config/index.js. The back end needs .env renamed from .env.example, pip3 install of requirements.txt, makemigrations and migrate, createsuperuser, and python3 manage.py runserver, plus python3 proxy.py for traffic recording.

### How do scheduled and asynchronous test runs work in LunarLink?

Scheduled tasks follow crontab expressions and can be enabled and disabled from the interface, with case execution running serially or in parallel, and a test report pushed to WeCom when a run completes. The worker is started separately with celery -A backend worker -B --loglevel=info, which runs the beat scheduler alongside the worker.

### Can LunarLink import existing API definitions?

Yes. The interface import module synchronises with YApi, and the README notes that because YApi is used as the intermediary this indirectly supports Swagger, Postman and Har, so cases can be generated without manual entry. A separate traffic recording module produces a test case from a browser session, with parameters between interfaces extracted and linked automatically.

## Sources

- [License: MIT](https://github.com/tahitimoon/LunarLink/blob/main/LICENSE)
- [Project website](https://docs.lunarlink.top)
- [README](https://github.com/tahitimoon/LunarLink/blob/main/README.md)
- [Releases](https://github.com/tahitimoon/LunarLink/releases)
- [tahitimoon/LunarLink on GitHub](https://github.com/tahitimoon/LunarLink)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/tahitimoon-lunarlink
