How to Run Tests in the makeplane/plane Repository: Complete Guide

The makeplane/plane repository ships with a comprehensive pytest-based test suite that validates Django backend services through three distinct layers—unit, contract, and smoke tests—executable via standard pytest commands or the apps/api/run_tests.py helper script.

The Plane open-source project maintains a robust testing infrastructure located under apps/api/plane/tests/ that supports local execution without requiring external containers like Redis or Elasticsearch. Because the suite relies on fixtures that mock external services, developers can run the full test matrix locally to validate API contracts and end-to-end workflows.

Test Suite Architecture

The Plane codebase organizes tests into three logical layers, each serving a specific validation purpose:

  • Unit tests isolate individual functions or model methods. These live in plane.tests.unit and use fixtures like create_user and api_token.
  • Contract tests verify public API contracts for both the external API (/api/v1/) and web-app API (/api/). These reside in plane.tests.contract.api and plane.tests.contract.app, utilizing api_key_client for API key authentication and session_client for session-based authentication.
  • Smoke tests spin up a real Django test server to perform end-to-end checks. These are found in plane.tests.smoke and rely on the plane_server live server fixture.

How to Run Tests in the makeplane/plane Repository

Running the Full Test Suite

To execute all test layers—unit, contract, and smoke—run the standard pytest command from the API directory:

python -m pytest

Alternatively, use the convenience wrapper script located at apps/api/run_tests.py:

./run_tests.py

Targeting Specific Test Layers

During development, you can isolate specific test categories by targeting their directory paths:


# Unit tests only

python -m pytest plane/tests/unit/

# External API contract tests

python -m pytest plane/tests/contract/api/

# Web-app (App) contract tests

python -m pytest plane/tests/contract/app/

# Smoke tests (live server)

python -m pytest plane/tests/smoke/

Using the run_tests.py Helper Script

The run_tests.py script in apps/api/ provides shorthand flags for common workflows:


# Run only unit tests

./run_tests.py -u

# Run contract tests with coverage report

./run_tests.py -c -o

# Execute tests in parallel (uses pytest-xdist)

./run_tests.py -p

Note: When using parallel execution (-p), ensure your machine has sufficient RAM, as pytest-xdist spawns multiple workers.

Generating Coverage Reports

To generate both terminal and HTML coverage reports, execute:

python -m pytest --cov=plane --cov-report=term --cov-report=html

The HTML report will be available in the htmlcov/ directory after execution.

Key Testing Concepts and Fixtures

Understanding the testing conventions in apps/api/plane/tests/ ensures accurate test implementation:

  • Authentication methods: External API tests require an X-Api-Key header provided by the api_key_client fixture, while web-app tests use Django session cookies via the session_client fixture.
  • URL reversing: Use reverse("api:endpoint_name") for external API endpoints and reverse("endpoint_name") for web-app endpoints.
  • Database access: Any test touching the database must include the @pytest.mark.django_db decorator.
  • External service mocking: Fixtures like mock_redis, mock_elasticsearch, and mock_celery prevent real network calls, keeping the suite deterministic and fast.

Example Test Implementation

Below is a practical example of a contract test using the API-key authenticated client:

import pytest
from django.urls import reverse

@pytest.mark.contract
@pytest.mark.django_db
def test_create_issue(api_key_client):
    url = reverse("api:issues-list")
    resp = api_key_client.post(url, {"name": "Test issue", "project": 1})
    assert resp.status_code == 201
    assert resp.json()["name"] == "Test issue"

Summary

  • The Plane repository uses pytest to organize tests into unit, contract, and smoke layers under apps/api/plane/tests/.
  • Execute tests using python -m pytest or the apps/api/run_tests.py helper script with flags like -u (unit), -c (contract), and -p (parallel).
  • The suite mocks external services (Redis, Elasticsearch, Celery) via fixtures defined in conftest.py and conftest_external.py, enabling local execution without containers.
  • Use api_key_client for external API authentication and session_client for web-app session authentication.
  • Generate coverage reports with --cov=plane flags to produce HTML output in htmlcov/.

Frequently Asked Questions

What is the difference between contract and smoke tests in Plane?

Contract tests verify the API schema and response formats for the external (/api/v1/) and web-app (/api/) interfaces using mocked dependencies, while smoke tests spin up an actual Django test server via the plane_server fixture to validate end-to-end workflows with real HTTP requests.

Can I run tests without installing Redis or Elasticsearch locally?

Yes. The test suite in makeplane/plane includes fixtures that mock Redis, Elasticsearch, and Celery (located in conftest_external.py), allowing the full test suite to run locally without external containers or services.

How do I authenticate API requests in Plane contract tests?

External API contract tests use the api_key_client fixture, which automatically injects an X-Api-Key header into requests. Web-app contract tests use the session_client fixture, which handles Django session cookie authentication for endpoints under the web-app namespace.

Where can I find more detailed documentation about Plane's testing strategy?

Reference the apps/api/plane/tests/README.md for an overview of test organization and apps/api/tests/RUNNING_TESTS.md for detailed execution instructions. Fixture definitions are located in apps/api/plane/tests/conftest.py and conftest_external.py.

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 →