Test health
Analyze the repository's current ability to detect important regressions, then
choose one bounded improvement slice that makes future changes safer. Optimize
for confidence and risk reduction—not test count, line coverage, or testing
activity.
A slice has one primary risk or behavior, one main seam or test level, and the
supporting setup and related scenarios needed to make the signal trustworthy.
It is intentionally larger than a token one-test change when the evidence calls
for it, but smaller than a broad testing campaign. This skill is a repository
assessment and incremental-improvement playbook. It is not a mandate to use
TDD everywhere, add tests for every file, migrate the testing stack, or make the
repository fully tested in one run.
Principles
Apply these principles directly:
- Treat coverage and test count as evidence, never as objectives. Do not set
arbitrary percentages or pursue 100% coverage by default.
- Prefer one coherent improvement slice per iteration: one risk area or
behavior boundary with enough supporting setup and related scenarios to make
it usable. Do not stop at an isolated test when a small companion check,
fixture, seam, or command is needed to close the same risk, but do not expand
into an independent risk area.
- Prioritize important, risky, frequently changed, or historically buggy
behavior over uncovered but unimportant lines.
- Test externally observable behavior through a stable interface or seam. Do
not add tests merely to exercise implementation details.
- Prefer the repository's existing runner, framework, fixtures, and naming
conventions when they are adequate. Introduce tooling only for a concrete,
evidenced need.
- Treat flaky, slow, or hard-to-run tests as a trust problem. Stabilizing a
valuable check can be more useful than adding another check.
- Use characterization tests when existing behavior is poorly understood. Use
regression tests for understood existing behavior. For genuinely new
behavior, prefer a small red → green → refactor loop at one observable seam
when it helps; strict retroactive TDD is not required.
- If architecture prevents meaningful testing, create only the smallest useful
seam. Do not broadly refactor toward a preferred architecture or mock every
dependency just to test one class.
- Be willing to conclude Good enough for now when additional testing has
low marginal value.
Workflow
Follow this sequence. Gather evidence before choosing a recommendation.
Understand the repository. Read repository instructions, the README,
manifests, build/workspace configuration, architecture notes, and relevant
documentation. Detect languages, frameworks, package managers, entrypoints,
and monorepo boundaries. Do not assume a particular ecosystem.
Inventory testing infrastructure. Locate test directories and naming
conventions, test configuration, fixtures/fakes/mocks/snapshots, coverage
configuration or reports, and CI configuration. Determine which test
commands are actually documented or encoded in manifests, task runners, and
CI. A dependency named test is not proof that a runnable suite exists.
Collect deterministic evidence. When command execution is available,
run the portable helper bundled with this skill:
python3 path/to/test-health/scripts/inspect_test_health.py --root . --pretty
It reports evidence only; it does not decide maturity or recommend work.
If it cannot run, perform the same inspection manually and lower confidence
rather than inventing results.
Run the smallest relevant existing checks. Inspect commands before
executing them. Run a focused test command when one exists, then a broader
existing suite when scope and time justify it. Also run relevant lint,
typecheck, build, or packaging checks when the repository normally uses
them. Report each as passed, failed, skipped, or unavailable. Never claim a
command ran from configuration alone.
Inspect CI. Establish whether tests run automatically, which command CI
uses, whether only a narrow subset runs, and whether failures are visible.
Sample real tests. Read a representative few—not every test file—across
the relevant levels and risk areas. Assess behavior assertions, seams,
mocks, isolation, readability, speed, flakiness, and maintainability.
Identify risk. Find important behavior and change paths: domain rules,
user journeys, public interfaces, persistence, permissions, destructive
operations, external integrations, error handling, and high-churn areas.
Use history when available; if it is unavailable, say so.
Assess health qualitatively. Use one of: No safety net,
Foothold, Partial safety net, Reliable safety net, or
Strong enough. Base the state on executability, risk coverage, test
quality, reliability, test-level fit, architectural testability, and change
protection—not on a numeric score.
Choose one bounded improvement slice. Compare candidate slices by risk
reduced, confidence gained, implementation effort, maintenance cost,
architectural prerequisites, and feedback speed. Select one primary behavior
or risk at one seam/test level, then include only the directly enabling work
and closely related scenarios needed to make that slice trustworthy. A slice
may include a small cluster of tests, fixture or runner setup, a minimal
seam, or focused CI wiring; it is larger than an isolated test when the
evidence calls for it, but smaller than a broad testing campaign. Define
what is explicitly out of scope before implementation.
Stop at the slice boundary. Finish when the primary risk has the
planned behavioral evidence and the relevant checks pass. Defer a second
independent risk, even if it appears nearby. Keep later ideas to at most
three brief, ordered follow-ups. Do not add tests solely to inflate metrics,
introduce a second framework without a concrete reason, favor E2E merely
because it is realistic, or favor unit tests merely because they are fast.
For detailed guidance, load only what is needed:
- Maturity and evidence
- Prioritization and bounded slice selection
- Test quality and test-level fit
- Ecosystem detection
- Final report format
Decision rules
Use repository evidence to choose among these common cases:
- A meaningful seam exists: protect the primary behavior through it. Include
the key success, failure, or boundary outcomes that belong to the same risk;
do not refactor for testability merely because another design would be easier
to test.
- Behavior is poorly understood: characterize a meaningful current slice
before changing it. Do not silently replace undocumented behavior with an
imagined ideal.
- Setup requires excessive mocking or invasive manipulation: identify the
one dependency or boundary that blocks useful observation and expose the
smallest seam there, then add the related behavioral checks needed to prove
that seam. Avoid broad dependency-injection, repository-pattern, or
architecture migrations.
- No testing infrastructure exists: establish a minimum foothold using the
ecosystem's natural tool, one clear command, and a small representative
behavioral slice. Include enough scenarios to exercise the important branch
or boundary; do not create a complete unit/integration/E2E stack.
- The suite is flaky, unreliable, or painfully slow: restore trust in the
highest-value feedback, including adjacent setup or guard checks when they
are part of the same failure, before increasing suite size.
- CI does not run valuable local tests: wire the existing focused command
into the normal change path and make its failure visible; do not introduce a
new framework or rebuild the whole pipeline in the same iteration.
- Testing is already strong: say Good enough for now unless a specific
additional slice clearly justifies its cost.
Do not equate a passing suite with meaningful protection, a large suite with
maturity, or high coverage with quality. Do not write tests for every source
file merely because it exists, target a coverage number, use snapshots as a
cheap coverage mechanism, or broadly refactor unprotected code just for
idealized testability. A few related scenarios that close one risk are part of
one manageable slice; unrelated gaps belong in later iterations.
Implementation mode
If the user asks to implement the recommendation, first confirm the existing
conventions and implement only that bounded slice. The slice may include a
minimal seam, fixture/helper, focused command or CI wiring, and a small related
set of tests when those pieces are inseparable from the observable boundary.
Keep the change behavior-focused and avoid unrelated cleanup.
After implementation:
- Run the new or changed tests and verify the planned scenarios freshly.
- Run the relevant broader suite and normal lint, typecheck, build, or
packaging checks when reasonably practical.
- Confirm the intended behavior is protected at the selected seam. When
useful, demonstrate that the tests fail if the protected behavior is
intentionally broken; do not claim this if it was not checked.
- Reassess the affected risk, confirm the slice stayed within its boundary,
and report the actual commands and results.
- Recommend no more than three short, ordered follow-ups, or say Good enough
for now. Do not turn follow-ups into an unbounded backlog.
Default report
Use the concise structure in report-format.md:
# Testing health
**State:** [state]
**Confidence:** [Low | Medium | High]
## What I found
## Biggest current risk
## Recommended iteration
**Primary risk or behavior:**
**Seam and test level:**
**Bounded slice:**
**Explicitly out of scope:**
## Why this first
## Done when
## Later
Include facts, commands, and observed results. If execution was unavailable,
say what was inferred from configuration or CI and lower confidence. Never turn
an unavailable check into a pass.
1---2name: test-health3description: Audit a repository's automated testing health and recommend a bounded, high-value next improvement slice. Use when assessing an existing test suite, introducing tests into an untested or legacy project, deciding what to test next, evaluating testing strategy or coverage, choosing between unit, integration, and end-to-end tests, investigating brittle or flaky tests, or determining whether a small architecture change is needed for testability. Detect and prefer the repository's existing stack and conventions. Improve testing incrementally rather than pursuing arbitrary coverage targets.4---56# Test health78Analyze the repository's current ability to detect important regressions, then9choose one bounded improvement slice that makes future changes safer. Optimize10for confidence and risk reduction—not test count, line coverage, or testing11activity.1213A slice has one primary risk or behavior, one main seam or test level, and the14supporting setup and related scenarios needed to make the signal trustworthy.15It is intentionally larger than a token one-test change when the evidence calls16for it, but smaller than a broad testing campaign. This skill is a repository17assessment and incremental-improvement playbook. It is not a mandate to use18TDD everywhere, add tests for every file, migrate the testing stack, or make the19repository fully tested in one run.2021## Principles2223Apply these principles directly:2425- Treat coverage and test count as evidence, never as objectives. Do not set26 arbitrary percentages or pursue 100% coverage by default.27- Prefer one coherent improvement slice per iteration: one risk area or28 behavior boundary with enough supporting setup and related scenarios to make29 it usable. Do not stop at an isolated test when a small companion check,30 fixture, seam, or command is needed to close the same risk, but do not expand31 into an independent risk area.32- Prioritize important, risky, frequently changed, or historically buggy33 behavior over uncovered but unimportant lines.34- Test externally observable behavior through a stable interface or seam. Do35 not add tests merely to exercise implementation details.36- Prefer the repository's existing runner, framework, fixtures, and naming37 conventions when they are adequate. Introduce tooling only for a concrete,38 evidenced need.39- Treat flaky, slow, or hard-to-run tests as a trust problem. Stabilizing a40 valuable check can be more useful than adding another check.41- Use characterization tests when existing behavior is poorly understood. Use42 regression tests for understood existing behavior. For genuinely new43 behavior, prefer a small red → green → refactor loop at one observable seam44 when it helps; strict retroactive TDD is not required.45- If architecture prevents meaningful testing, create only the smallest useful46 seam. Do not broadly refactor toward a preferred architecture or mock every47 dependency just to test one class.48- Be willing to conclude **Good enough for now** when additional testing has49 low marginal value.5051## Workflow5253Follow this sequence. Gather evidence before choosing a recommendation.54551. **Understand the repository.** Read repository instructions, the README,56 manifests, build/workspace configuration, architecture notes, and relevant57 documentation. Detect languages, frameworks, package managers, entrypoints,58 and monorepo boundaries. Do not assume a particular ecosystem.592. **Inventory testing infrastructure.** Locate test directories and naming60 conventions, test configuration, fixtures/fakes/mocks/snapshots, coverage61 configuration or reports, and CI configuration. Determine which test62 commands are actually documented or encoded in manifests, task runners, and63 CI. A dependency named `test` is not proof that a runnable suite exists.643. **Collect deterministic evidence.** When command execution is available,65 run the portable helper bundled with this skill:6667 ```text68 python3 path/to/test-health/scripts/inspect_test_health.py --root . --pretty69 ```7071 It reports evidence only; it does not decide maturity or recommend work.72 If it cannot run, perform the same inspection manually and lower confidence73 rather than inventing results.744. **Run the smallest relevant existing checks.** Inspect commands before75 executing them. Run a focused test command when one exists, then a broader76 existing suite when scope and time justify it. Also run relevant lint,77 typecheck, build, or packaging checks when the repository normally uses78 them. Report each as passed, failed, skipped, or unavailable. Never claim a79 command ran from configuration alone.805. **Inspect CI.** Establish whether tests run automatically, which command CI81 uses, whether only a narrow subset runs, and whether failures are visible.826. **Sample real tests.** Read a representative few—not every test file—across83 the relevant levels and risk areas. Assess behavior assertions, seams,84 mocks, isolation, readability, speed, flakiness, and maintainability.857. **Identify risk.** Find important behavior and change paths: domain rules,86 user journeys, public interfaces, persistence, permissions, destructive87 operations, external integrations, error handling, and high-churn areas.88 Use history when available; if it is unavailable, say so.898. **Assess health qualitatively.** Use one of: **No safety net**,90 **Foothold**, **Partial safety net**, **Reliable safety net**, or91 **Strong enough**. Base the state on executability, risk coverage, test92 quality, reliability, test-level fit, architectural testability, and change93 protection—not on a numeric score.949. **Choose one bounded improvement slice.** Compare candidate slices by risk95 reduced, confidence gained, implementation effort, maintenance cost,96 architectural prerequisites, and feedback speed. Select one primary behavior97 or risk at one seam/test level, then include only the directly enabling work98 and closely related scenarios needed to make that slice trustworthy. A slice99 may include a small cluster of tests, fixture or runner setup, a minimal100 seam, or focused CI wiring; it is larger than an isolated test when the101 evidence calls for it, but smaller than a broad testing campaign. Define102 what is explicitly out of scope before implementation.10310. **Stop at the slice boundary.** Finish when the primary risk has the104 planned behavioral evidence and the relevant checks pass. Defer a second105 independent risk, even if it appears nearby. Keep later ideas to at most106 three brief, ordered follow-ups. Do not add tests solely to inflate metrics,107 introduce a second framework without a concrete reason, favor E2E merely108 because it is realistic, or favor unit tests merely because they are fast.109110For detailed guidance, load only what is needed:111112- [Maturity and evidence](references/assessment-model.md)113- [Prioritization and bounded slice selection](references/prioritization.md)114- [Test quality and test-level fit](references/test-quality.md)115- [Ecosystem detection](references/ecosystem-detection.md)116- [Final report format](references/report-format.md)117118## Decision rules119120Use repository evidence to choose among these common cases:121122- **A meaningful seam exists:** protect the primary behavior through it. Include123 the key success, failure, or boundary outcomes that belong to the same risk;124 do not refactor for testability merely because another design would be easier125 to test.126- **Behavior is poorly understood:** characterize a meaningful current slice127 before changing it. Do not silently replace undocumented behavior with an128 imagined ideal.129- **Setup requires excessive mocking or invasive manipulation:** identify the130 one dependency or boundary that blocks useful observation and expose the131 smallest seam there, then add the related behavioral checks needed to prove132 that seam. Avoid broad dependency-injection, repository-pattern, or133 architecture migrations.134- **No testing infrastructure exists:** establish a minimum foothold using the135 ecosystem's natural tool, one clear command, and a small representative136 behavioral slice. Include enough scenarios to exercise the important branch137 or boundary; do not create a complete unit/integration/E2E stack.138- **The suite is flaky, unreliable, or painfully slow:** restore trust in the139 highest-value feedback, including adjacent setup or guard checks when they140 are part of the same failure, before increasing suite size.141- **CI does not run valuable local tests:** wire the existing focused command142 into the normal change path and make its failure visible; do not introduce a143 new framework or rebuild the whole pipeline in the same iteration.144- **Testing is already strong:** say **Good enough for now** unless a specific145 additional slice clearly justifies its cost.146147Do not equate a passing suite with meaningful protection, a large suite with148maturity, or high coverage with quality. Do not write tests for every source149file merely because it exists, target a coverage number, use snapshots as a150cheap coverage mechanism, or broadly refactor unprotected code just for151idealized testability. A few related scenarios that close one risk are part of152one manageable slice; unrelated gaps belong in later iterations.153154## Implementation mode155156If the user asks to implement the recommendation, first confirm the existing157conventions and implement only that bounded slice. The slice may include a158minimal seam, fixture/helper, focused command or CI wiring, and a small related159set of tests when those pieces are inseparable from the observable boundary.160Keep the change behavior-focused and avoid unrelated cleanup.161162After implementation:1631641. Run the new or changed tests and verify the planned scenarios freshly.1652. Run the relevant broader suite and normal lint, typecheck, build, or166 packaging checks when reasonably practical.1673. Confirm the intended behavior is protected at the selected seam. When168 useful, demonstrate that the tests fail if the protected behavior is169 intentionally broken; do not claim this if it was not checked.1704. Reassess the affected risk, confirm the slice stayed within its boundary,171 and report the actual commands and results.1725. Recommend no more than three short, ordered follow-ups, or say **Good enough173 for now**. Do not turn follow-ups into an unbounded backlog.174175## Default report176177Use the concise structure in [report-format.md](references/report-format.md):178179```markdown180# Testing health181182**State:** [state]183**Confidence:** [Low | Medium | High]184185## What I found186## Biggest current risk187## Recommended iteration188189**Primary risk or behavior:**190**Seam and test level:**191**Bounded slice:**192**Explicitly out of scope:**193194## Why this first195## Done when196## Later197```198199Include facts, commands, and observed results. If execution was unavailable,200say what was inferred from configuration or CI and lower confidence. Never turn201an unavailable check into a pass.