bb-plane-fork/apiserver/plane/tests
Mohamed Hayballa 6000639921
feat(tests): Add comprehensive test suite for the Project API (#7252)
* feat(tests): Add reusable workspace fixture

Introduces a new `workspace` fixture in `conftest.py` to provide a
consistent and reusable setup for tests that require a workspace.

* feat(tests): Add tests for project creation (POST)

This commit introduces a comprehensive test suite for the project creation API endpoint.

The suite covers a wide range of scenarios, including:
- Successful creation and verification of side-effects (default states, project members, user properties).
- Validation for invalid or missing data (400 Bad Request).
- Permission checks for different user roles (e.g., guests are forbidden).
- Authentication requirements (401 Unauthorized).
- Uniqueness constraints for project names and identifiers (409 Conflict).
- Successful creation with all optional fields populated.

It leverages the `workspace`, `session_client` and `create_user` fixtures for a consistent test setup.

* refactor(tests): Centralize project URL helper into a base class

To avoid code duplication in upcoming tests, this commit introduces a `TestProjectBase` class.

The `get_project_url` helper method is moved into this shared base class, and the existing `TestProjectAPIPost` class is updated to inherit from it. This ensures the URL generation logic is defined in a single place and preparing the suite for the upcoming GET tests.

* feat(tests): Add tests for project listing and retrieval (GET)

This commit adds a suite for the GET method. It leverages the previously created `TestProjectBase` class for URL generation.

The new test suite covers:
- Listing projects:
  - Verifies that administrators see all projects.
  - Confirms guests only see projects they are members of.
  - Tests the separate detailed project list endpoint.
- Retrieving a single project:
  - Checks for successful retrieval of a project by its ID.
  - Handles edge cases for non-existent and archived projects (404 Not Found).
- Authentication:
  - Ensures authentication is required (401 Unauthorized).

* feat(tests): Add tests for project update (PATCH) and deletion (DELETE)

Key scenarios tested for PATCH:
- Successful partial updates by project administrators.
- Forbidden access for non-admin members (403).
- Conflict errors for duplicate names or identifiers on update (409).
- Validation errors for invalid data (400).

Key scenarios tested for DELETE:
- Successful deletion by both project admins and workspace admins.
- Forbidden access for non-admin members (403).
- Authentication checks for unauthenticated users (401).

* Remove unnecessary print statement

* refactor(tests): Update workspace fixture to use ORM

Updates the `workspace` fixture to create the model instance directly via the ORM using the `Workspace` model instead of the API, as requested during code review.

* Refactor: Remove some unused imports

Removes imports that I added while working on the test suite for the Project API but were ultimately not used. Note that other unused imports still exist from the state of the codebase when this branch was created/forked.
2025-07-03 00:40:42 +05:30
..
contract feat(tests): Add comprehensive test suite for the Project API (#7252) 2025-07-03 00:40:42 +05:30
smoke [WEB-3707] pytest based test suite for apiserver (#7010) 2025-05-26 15:26:26 +05:30
unit [WEB-4340] fix: duplicate assignees in user recents (#7216) 2025-06-18 15:14:21 +05:30
__init__.py [WEB-3707] pytest based test suite for apiserver (#7010) 2025-05-26 15:26:26 +05:30
apps.py build: merge frontend and backend into a single repo 2022-11-30 02:47:42 +05:30
conftest.py feat(tests): Add comprehensive test suite for the Project API (#7252) 2025-07-03 00:40:42 +05:30
conftest_external.py [WEB-3707] pytest based test suite for apiserver (#7010) 2025-05-26 15:26:26 +05:30
factories.py [WEB-3707] pytest based test suite for apiserver (#7010) 2025-05-26 15:26:26 +05:30
README.md [WEB-3707] pytest based test suite for apiserver (#7010) 2025-05-26 15:26:26 +05:30
TESTING_GUIDE.md [WEB-3707] pytest based test suite for apiserver (#7010) 2025-05-26 15:26:26 +05:30

Plane Tests

This directory contains tests for the Plane application. The tests are organized using pytest.

Test Structure

Tests are organized into the following categories:

  • Unit tests: Test individual functions or classes in isolation.
  • Contract tests: Test interactions between components and verify API contracts are fulfilled.
    • API tests: Test the external API endpoints (under /api/v1/).
    • App tests: Test the web application API endpoints (under /api/).
  • Smoke tests: Basic tests to verify that the application runs correctly.

API vs App Endpoints

Plane has two types of API endpoints:

  1. External API (plane.api):

    • Available at /api/v1/ endpoint
    • Uses API key authentication (X-Api-Key header)
    • Designed for external API contracts and third-party access
    • Tests use the api_key_client fixture for authentication
    • Test files are in contract/api/
  2. Web App API (plane.app):

    • Available at /api/ endpoint
    • Uses session-based authentication (CSRF disabled)
    • Designed for the web application frontend
    • Tests use the session_client fixture for authentication
    • Test files are in contract/app/

Running Tests

To run all tests:

python -m pytest

To run specific test categories:

# Run unit tests
python -m pytest plane/tests/unit/

# Run API contract tests
python -m pytest plane/tests/contract/api/

# Run App contract tests
python -m pytest plane/tests/contract/app/

# Run smoke tests
python -m pytest plane/tests/smoke/

For convenience, we also provide a helper script:

# Run all tests
./run_tests.py

# Run only unit tests
./run_tests.py -u

# Run contract tests with coverage report
./run_tests.py -c -o

# Run tests in parallel
./run_tests.py -p

Fixtures

The following fixtures are available for testing:

  • api_client: Unauthenticated API client
  • create_user: Creates a test user
  • api_token: API token for the test user
  • api_key_client: API client with API key authentication (for external API tests)
  • session_client: API client with session authentication (for app API tests)
  • plane_server: Live Django test server for HTTP-based smoke tests

Writing Tests

When writing tests, follow these guidelines:

  1. Place tests in the appropriate directory based on their type.
  2. Use the correct client fixture based on the API being tested:
    • For external API (/api/v1/), use api_key_client
    • For web app API (/api/), use session_client
    • For smoke tests with real HTTP, use plane_server
  3. Use the correct URL namespace when reverse-resolving URLs:
    • For external API, use reverse("api:endpoint_name")
    • For web app API, use reverse("endpoint_name")
  4. Add the @pytest.mark.django_db decorator to tests that interact with the database.
  5. Add the appropriate markers (@pytest.mark.contract, etc.) to categorize tests.

Test Fixtures

Common fixtures are defined in:

  • conftest.py: General fixtures for authentication, database access, etc.
  • conftest_external.py: Fixtures for external services (Redis, Elasticsearch, Celery, MongoDB)
  • factories.py: Test factories for easy model instance creation

Best Practices

When writing tests, follow these guidelines:

  1. Use pytest's assert syntax instead of Django's self.assert* methods.
  2. Add markers to categorize tests:
    @pytest.mark.unit
    @pytest.mark.contract
    @pytest.mark.smoke
    
  3. Use fixtures instead of setUp/tearDown methods for cleaner, more reusable test code.
  4. Mock external dependencies with the provided fixtures to avoid external service dependencies.
  5. Write focused tests that verify one specific behavior or edge case.
  6. Keep test files small and organized by logical components or endpoints.
  7. Target 90% code coverage for models, serializers, and business logic.

External Dependencies

Tests for components that interact with external services should:

  1. Use the mock_redis, mock_elasticsearch, mock_mongodb, and mock_celery fixtures for unit and most contract tests.
  2. For more comprehensive contract tests, use Docker-based test containers (optional).

Coverage Reports

Generate a coverage report with:

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

This creates an HTML report in the htmlcov/ directory.

Migration from Old Tests

Some tests are still in the old format in the api/ directory. These need to be migrated to the new contract test structure in the appropriate directories.