Open-source project
liwanlei/FXTest avatar
liwanlei/FXTest

FXTest: a Flask interface testing platform with mock server and scheduler

接口自动化测试平台——python+flask版,支持http协议,java 版本开发完毕https://github.com/liwanlei/plan

757 stars404 forksPythonMIT

At a glance

What is it?
FXTest is a Chinese-language interface automation testing platform built with Flask, Python 3 and Bootstrap, offering API and case management, scheduled runs through APScheduler and Redis, a built-in mock server, HTML reports with email and DingTalk notification, and JMeter script generation. The author describes it as a study reference, maintained irregularly.
Who is it for?
FXTest suits a Chinese-speaking team that wants a self-hosted interface testing platform in one application, with scheduling, mocking and reporting already wired together rather than assembled from separate tools. It does not suit a team that needs a maintained, current stack, since the pinned dependencies are from the 2021 era and the author states the project is maintained irregularly and offered for learning.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 99 days ago.
What is it written in?
Mainly Python, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 25, 2026, and from our analysis. They are not legal advice.

Editorial analysis

What the platform covers

FXTest is a complete interface automation testing solution, described in the README as built with Flask, Python 3, Bootstrap, APScheduler, Redis and SQLite or MySQL. The project topics are automated-testing, flask, interface, mock-server, python-flask and test.

The feature list is broad enough to describe the scope. Interface management covers projects, modules, API CRUD and interface parameter configuration. Test cases cover creation, execution of several cases in combination, and import and export to Excel. Scheduled tasks run on APScheduler with Redis for persistence. The built-in mock server validates headers and params and returns JSON or XML. Test reports are generated as HTML with email and DingTalk group notification. Load testing support converts interface cases into JMeter JMX scripts and runs them remotely. There is multi-role permission management with ordinary user, administrator and super administrator roles, and Flask-Admin provides the backend administration system.

That combination is the point of the project. Each of these is a small tool that a team could add separately, and the platform's argument is that the whole loop, define an interface, write a case, schedule it, report the result, notify the group, is one application.

The project description also points to a Java implementation of the same idea at github.com/liwanlei/plan, which is described as complete, and the README recommends several related projects by the same author covering App automation, ADB performance tooling and a non-platform Python interface testing script.

One caveat comes from the README itself, in the contact section, where the project is described as an open source project maintained irregularly over the long term and offered for study and reference.

The project layout and what lives where

The README publishes the whole directory tree, which is the best available description of the design.

The app/ directory is the Flask application, and it is split by feature. There is a case/ directory for test case management including creation, execution and export, a home/ directory for the index page, projects and dashboard, an interface/ directory for API management, a mock/ directory for the mock server, a task/ directory for scheduled task management, a test_case/ directory described as the test execution engine, and a users/ directory for user management. Inside app/ there are static/ for CSS, JavaScript, fonts and images, templates/ for Jinja2 templates split into home, add and edit subdirectories, an upload/ directory for uploaded file storage, models.py for the SQLAlchemy data models, forms.py for the WTForms forms, views.py for the root route views and urls.py for root route registration.

The common/ directory is the part that holds the actual testing capability, and its twenty-odd modules are the interesting part. PackageRequest.py is the HTTP request core and api_client.py wraps HTTP API requests. assertions.py holds the assertion logic. jmx_builder.py generates the JMeter JMX scripts. mock_server.py is the core of the mock server. BSTestRunner.py is the test executor, described as based on unittest. Then there is the plumbing: redis_client.py, mysql_client.py, excel_utils.py, excel_parser.py, dingtalk.py for the DingTalk robot notification, ssh_tools.py for remote execution, jenkins_client.py for the Jenkins API, send_email.py, decorators.py for the permission decorators, and a set of list, dict and pagination helpers.

At the root there are config.py for environment variables and Flask configuration, manage.py as the application entry point, db_create.py and db_migrate.py for database setup, error_message.py as an error code and message enumeration, requirements.txt, a Dockerfile and the .env template.

The repository also carries three SQLite files at the top level, data.sqlite, produce.sqlite and test.sqlite, plus a test.sql, which tells you the project ships some data for demonstration.

Installing and running it locally

The environment requirements are Python 3.6 or above, Redis because the scheduled task persistence depends on it, SQLite as the default database or MySQL, and Jenkins if you want that integration, which the README notes is optional and whose code is commented out by default.

The install step is the standard one.

bash
pip install -r requirements.txt

Then you copy the .env template to a real configuration file and edit it. The README's table lists the variables and their defaults, and the set is a good summary of what the platform talks to. SECRET_KEY is the Flask key, DATABASE_URL selects the database and leaving it empty means SQLite, REDIS_HOST and REDIS_PORT default to 127.0.0.1 and 6379, REDIS_PASSWORD is empty by default, MAIL_USERNAME and MAIL_PASSWORD are for the mail notifications, DINGTALK_ACCESS_TOKEN is the DingTalk robot token, and JENKINS_URL and JENKINS_USER default to localhost:8080. More configuration lives in config.py and the .env file.

The application is then started with the entry point script.

bash
python manage.py

After that you open http://127.0.0.1:5000/index in the browser.

The .env template deserves a specific warning, because the repository contains a .env file and the README asks you to copy it. If that file has real values in it, they are in the repository, and the v4.x changelog records that all sensitive configuration was moved to .env environment variables as one of the hardening changes, so the intent is right even if the committed template is a risk.

The v4.x hardening work and the v3.x feature history

The upgrade notes in the README are the most honest part of the documentation, and they are worth reading because they describe what the author fixed rather than what the project added.

The v4.x line, described as the current one, is largely a hardening release. eval() calls were replaced with ast.literal_eval() and json.loads(), which closes an arbitrary code execution path that matters a great deal in a test platform that handles user-supplied expressions. All sensitive configuration moved to .env environment variables. The app/Interface/ directory was renamed to app/interface/ for consistent lowercase naming, and 18 modules under common/ were renamed from camel case or misspelled names to `lowercase_with_underscores`. Empty except clauses became except Exception, and return values were unified. os.system('touch') was replaced with a portable open and close, and the debug print() calls were replaced with structured logger output, which is what the loguru-based case logger in common/case_logger.py is for.

The v3.x line is where the features came from. Jenkins integration, a refactor of the test case execution engine onto unittest, one-click conversion of interface cases into JMeter JMX scripts, generic parameter configuration support, database structure optimisation, a blacklist feature, smoke and regression case markers, and the log framework upgrade to loguru.

Two things stand out for an adopter. The blacklist and the smoke and regression markers are the features a real team would reach for first, because they are what lets a large case set be run selectively. And the renaming work in v4.x means any script or documentation that referenced the old camel case module paths breaks with the upgrade, which is a migration cost the changelog does not spell out.

Deployment with Docker or behind a reverse proxy

Two deployment routes are documented, and the README is brief about both.

The Docker route builds the image and runs it with the application port and Redis exposed.

bash
docker build -t fxtest .
docker run -p 5000:5000 -p 6379:6379 fxtest

The second route is Supervisor with Gunicorn and Nginx, and the configuration files for it are named in the README: flaskapi_su.conf configures Supervisor, super.conf configures Gunicorn, and the Gunicorn start command is given explicitly.

bash
gunicorn -c super.conf manage:app

The repository listing shows the full set of deployment configuration files: flaskapi.conf, flaskapi_su.conf, flaskapi_uwsgi.ini and super.conf, so there is a uWSGI path as well. The docker-compose file is not present, so the Docker route is a single container with Redis alongside, which is enough to try the platform and not enough for a real deployment.

The Gunicorn route is the one to use for anything longer lived, and the fact that the config files are committed is helpful. What is missing is any mention of what runs the migrations in production, and since db_migrate.py is at the root of the repository rather than being wired into an entry point, that step has to be run explicitly, and it has to be run before the application starts serving.

The scheduler is the other deployment consideration. APScheduler with Redis for persistence keeps the scheduled jobs across restarts, which is the right choice, but it also means the platform needs a reachable Redis, and the scheduled jobs will run against real interfaces at whatever time they were configured for.

Where FXTest is the wrong choice

The first limitation is the dependency vintage. The requirements file pins Flask 2.0.2, SQLAlchemy 1.4.13, APScheduler 3.7.0, redis 3.5.3, celery 5.2.2, gunicorn 20.1.0 and requests 2.25.1, all of them from the 2021 era. A platform that pins a Flask from before the 2.0 branch's later security fixes, and a SQLAlchemy before the 2.0 rewrite, is going to be in conflict with a current application, and anyone installing it into a modern environment will hit dependency conflicts. The upside is that it is self-contained and pinned, so it installs consistently in a fresh container, which is what the Docker route is for.

The second is that the interface layer is narrow. The README says the platform supports the HTTP protocol, and the test topics confirm it. A team whose testing needs are WebSocket, gRPC or database-level will find nothing here, and the Java sibling project exists because the author wanted that covered too.

The third is the maintenance posture, stated by the author. The project is maintained irregularly, and the versions.md changelog is linked for more history. An interface testing platform is infrastructure that teams depend on, so irregular maintenance is a real operational risk, and the practical mitigation is to treat the platform as an internal tool you fork rather than a dependency you track.

The fourth is the security surface of the whole design. A testing platform stores credentials for the interfaces it calls, holds the results of those calls, offers a mock server that responds to requests, and can execute commands over SSH on remote hosts through ssh_tools.py, plus Jenkins integration. That is a lot of capability in one application with three roles and a Flask-Admin backend. The v4.x eval() to ast.literal_eval() change shows the author was thinking about this, and the presence of a SECURITY.md file is a good sign, but the design still argues for running it on an internal network rather than exposing it.

The fifth is the UI. The interface is Bootstrap 3 with Flask-Bootstrap 3.3.7.1 and Flask-BabelEx for translations, which is a decade-old front end stack, and the README's own screenshots are the evidence. It is functional for an internal tool and dated for anything user-facing.

Licence, community and the cost of running your own platform

The project is under the MIT licence, with the LICENSE file at the root of the repository, so the code can be used and modified without restriction beyond keeping the notice.

The repository is not archived and the last push was on 2026-07-18, so the code is being touched, but the release history is empty in the sense that the project publishes no GitHub releases, so the master branch is the artefact and the versions.md file is the changelog.

The community around it is the author's other projects. The README links a Python App automation platform called UFATestPlan, a Python and ADB App performance tool, a non-platform Python interface testing script, the Java platform, and an Appium Python UI automation project. Contact details include an email address, a QQ number, and two QQ groups, one for the project and one for Python interface testing. The sponsorship picture is the author's GitHub sponsors page.

The running cost is where this kind of tool gets expensive. A database for the case and result data, Redis for the scheduler, and an SMTP server for the mail notifications, plus a DingTalk robot token if you want the group notifications. The Jenkins integration adds another service, and the JMeter export assumes a JMeter installation somewhere to run the generated scripts, plus SSH access to it, which is what ssh_tools.py is for.

Against that, the alternative is paying per seat for a commercial interface testing platform, or assembling the same pieces from separate open source tools, which is the comparison the project is implicitly making. For a team that already has Docker and a spare Redis, the platform can run on one small virtual machine, and that is the argument in its favour.

Editorial conclusion

FXTest suits a Chinese-speaking team that wants a self-hosted interface testing platform in one application, with scheduling, mocking and reporting already wired together rather than assembled from separate tools. It does not suit a team that needs a maintained, current stack, since the pinned dependencies are from the 2021 era and the author states the project is maintained irregularly and offered for learning. Verify the Flask and SQLAlchemy versions in requirements.txt against your own project before installing, and expect to run the platform behind a reverse proxy rather than exposing it directly.

Frequently asked questions

How do I install and start FXTest?

Install the dependencies with pip install -r requirements.txt, copy the .env template to a real configuration file and fill in the values, then run python manage.py and open http://127.0.0.1:5000/index. The environment needs Python 3.6 or above, Redis for scheduled task persistence, and SQLite or MySQL.

What features does the FXTest platform provide?

Interface management with projects, modules, CRUD and parameter configuration, test case management with multi-case execution and Excel import and export, scheduled runs through APScheduler and Redis, a built-in mock server with header and param validation, HTML test reports with email and DingTalk notification, one-click conversion of interface cases to JMeter JMX scripts, and multi-role permissions with a Flask-Admin backend.

How do I deploy FXTest in production?

The README documents two routes. Docker builds the image with docker build and runs it with docker run exposing ports 5000 and 6379. For a longer lived deployment it points at Supervisor with Gunicorn and Nginx, with flaskapi_su.conf for Supervisor, super.conf for Gunicorn, and the start command gunicorn -c super.conf manage:app.

What security changes did version 4 of FXTest make?

The v4.x changelog records that eval() calls were replaced with ast.literal_eval() and json.loads(), that all sensitive configuration was moved into .env environment variables, that empty except clauses were replaced with except Exception, and that debug print() calls were replaced with structured logger output. It also renames 18 common/ modules to `lowercase_with_underscores` and lowercases the app/interface/ directory.

Official sources

  1. Issues
  2. License: MIT
  3. liwanlei/FXTest on GitHub
  4. README
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/liwanlei-fxtest.svg)](https://hysenlabs.com/projects/liwanlei-fxtest)

Was this useful?