Testing
Each test covers product behaviour, a security rule, an HTTP contract, or database behaviour. Its name states what failure it catches, and it runs at the lowest layer that can prove the result.
| Layer | Use |
|---|---|
| Unit | Parsing, mapping, scoring, state transitions, cache policy, and time boundaries |
| Ktor route | Production authentication, decoding, statuses, headers, safe errors, and rejected-call side effects |
| PostgreSQL integration | Locks, cascades, atomic replacement, concurrent sessions, cleanup, and claim recovery |
| OpenAPI contract | Route inventory, exact schemas, statuses, headers, operation IDs, and security requirements |
| Frontend adapter | Bounded transport, malformed responses, request IDs, and wire-to-model mapping |
| Component and Storybook | Rendering states, validation, focus, keyboard interaction, and accessibility |
| Browser workflow | Navigation, SSR, hydration, responsive workspaces, and cross-tab behaviour |
| Live integration | A+, Mailpit, manual callbacks, archive streaming, and role boundaries |
Tests use fixed clocks and deterministic fixture data. PostgreSQL concurrency tests use the real database engine. Browser cases wait for observable state instead of fixed sleeps. Mocks replace external boundaries, not the route, service, component, or reducer under test.
Run the repository gate from the root:
scripts/verify.shThe release gate also runs:
scripts/smoke-backend-container.sh --no-cachescripts/smoke-frontend-container.sh --no-cache(cd frontend && bun audit --prod)(cd frontend && bun run test:mutation)Mutation checks
Section titled “Mutation checks”bun run test:mutation runs a focused
StrykerJS check over
the sign-in response parser, bounded HTTP reader, cross-origin request policy,
course-configuration validation and merge logic, and grade-publication outcome
mapping. The command runner executes the owning unit tests for each mutant and
fails below the configured floor. The floor describes only these selected pure
decision modules, not the application as a whole. The scheduled and release
workflow reports surviving mutations and writes a local JSON report for
inspection.
JVM mutation testing is not a build gate. PIT supports Kotlin through the Arcmutate Kotlin plugin, which requires a licence file. That prevents the gate from running from the checked-in project and public dependencies alone. Kotlin security rules use boundary, table-driven, and failure-injection tests instead.
scripts/test-course.sh verify-live checks the deployed boundary of the
isolated Comprehensive Test Course. Test the ordinary Compose stack separately;
the fixture environment has different configuration and volumes.
Svelte test boundaries
Section titled “Svelte test boundaries”Use the official Svelte testing guidance
to choose a runner and render mode. Pure model and transformation tests run in
the unit project. Components that depend on browser layout, selection, focus,
observers, or hydration run in the Playwright-backed browser project. Tests
using runes outside a component use a .svelte.test.ts filename so the Svelte
compiler applies the same semantics as production code.
Remote-function tests cover input validation, owned result mapping, precise query updates, and service failures. Route tests cover SSR, load parallelism, cookies, redirects, and safe error mapping. The official remote-functions contract defines the browser export as a generated caller whose implementation runs on the server. Tests must exercise the relevant side of that boundary. Mocking the transformed function does not test transport.
quality/test-inventory.md covers Kotlin, Python, frontend, browser, Storybook,
documentation, Caddy, container, PostgreSQL, and benchmark verification. A
source is accepted only after its assertions and distinct failure modes have an
inspected rationale in the corresponding review file. Reviews store a digest of
the inspected source or test body, so adding or changing a case invalidates the
review. Record one inspected source at a time with
node scripts/test-inventory.mjs --write --review-source <path> --review-note "<what was verified>". The command requires fresh evidence and cannot refresh
the repository wholesale. bun run test:inventory rejects missing, stale, or
unresolved reviews, disabled tests, duplicate stable names, and exact duplicate
coverage at the same production boundary.