Testing¶
Coverage requirements¶
Both backend and web UI enforce 85% minimum coverage.
Backend¶
# Run all tests with coverage
uv run pytest tests/ -v
# Run specific test
uv run pytest -k "test_create_session" -v
# Verbose with short tracebacks
uv run pytest tests/ -v --tb=short
Rules¶
- Use
pytestwithpytest-asyncio - Zero warnings — all pytest warnings must be resolved
- Test against ports (interfaces), not adapters
- Mock infrastructure in tests
- Use fixtures for common setup
- No Docker for database tests — use mocking/patching
Test structure¶
tests/
├── conftest.py # Shared fixtures
├── test_services/ # Domain service tests
├── test_adapters/ # Adapter unit tests
└── test_routes/ # REST endpoint tests
Configuration¶
Coverage is configured in pyproject.toml:
[tool.pytest.ini_options]
testpaths = ["tests"]
asyncio_mode = "auto"
addopts = "--cov=src/volundr --cov-report=term-missing --cov-fail-under=85"
[tool.coverage.run]
source = ["src/volundr"]
branch = true
Web UI¶
Rules¶
- Use
vitestwith@testing-library/react - Co-locate test files next to source (
Component.test.tsx) - Mock service ports in component tests
- Coverage thresholds: 85% on statements, branches, functions, lines
CI¶
The CI pipeline runs four jobs:
- Lint — ruff check + format check
- Test — pytest with coverage, uploaded to Codecov
- Web Lint — ESLint + Prettier + TypeScript check
- Web Test — vitest with coverage, uploaded to Codecov
- Helm Lint — lint both Helm charts