8. MVP Testing Strategy¶
Overview¶
Location: popupsim/backend/tests/
Status: 378 tests passing, 54% coverage
Test Organization¶
tests/
├── unit/ # 318 unit tests
│ ├── contexts/
│ │ ├── configuration/ # Config loading & validation
│ │ ├── retrofit_workflow/
│ │ │ ├── application/ # Coordinators, services
│ │ │ ├── domain/ # Domain services, aggregates
│ │ │ └── infrastructure/ # Resource managers
│ │ └── railway_infrastructure/
│ └── shared/ # Shared utilities
└── validation/ # 60 validation tests
├── test_retrofit_workflow_scenarios.py
├── test_layered_scenarios.py
├── test_layered_timelines.py
└── test_scenario_builder.py
Test Types¶
Unit Tests¶
Test individual components without external dependencies:
def test_batch_formation() -> None:
"""Test domain service."""
service = BatchFormationService()
wagons = [Wagon(...) for _ in range(5)]
assert service.can_form_batch(wagons, min_size=1, max_size=10)
Integration Tests¶
Test context interactions:
def test_configuration_loading() -> None:
"""Test file loading."""
builder = ConfigurationBuilder(Path("test_scenario"))
scenario = builder.build()
assert scenario.id == "test"
assert len(scenario.workshops) > 0
Simulation Tests¶
Test with SimPy:
def test_collection_coordinator() -> None:
"""Test coordinator with SimPy."""
env = simpy.Environment()
coordinator = CollectionCoordinator(...)
coordinator.start()
env.run(until=100)
assert len(coordinator.processed_batches) > 0
Running Tests¶
# All tests
uv run pytest
# Specific context
uv run pytest popupsim/backend/tests/unit/configuration/
# With coverage
uv run pytest --cov=popupsim/backend/src/
# Verbose
uv run pytest -v
Test Fixtures¶
File: tests/conftest.py
import pytest
from pathlib import Path
@pytest.fixture
def test_scenario_path() -> Path:
"""Path to test scenario."""
return Path("tests/fixtures/test_scenario")
@pytest.fixture
def sample_scenario() -> Scenario:
"""Sample scenario for testing."""
return Scenario(
id="test",
start_date=datetime(2025, 1, 1),
end_date=datetime(2025, 1, 2),
...
)
Coverage Goals¶
Current Coverage: 54.34% (exceeds 40% requirement)
Target Coverage by Component: - Domain services: > 90% (currently 85-98%) - Coordinators: > 80% (currently 70-88%) - Infrastructure: > 70% (currently 57-98%) - Overall: > 40% ✅ (currently 54%)
Quality Standards¶
All code must pass:
# Code formatting
uv run ruff format .
# Linting (0 errors required)
uv run ruff check .
# Type checking (0 errors required, strict mode)
uv run mypy popupsim/backend/src/
# Static analysis
uv run pylint popupsim/backend/src/
# All tests (378/378 passing required)
uv run pytest
# Run all checks
uv run ruff format . && uv run ruff check . && uv run mypy popupsim/backend/src/ && uv run pylint popupsim/backend/src/ && uv run pytest
MyPy Configuration:
[tool.mypy]
disallow_untyped_defs = true # All functions must have type hints
strict = true
Best Practices¶
✅ Do's¶
- Test domain logic without SimPy
- Use fixtures for common test data
- Test error cases
- Keep tests fast
- Include type hints in all test functions
- Use descriptive test names
❌ Don'ts¶
- Don't test external libraries
- Don't use real file I/O in unit tests
- Don't create complex test scenarios
- Don't skip type hints (mypy strict mode enforced)