Files
scheduler/tests
jpmschweitzer 6915be31ca fix(tests): match postgres_host assertion to the fixture actually in effect
tests/conftest.py sets os.environ["POSTGRES_HOST"] = "postgres-shared" at
module level (before `from src.main import app`), commented "Use real
postgres for integration tests". test_settings_loads_from_environment
asserted settings.postgres_host == "test-postgres", a value grep confirms
nothing in this suite has ever set — git log -p shows both the conftest
line and this assertion originate in the same single commit and neither has
changed since. Matched the assertion to the environment the suite actually
runs under.

Not a source change and not a claim that "postgres-shared" is the right
fixture value for a suite this ticket also found is not actually hermetic
where that value is concerned (see the 12 pre-existing DNS errors, tracked
separately from this fix) — only that the assertion should test what the
fixture sets, not an unset value.
2026-08-18 15:50:45 +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