How to Run API Tests in the Plane Backend: A Complete Docker Guide
The Plane backend API test suite runs inside an isolated Docker Compose stack defined in docker-compose-test.yml, which spins up temporary PostgreSQL, Valkey, RabbitMQ, and MinIO containers before executing pytest from the api-tests service.
The makeplane/plane repository uses a fully containerized approach to ensure reproducible test runs. Instead of requiring a local database or Redis instance, the test harness orchestrates ephemeral infrastructure through Docker Compose, allowing developers to execute unit, contract, and integration tests in a clean environment for every run.
Prerequisites and Environment Setup
Before executing any Docker commands, you must prepare the environment configuration files. The repository includes a helper script that copies template files to active configuration locations.
Run the setup script from the repository root:
./setup.sh
This script copies apps/api/.env.example to apps/api/.env, along with environment files for other applications. The docker-compose-test.yml file reads variables from apps/api/.env, making this step mandatory before launching the test stack.
Understanding the Docker Compose Test Stack
The test infrastructure is defined in docker-compose-test.yml at the repository root. This configuration launches five interconnected services:
test-db– PostgreSQL 15.7 Alpine for the test databasetest-redis– Valkey 7.2.11 Alpine (Redis-compatible) for caching and Celery brokertest-mq– RabbitMQ 3.13.6 with management UI for task queuingtest-minio– MinIO for S3-compatible object storage testingapi-tests– Custom image built fromapps/api/Dockerfile.devthat executes pytest
The api-tests service declares explicit depends_on conditions with health checks for all data stores. The container waits until PostgreSQL, Valkey, RabbitMQ, and MinIO report healthy status before launching the test runner.
Running the Full API Test Suite
To execute the entire test suite with proper exit code propagation and automatic cleanup of dependent services, use the following command:
docker compose -f docker-compose-test.yml up \
--build \
--abort-on-container-exit \
--exit-code-from api-tests
Command breakdown:
--build– Recompiles theapi-testsimage whenDockerfile.devor test requirements change--abort-on-container-exit– Stops all supporting containers (database, cache, etc.) immediately when the test container finishes--exit-code-from api-tests– Propagates pytest’s exit status to the shell, ensuring CI pipelines correctly detect failures
Running Specific Test Subsets
You can override the default pytest command to run specific markers, directories, or individual files using docker compose run.
Run only unit tests:
docker compose -f docker-compose-test.yml run --rm --build api-tests pytest -m unit
Run a specific test directory with verbose output:
docker compose -f docker-compose-test.yml run --rm api-tests \
pytest plane/tests/unit/models/ -vv
Run a single test file:
docker compose -f docker-compose-test.yml run --rm api-tests \
pytest plane/tests/unit/models/test_workspace.py -vv
Test Configuration and Markers
Test categorization is controlled by apps/api/pytest.ini, which defines markers used to filter test runs:
unit– Fast, isolated unit testscontract– API contract validation testssmoke– Critical path smoke testsslow– Long-running integration tests
The api-tests service automatically sets DJANGO_SETTINGS_MODULE=plane.settings.test via environment variables defined in docker-compose-test.yml (lines 10-20). This ensures the Django configuration points to the temporary PostgreSQL and Redis instances rather than production endpoints.
Cleanup and Teardown
After test execution, remove the temporary volumes and network to ensure a clean slate for subsequent runs:
docker compose -f docker-compose-test.yml down -v
The -v flag deletes named volumes containing test data, preventing state leakage between test sessions.
Summary
- Containerized execution – API tests run inside Docker via
docker-compose-test.yml, eliminating local dependency conflicts - Ephemeral infrastructure – PostgreSQL, Valkey, RabbitMQ, and MinIO containers are created fresh for each test run
- Setup requirement – Always run
./setup.shfirst to generate required.envfiles from templates - Flexible filtering – Use pytest markers (
-m unit,-m contract) or file paths to run specific subsets - Clean teardown – Execute
docker compose -f docker-compose-test.yml down -vto remove test artifacts
Frequently Asked Questions
How do I debug a failing test in the Plane backend?
Use docker compose run with the --rm flag to access an interactive shell. You can override the command to enter a bash session inside the test container, then manually invoke pytest with --pdb to drop into the debugger when failures occur.
Can I run API tests without Docker?
The Plane backend test suite is designed specifically for Docker execution as defined in docker-compose-test.yml. While theoretically possible to run pytest locally against manually provisioned services, the official RUNNING_TESTS.md documentation only supports the containerized approach to ensure environment consistency.
Where are the test fixtures and utilities defined?
Shared test fixtures, including api_client and create_user, are documented in apps/api/plane/tests/TESTING_GUIDE.md. These utilities handle authentication, database setup, and mock object creation for the Django test environment.
Why does the test suite use Valkey instead of Redis?
The test-redis service uses valkey/valkey:7.2.11-alpine, an open-source Redis fork. This provides Redis-compatible caching and queue functionality while aligning with the project's open-source licensing requirements. The connection strings in plane.settings.test point to this Valkey instance automatically.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →