Test Audit CLI
Reference for the trovella-test-audit CLI tool -- coverage aggregation, source-to-test mapping, and mutation testing across the monorepo.
trovella-test-audit is a custom CLI tool at tools/test-audit/ that provides quantitative test quality analysis across the monorepo. It is a private npm package (@repo/test-audit) invoked via pnpm test-audit <command>.
Commands
coverage -- Aggregate Coverage
Runs pnpm turbo test:coverage with scope filters, then collects coverage-final.json files from each package's coverage/ directory. Uses istanbul-lib-coverage to merge all per-package data into a unified coverage map.
# Full monorepo coverage
pnpm test-audit coverage .
# Single package
pnpm test-audit coverage packages/ai
# Subdirectory within a package
pnpm test-audit coverage packages/mcp/src/plan-engine/
# Human-readable output
pnpm test-audit coverage packages/ai --human
Output includes:
- Per-file line, branch, function, and statement percentages
- Uncovered line ranges for each file
- Source files with zero coverage
- List of all test files in scope
- Files sorted by number of uncovered lines (worst gaps first)
report -- Full Coverage Context
Semantic alias for coverage that always includes the full context (uncovered files, test file list). Used by the /test-review skill to gather comprehensive coverage data.
pnpm test-audit report packages/mcp --human
map -- Source-to-Test Mapping
Runs each test file in isolation with its own coverage pass, then builds an inverted index mapping source code lines to the test files that cover them.
pnpm test-audit map packages/ai --human
Answers the question: "Which test files cover this function?"
Output includes:
- Per-function mapping to test files
- Uncovered functions (zero test coverage across all test files)
- Single-test coverage warnings -- lines covered by exactly one test file, representing fragile coverage
The /test-write skill uses this command for context efficiency: instead of reading all test files in a package, it reads only the test files that cover the code being modified.
mutate -- Mutation Testing
Runs StrykerJS mutation testing against the specified scope. StrykerJS systematically modifies source code (changing > to >=, removing function calls, flipping booleans) and reruns tests. If tests fail after a mutation, the mutation is "killed" -- tests caught the change. If all tests still pass, the mutation "survived" -- tests missed the change.
# Run mutation testing for a package
pnpm test-audit mutate packages/ai
# Human-readable output
pnpm test-audit mutate packages/search --human
Output includes:
- Mutation score -- percentage of non-equivalent mutants killed
- Counts by status -- killed, survived, timeout, no coverage
- Surviving mutant details -- file, line, operator type, replacement value
- Per-test-file breakdown -- how many mutants each test file killed
StrykerJS configuration:
| Setting | Value | Rationale |
|---|---|---|
| Thresholds | high: 80, low: 60, break: null | Informational, not blocking |
| Concurrency | floor(cpus / 2) | Leave headroom for other work |
| Incremental mode | Enabled | Cache results for changed files only |
| TypeScript checker | Enabled | Skip mutations that produce compile errors |
pnpm Symlink Workaround
StrykerJS spawns worker processes that need @stryker-mutator/* packages in the target package's node_modules. Under pnpm strict isolation, these packages only exist in the tools/test-audit workspace. The tool creates temporary junction symlinks before running StrykerJS and cleans them up afterward. This is fragile -- a pnpm major version upgrade could break the symlink paths.
Scope Resolution
All commands accept a scope argument that resolves to one or more Turborepo filter flags:
| Input | Resolves To |
|---|---|
. | Entire monorepo (no filter) |
packages/ai | --filter=@repo/ai |
packages/mcp/src/plan-engine/ | --filter=@repo/mcp (walks up to find package.json) |
The resolver (resolve-scope.ts) walks up from the given path to find the nearest package.json, reads the name field, and constructs the Turborepo filter flag.
Output Formats
All commands default to JSON output designed for programmatic consumption by Claude Code skills. Add --human for terminal-readable formatted output.
# JSON (for skills)
pnpm test-audit coverage packages/ai
# Formatted (for humans)
pnpm test-audit coverage packages/ai --human
Integration with AI Skills
The CLI tool is the data source for both /test-write and /test-review:
| Skill | Commands Used | Purpose |
|---|---|---|
/test-write | map, mutate | Read only relevant test files; verify test quality via mutation score |
/test-review | report, mutate | Score coverage and mutation resilience dimensions with real data |
When the CLI tool is unavailable (e.g., tool failure or timeout), /test-review adjusts confidence levels downward but still produces findings based on AI analysis of the source and test code.