4.3 KiB
Running the API Test Suite
This guide covers running the Django/pytest suite for apps/api inside Docker via docker-compose-test.yml at the repo root. The compose file boots an isolated stack — Postgres, Valkey (Redis), RabbitMQ, MinIO — with tmpfs-backed data dirs, so every run begins from a clean slate and a single teardown command removes everything.
For background on the test layout, markers, and fixtures, see TESTING_GUIDE.md and README.md.
Prerequisites
-
Docker and Docker Compose v2 (
docker compose ...) -
Env files generated via the setup script:
./setup.shThis copies
apps/api/.env.example→apps/api/.env(along with the other app env files). The compose file readsapps/api/.env, so this step must run before the firstdocker composeinvocation.
Running the suite
All commands are run from the repo root.
Full suite
docker compose -f docker-compose-test.yml up \
--build \
--abort-on-container-exit \
--exit-code-from api-tests
--buildrebuilds theapi-testsimage whenDockerfile.devorrequirements/*.txtchange.--abort-on-container-exitstops the dependency services as soon asapi-testsexits.--exit-code-from api-testspropagates pytest's exit code so this works in CI.
Filtered runs
Use docker compose run to override the default pytest command. Anything you pass after the service name is forwarded to pytest.
# Only unit tests (marker defined in pytest.ini)
docker compose -f docker-compose-test.yml run --rm --build api-tests pytest -m unit
# A single directory, filtered by name
docker compose -f docker-compose-test.yml run --rm api-tests \
pytest plane/tests/unit -k "test_workspace"
# Single file with verbose output
docker compose -f docker-compose-test.yml run --rm api-tests \
pytest plane/tests/unit/models/test_workspace.py -vv
The available markers (unit, contract, smoke, slow) are declared in apps/api/pytest.ini.
Teardown
docker compose -f docker-compose-test.yml down -v
-v removes the ephemeral volumes and the test_env network. Because the data directories are tmpfs, no host state survives a teardown — every run starts clean. Run this between unrelated test sessions to free Docker resources.
How it works
| Service | Image | Purpose |
|---|---|---|
test-db |
postgres:15.7-alpine |
Application database |
test-redis |
valkey/valkey:7.2.11-alpine |
Cache / Celery broker |
test-mq |
rabbitmq:3.13.6-management-alpine |
Task queue |
test-minio |
minio/minio |
S3-compatible object storage |
api-tests |
built from apps/api/Dockerfile.dev |
Installs requirements/test.txt, runs pytest |
All four dependencies expose health checks; api-tests waits for service_healthy on each via depends_on, so pytest only starts once the stack is ready.
Test-time env overrides live in the compose file itself (POSTGRES_HOST=test-db, REDIS_URL=redis://test-redis:6379/, AWS_S3_ENDPOINT_URL=http://test-minio:9000, DJANGO_SETTINGS_MODULE=plane.settings.test). Everything else is inherited from apps/api/.env.
Troubleshooting
./apps/api/.env: no such file or directory— run./setup.shfrom the repo root.- Port already in use — none of the test services publish host ports; if you see this it's coming from a different compose stack. Stop the local stack (
docker compose -f docker-compose-local.yml down). - Stale image after dependency changes — rebuild explicitly:
docker compose -f docker-compose-test.yml build --no-cache api-tests. - MinIO bucket missing — the
test-minioentrypoint creates the bucket named byAWS_S3_BUCKET_NAME(defaultuploads). Change the value inapps/api/.envand re-run. - Database state leaking between runs — confirm you ran
down -v(not justdown). The tmpfs mounts are torn down with the container, but the network and any externally created volumes need-vto clear.