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 database
  • test-redis – Valkey 7.2.11 Alpine (Redis-compatible) for caching and Celery broker
  • test-mq – RabbitMQ 3.13.6 with management UI for task queuing
  • test-minio – MinIO for S3-compatible object storage testing
  • api-tests – Custom image built from apps/api/Dockerfile.dev that 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 the api-tests image when Dockerfile.dev or 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 tests
  • contract – API contract validation tests
  • smoke – Critical path smoke tests
  • slow – 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.sh first to generate required .env files 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 -v to 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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →