Skip to content

Unit Testing

s# Unit Testing Guide

This guide explains how to run and write unit tests for the Tracker REST API.

Overview

The Tracker REST API uses pytest for unit testing. The tests are located in the tests directory and are organized as follows:

  • tests/conftest.py: Contains pytest fixtures used by the tests
  • tests/models.py: Contains SQLite-compatible models for testing
  • tests/test_main.py: Tests for the main application
  • tests/api/routes/: Tests for API routes

Running Tests

You can run tests either locally or in the Docker container.

Running Tests Locally

To run the tests locally, use the following command:

python -m pytest

To run a specific test file:

python -m pytest tests/test_main.py

To run tests with verbose output:

python -m pytest -v

Using Docker

To run the tests in the Docker container, use the following command:

docker exec tracker-restapi-dev-1 python -m pytest

To run a specific test file:

docker exec tracker-restapi-dev-1 python -m pytest tests/test_main.py

To run tests with verbose output:

docker exec tracker-restapi-dev-1 python -m pytest -v

Using the Docker Test Runner

We've created a custom test runner script that integrates with VSCode to run tests in the Docker container.

You can use the Docker test runner script directly:

.vscode/docker_test_runner.py tests/test_main.py

Or to run all tests:

.vscode/docker_test_runner.py tests

Using VSCode

You can run tests directly from VSCode using the integrated test explorer or the provided launch configurations. Our setup includes custom test runners that allow VSCode to run tests either locally or in the Docker container.

Using the Test Explorer

  1. Open the Test Explorer view by clicking on the flask icon in the sidebar
  2. You should see all the tests discovered in your project
  3. Click on the play button next to a test to run it
  4. You can also run all tests by clicking the play button at the top of the Test Explorer

The tests will run locally, and the results will be displayed in the Test Explorer.

Using Launch Configurations

  1. Open the test file you want to run
  2. Click on the "Run and Debug" icon in the sidebar
  3. Select one of the following configurations from the dropdown:
  4. "Python: Debug Tests" - Runs the current test file in the Docker container
  5. "Python: Debug All Tests" - Runs all tests in the Docker container
  6. "Python: Debug Tests in Docker" - Runs the current test file in the Docker container
  7. "Python: Debug Tests Locally" - Runs the current test file locally
  8. "Python: Debug All Tests Locally" - Runs all tests locally
  9. Click the green play button

Using Tasks

You can also run tests using the defined tasks:

  1. Press Ctrl+Shift+P (or Cmd+Shift+P on macOS) to open the command palette
  2. Type "Tasks: Run Task" and select it
  3. Choose one of the following tasks:
  4. "Run pytest in Docker" - Runs the current test file in the Docker container
  5. "Run all pytest in Docker" - Runs all tests in the Docker container
  6. "Run pytest locally" - Runs the current test file locally
  7. "Run all pytest locally" - Runs all tests locally

How It Works

Our VSCode integration uses custom test runner scripts that:

  1. Execute pytest either locally or in the Docker container
  2. Pass the appropriate test file or directory
  3. Display the results in VSCode

This allows you to use VSCode's test explorer and debugging features while running tests either locally or in the Docker container.

Test Database

The tests use SQLite as the database backend instead of PostgreSQL. This makes the tests faster and easier to run without requiring a PostgreSQL server.

The test database is created and destroyed for each test function, ensuring that tests don't interfere with each other.

SQLite Compatibility

Since the application uses PostgreSQL-specific features like the geography type, we need to use SQLite-compatible models for testing. These models are defined in tests/models.py.

Test Fixtures

The test fixtures are defined in tests/conftest.py. These fixtures provide the test environment and test data for the tests.

Key Fixtures

  • db: Provides a fresh database session for each test
  • app: Creates a FastAPI test application
  • client: Creates a TestClient for making HTTP requests to the API
  • admin_user: Creates an admin user for testing
  • regular_user: Creates a regular user for testing
  • admin_token and user_token: Create authentication tokens for the admin and regular users
  • admin_headers and user_headers: Create headers with authentication tokens for making authenticated requests
  • test_client: Creates a test client (organization)
  • test_brand: Creates a test brand
  • test_production_run: Creates a test production run
  • test_tracker: Creates a test tracker

Writing Tests

When writing tests, follow these guidelines:

  1. Use the provided fixtures to set up the test environment
  2. Test both successful and error cases
  3. Test with both admin and regular users to ensure proper authorization
  4. Use descriptive test names and docstrings

Example Test

def test_read_trackers(client: TestClient, admin_headers: dict, test_tracker: Tracker) -> None:
    """
    Test retrieving a list of trackers.
    """
    response = client.get("/api/v1/trackers/", headers=admin_headers)
    assert response.status_code == 200

    data = response.json()
    assert "items" in data
    assert "total" in data
    assert data["total"] >= 1

Client Filtering

The API uses client filtering to restrict access to data based on the user's client list. In the tests, we set up the admin and regular users with access to the test client, so they can access the test data.

Debugging Tests

If a test is failing, you can use the VSCode debugger to step through the test and see what's happening. Set breakpoints in the test file or in the application code to see the values of variables at different points in the execution.

Test Coverage

To run tests with coverage reporting:

docker exec tracker-restapi-dev-1 python -m pytest --cov=app

This will show the test coverage for the app directory.

Continuous Integration

The tests are run automatically in the CI/CD pipeline. If a test fails in the pipeline, it will prevent the code from being deployed.