Skip to content

Testing

Suite Where Run locally
Backend (pytest, ~11k tests) backend/tests/ cd backend && uv run pytest tests/ -n logical
Root supply-chain contracts tests/supply_chain/ uv run --project backend --no-sync pytest tests/supply_chain/
Frontend (Vitest via Analog) frontend/ai.client/src/**/*.spec.ts cd frontend/ai.client && npm test
Infrastructure (jest) infrastructure/test/ cd infrastructure && npx jest
Load-test unit tests tests/load/tests/ cd tests/load && uv run pytest tests/
Operational scripts scripts/restore-data/test_restore.py cd scripts/restore-data && uv run --frozen pytest test_restore.py

The backend suite is hermetic: a conftest guard fails any test that opens a socket to a non-local host, so a partially mocked test cannot quietly reach AWS. Run it with -n logical rather than -n auto; with psutil installed, auto counts physical cores and starts half as many workers as the machine has.

.github/workflows/ci.yml runs on every pull request into develop or main, but it does not run every suite every time. A changes job reads the PR’s file list and maps each path to the suites that can observe it (scripts/ci/classify-changes.sh):

Changed paths Suites
docs/, docs-site/, tui/, root markdown, LICENSE none
backend/ backend, load-test unit
backend/scripts/ backend, load-test unit, infrastructure (jest asserts the backfill scripts exist)
frontend/ frontend, frontend under --coverage
infrastructure/, RELEASE_NOTES.md infrastructure, plus the backend supply-chain and architecture suites that read the CDK tree
.claude/ infrastructure (one jest test reads the release skill)
tests/load/ load-test unit
.github/, scripts/, anything unrecognised everything

The mapping is fail-open. A new top-level directory, an empty file list, or a workflow_dispatch run turns every suite on; only the explicit list in the first row turns none on. The rules are pinned by backend/tests/supply_chain/test_ci_path_filter.py, so extend the script and the test together.

The deploy workflows (backend.yml, platform.yml, frontend-deploy.yml) are unaffected: on push to develop and main they still run their full suites before deploying, so the PR gate is the first line, not the last.