Testing
Run the smallest test selection that exercises the behavior you changed. A
path filter lets Vitest skip unrelated test files; -t filters tests only
after it has loaded the file. Keep pure unit tests separate from app-boot,
network, browser, Redis, and database tests so a focused check remains
deterministic and quick.
| Area | Focused command |
|---|---|
| API route or helper | pnpm --filter api exec vitest run src/routes/<site> |
| API middleware or job | pnpm --filter api exec vitest run src/middlewares/<file>.test.ts |
| Worker parser or adapter | cd apps/worker && uv run pytest tests/test_<site>_parsers.py -q -p no:randomly |
| Worker focused case | cd apps/worker && uv run pytest tests/test_<area>.py -q -p no:randomly |
| Product web tools | pnpm --filter toolzerhub exec vitest run src/features/tools |
| Product web feature | pnpm --filter toolzerhub exec vitest run src/features/dashboard/<area> |
| Docs web library | pnpm exec tsx --test apps/web/toolzerhub-docs/lib/<file>.test.ts |
| Shared package | pnpm --filter @thenetaji/packages exec tsx --test <area>/<file>.test.ts |
Keep existing test commands as each service's established CI entry point.
Use a native path filter locally; do not add wrapper scripts unless the runner
cannot express the scope.
For API migration wiring, run src/routes/legacy-alias-routing.test.ts and
scripts/openapi-spec-drift.test.ts explicitly with --maxWorkers=1. These
boot the full application. Family contract and validation tests should mount
their local routers with the global error handler and validate test environment
defaults, so choosing one family does not repeatedly boot unrelated services.
apps/web/toolzerhub-docs is a standalone pnpm project and its tests import
node:test; run its TypeScript files through the root tsx executable with
an explicit path. Do not target it with a workspace filter.
Write tests around a caller-visible result, a durable contract, or a known regression. A static check is appropriate when starting the real dependency is outside the test boundary and the check guards a concrete wiring or cross-service contract. Delete or rewrite a test that only repeats internal control flow, exact source spelling, or an implementation detail without a user, operator, or compatibility consequence. Keep a small negative case when it proves a custom checker would catch the failure it was created for.
Arrange the inputs, exercise the public boundary, and assert an independently chosen result. Cover the failure paths that matter as well as success. Mock external dependencies instead of the behavior under test; keep tests isolated and repeatable. Before adding a case, name the plausible bug it would catch. Do not derive the expected result by repeating the implementation's calculation.
The calculator catalog follows this rule: src/features/tools/index.test.ts
validates every registered manifest and runs every tool with defaults; each
tool's manifest.test.ts contains only its independently derived results and
meaningful edge cases.
The test-pruning ledger records the current audit and validation output.
Sources
- Google Testing Blog: Test Behavior, Not Implementation
- Google Testing Blog: Test Sizes
- Google Testing Blog: Change-Detector Tests
- Ham Vocke: The Practical Test Pyramid
- Vitest: Filtering
- pytest: Marking test functions