Files
scheduler/tests
jpmschweitzerandClaude 7b80e30691 feat(executors): add docker prune executor
Non-interactive equivalent of system-admin-toj's prune-docker.sh, which
prompts per stage and so cannot run from cron.

Only the stages that discard regenerable data run by default: build
cache and dangling images. Unused images and volumes are opt-in, because
docker volume prune removes volumes belonging to merely-stopped
containers rather than only orphaned ones, which on this host is a
plausible way to lose a database.

A failing stage is reported and the remaining stages still run, since a
partial reclaim beats none, but the task still ends up failed so the
error is not swallowed.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-08-08 11:00:42 +02:00
..

Scheduler Tests

Comprehensive test suite for The Scheduler using pytest.

Test Structure

tests/
├── conftest.py                    # Shared fixtures and configuration
├── test_api.py                    # API endpoint tests
├── test_example_executor.py       # Example executor tests
├── test_doc_sync_executor.py      # Documentation sync executor tests
└── README.md                      # This file

Running Tests

Run all tests

docker exec scheduler pytest

Run with coverage report

docker exec scheduler pytest --cov=src --cov-report=term-missing

Run specific test file

docker exec scheduler pytest tests/test_api.py

Run specific test class

docker exec scheduler pytest tests/test_api.py::TestHealthEndpoint

Run specific test

docker exec scheduler pytest tests/test_api.py::TestHealthEndpoint::test_health_endpoint_returns_healthy

Run tests by marker

# Run only unit tests
docker exec scheduler pytest -m unit

# Run only API tests
docker exec scheduler pytest -m api

# Run only executor tests
docker exec scheduler pytest -m executor

# Run only fast tests (exclude slow)
docker exec scheduler pytest -m "not slow"

Run with verbose output

docker exec scheduler pytest -v

Run with detailed failure output

docker exec scheduler pytest -vv --tb=long

Stop on first failure

docker exec scheduler pytest -x

Test Markers

Tests are organized with pytest markers:

  • @pytest.mark.unit - Fast unit tests with no external dependencies
  • @pytest.mark.integration - Integration tests (may use database)
  • @pytest.mark.api - API endpoint tests
  • @pytest.mark.executor - Task executor tests
  • @pytest.mark.slow - Tests that take a while to run

Coverage Reports

After running tests with coverage:

  • Terminal: Shows missing lines in terminal output
  • HTML: Open htmlcov/index.html in browser for detailed report
  • JSON: Machine-readable coverage data in coverage.json

View HTML coverage report:

# From host machine
open /home/jpmschweitzer/docker-data/scheduler/htmlcov/index.html

Writing New Tests

Test File Naming

  • Test files must start with test_
  • Place in tests/ directory
  • Use descriptive names: test_<module_name>.py

Test Function Naming

  • Test functions must start with test_
  • Use descriptive names: test_<what_is_being_tested>

Using Fixtures

Fixtures are defined in conftest.py:

def test_something(test_settings, auth_headers):
    # Use fixtures as function parameters
    assert test_settings.app_name == "Test Scheduler"

Adding Markers

@pytest.mark.unit
@pytest.mark.api
def test_health_endpoint(client):
    response = client.get("/health")
    assert response.status_code == 200

Async Tests

@pytest.mark.asyncio
async def test_async_function():
    result = await some_async_function()
    assert result is not None

Mocking

from unittest.mock import patch, MagicMock

def test_with_mock():
    with patch('module.function') as mock_func:
        mock_func.return_value = "mocked"
        result = call_function_that_uses_it()
        assert result == "mocked"

Continuous Integration

These tests are designed to run in CI pipelines:

# Example GitHub Actions
- name: Run tests
  run: |
    docker exec scheduler pytest --cov=src --cov-report=xml
    docker exec scheduler pytest --cov=src --cov-report=html

Test Database

Tests use mocked database connections by default. For integration tests that require a real database:

  1. Set up a test database
  2. Use POSTGRES_DB=test_scheduler environment variable
  3. Run migrations before tests
  4. Clean up after tests

Troubleshooting

Tests fail with "ModuleNotFoundError"

# Install test dependencies
docker exec scheduler /venv/bin/pip install -r requirements.txt

Tests fail with database errors

  • Tests use mocked connections by default
  • Check that mocks are properly set up in conftest.py
  • For integration tests, ensure test database exists

Coverage not working

# Reinstall pytest-cov
docker exec scheduler /venv/bin/pip install --upgrade pytest-cov

Best Practices

  1. Fast by default: Unit tests should be fast (<1s each)
  2. Isolated: Tests should not depend on each other
  3. Descriptive: Test names should clearly describe what they test
  4. Single assertion: Test one thing per test when possible
  5. Use fixtures: Reuse common setup via fixtures
  6. Mock external deps: Don't hit real databases/APIs in unit tests
  7. Mark appropriately: Use markers to categorize tests

Current Coverage

Run this to see current coverage:

docker exec scheduler pytest --cov=src --cov-report=term

Target: 80%+ code coverage for critical paths