The single canonical, always-current source for test counts and
coverage (per CLAUDE.md, quality-checks.md, and the developer
testing.md). Other docs reference this file instead of duplicating a
number that would drift.
Counts are collected with --collect-only (no run needed); coverage
percentages come from the CI coverage.yml night shift, not from a
local run (make test-coverage is heavy and thermally stressful, so it
is opt-in only). Re-measure with the commands in the last section.
| Level | Suite | Count | How measured (this session, v2.15.0) |
|---|---|---|---|
| Unit + integration | Backend (backend/tests) |
1858 | cd backend && poetry run pytest --collect-only -q |
| Unit + integration | Plugins (14 packages, sum below) | 1137 | per-plugin pytest --collect-only, backend's shared venv |
| Unit + component | Frontend (Vitest) | 10438 (988 files) | cd frontend && bunx vitest run (tail total, CI push run) |
| Grand total | measured this session | 13433 | 1858 + 1137 + 10438 |
E2E (Playwright smoke + Dexie-mode + visual) is separate from
make test and is not counted here; run cd e2e && npx playwright test.
| Plugin | Tests |
|---|---|
| assessment | 110 |
| session | 237 |
| tracking | 64 |
| tools | 58 |
| gamification | 69 |
| content-loader | 339 |
| anki | 20 |
| notebooklm | 27 |
| learning-repo | 53 |
| missions | 41 |
| ai-anthropic | 35 |
| ai-openai | 32 |
| ai-gemini | 34 |
| ai-perplexity | 18 |
| Total | 1137 |
The previous recorded baseline is the v2.14.0 snapshot
(history/2026-09-17-coverage.md). v2.15.0 added parametric
exercises, three extension types, the Settings reorganisation, the
compact lesson summary and the pytest path-isolation guard (#3145).
| Suite | Baseline (v2.14.0) | Current (v2.15.0) | Delta |
|---|---|---|---|
| Backend | 1824 | 1858 | +34 |
| Plugins | 1130 | 1137 | +7 |
| Frontend (Vitest) | 9775 | 10438 | +663 |
Coverage runs on CI (.github/workflows/coverage.yml, daily 03:00 UTC
workflow_dispatch), NOT as part of the local workflow. Pull the latest HTML +coverage.xmlreports without a local run:
gh run download --name backend-coverage
gh run download --name frontend-coverage
gh run download --name adaptive-learner-plugin-gamification-coverage # etc. per pluginTargets per module type live in quality-checks.md ("Coverage Targets
per Module Type"). Codecov is intentionally not wired up.
# Backend
cd backend && poetry run pytest --collect-only -q | tail -1
# Plugins (sum across all packages)
cd backend && for d in ../plugins/adaptive-learner-plugin-*/; do \
poetry run pytest "$d/tests" --collect-only -q 2>/dev/null | tail -1; done
# Frontend (Vitest) - runs the suite; take the "Tests N passed" total
cd frontend && bunx vitest run 2>&1 | grep -E "Tests +[0-9]+"Update this file when the counts move (this IS the canonical location -
do not copy the numbers elsewhere). Per test-coverage-audits.md, a
full audit additionally copies the previous version to
docs/audits/history/YYYY-MM-DD-coverage.md before overwriting.