test-design-workflow
Skill1 starsChanged 4 months agoMITView on GitHub
Use when the user asks to design, add, improve, or review tests for a feature, bug fix, API, CLI, UI, integration, migration, or security boundary. Use when test scope, success/failure/boundary cases, fixtures, mocks, automation level, or regression confidence must be chosen.
In this repository15 other files it gives its agents.
- AGENTS.mdAGENTS.md
- CLAUDE.mdCLAUDE.md
- agent-config-referenceSkill
- agent-security-guardSkill
- code-review-workflowSkill
- cross-model-verificationSkill
- git-workflow-for-agentsSkill
- incident-retro-workflowSkill
- observability-workflowSkill
- planning-workflowSkill
- requirements-clarifierSkill
- skill-authoring-workflowSkill
- skill-pipeline-orchestratorSkill
- skill-review-workflowSkill
- systematic-debuggingSkill
The file
Show its rules and text
We split this skill into the rules it gives an agent
17 rules. About 0 are common, 15 are distinctive, and 2 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈15
Distinctive · estimate
This author's own choices. Worth a look.
2
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 38
If the contract is vague, load requirements-clarifier before inventing tests.
- Very specific: line 65
No contract -> ask for acceptance criteria or use requirements-clarifier.
- Distinctive: line 66
Only implementation detail exists -> translate it to user-visible behavior before testing.
- Distinctive: line 93
No test framework -> propose the smallest harness and a manual fallback.
- Distinctive: line 132
Use the smallest data that triggers the behavior.
- Distinctive: line 134
Prefer nearby factories/builders.
- Distinctive: line 136
Avoid snapshots unless they are the contract.
- Distinctive: line 154
Read 2-3 nearby tests. Match imports, naming, setup, teardown, assertions, and file location.
- Distinctive: line 172
No nearby tests -> use the closest same-layer pattern and state the gap.
- Distinctive: line 188
Test body checklist: name behavior and condition.
- Distinctive: line 191
Test passes before the change -> it does not prove the new behavior.
- Distinctive: line 192
Test errors from setup -> fix setup before trusting red/green.
- Distinctive: line 193
Test needs many unrelated mocks -> reconsider design or test at a different level.
- Distinctive: line 201
Run before fix if the bug is still present.
- Distinctive: line 204
If none is safe, state why and lower confidence.
- Distinctive: line 223
Run the narrow test, then the smallest wider suite:
- Distinctive: line 245
Do not claim "covered" for cases not encoded in assertions or manual steps.
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Test Design Workflow
Overview
Good tests protect behavior, not implementation trivia. Extract the contract, map risk to the lowest proving level, design cases, then prove each regression catches its defect.
When to Use
| Use When | Don't Use When |
| The user says "add tests", "design tests", "test plan", "coverage gap", "regression test", or "what should we test" | A failing test or bug still needs root-cause investigation; use systematic-debugging first |
| A feature, bug fix, API, CLI, UI flow, migration, or integration needs automated or manual coverage | The user only asks to run an existing test command with no design decision |
| Code review finds missing tests, weak assertions, over-mocking, snapshot churn, or happy-path-only coverage | The artifact is a broad code review; use code-review-workflow |
| Behavior has validation rules, permissions, money/data risk, time/order sensitivity, compatibility, or external systems | There is no behavior contract, requirement, diff, bug report, or user path to test |
| Existing tests are brittle, slow, flaky, broad, or tied to implementation details | The user wants browser QA report-only exploration; use the local QA skill if available |
Phase 0 Benchmark Decision
Type: Technique. Adopt the Superpowers/GStack pattern: behavior-first tests, red proof before confidence, user-path evidence for QA, local style matching, and verification before coverage claims.
Test Design Gate
No behavior contract -> no test design.
No expected result -> no test case.
No failure proof for a regression test -> no confidence claim.If the contract is vague, load requirements-clarifier before inventing tests.
The Process
contract -> risk -> level -> cases -> fixtures -> style -> fail proof -> report
| | | | | | | |
v v v v v v v v
behavior blast pyramid matrix boundary patterns red/green residualStep 1: Extract the Behavior Contract
Expected Output: contract=<observable behavior>, actor=<user|system>, input=<data>, output=<result>, invariant=<must hold>
Name the behavior before choosing test mechanics. Pull it from requirements, bug report, diff, PR, route, CLI help, API schema, or existing tests.
git status --short
git diff --name-status
git diff --stat
rg -n "TODO|FIXME|acceptance|should|must|error|permission|validation" .Contract format: when <actor> does <action> with <input/state>, system returns <output/state>; invariant=<must hold>; risk=<who is hurt>.
If fails:
- No contract -> ask for acceptance criteria or use
requirements-clarifier. - Only implementation detail exists -> translate it to user-visible behavior before testing.
- Bug fix has no repro -> use
systematic-debuggingto capture the failing path first.
Step 2: Map Risk to Test Level
Expected Output: levels=<unit|integration|contract|e2e|manual>, rationale=<risk and feedback speed>
Choose the lowest level that proves the contract without hiding the boundary that can fail.
| Risk signal | Prefer |
| Pure function, parser, validator, state reducer | Unit |
| DB query, transaction, cache, job, filesystem | Integration |
| API request/response, CLI contract, SDK compatibility | Contract or integration |
| Auth, billing, checkout, onboarding, critical UI workflow | E2E plus lower-level tests |
| Migration, data repair, idempotency, rollback | Integration plus dry-run checklist |
| Visual-only CSS or copy | Component/screenshot/manual |
| External service | Contract fake plus one safe smoke test |
Detect local test surfaces:
rg --files -g "*test*" -g "*spec*" -g "__tests__/**"
rg --files | rg "pytest|vitest|jest|playwright|cypress|package.json|pyproject.toml|go.mod|Cargo.toml"If fails:
- No test framework -> propose the smallest harness and a manual fallback.
- E2E is too slow -> cover logic lower down and keep one smoke path.
- Boundary is mocked away -> move the test outward until that boundary is exercised.
Step 3: Build the Case Matrix
Expected Output: cases=<success/failure/boundary/regression table>, expected_results=<specific assertions>
Design cases before writing code. Cover success, failure, boundary, and regression cases per behavior change.
| Case type | Include when | Example assertion |
| Success | Main promised behavior | returns 201 and persists one record |
| Failure | Invalid input, denied auth, dependency error | returns 400 with field error |
| Boundary | empty, null, min/max, duplicate, timezone, pagination | page 2 starts after page 1 |
| State transition | status, retry, idempotency, concurrency | duplicate webhook does not double charge |
| Regression | Known bug was fixed | old failing input returns expected result |
| Compatibility | API/CLI/config used by callers | old flag still works with warning |
| Security | auth, tenant, secret, shell, SSRF, LLM output | tenant data is isolated |
Case row format:
| ID | Behavior | Setup | Action | Expected | Level |If fails:
- Matrix has only success cases -> add at least one failure and one boundary case.
- Expected result says "works" -> replace with exact status, value, state, or visible text.
- Security boundary appears -> load
agent-security-guardfor adversarial cases.
Step 4: Choose Fixtures, Mocks, and Oracles
Expected Output: fixtures=<data>, mocks=<boundary only>, oracle=<how correctness is known>
Fixtures must reveal behavior. Mock only boundaries you do not own or cannot make deterministic.
Rules:
- Use the smallest data that triggers the behavior.
- Name data by meaning.
- Prefer nearby factories/builders.
- Assert response, state, row, event, file, stdout, UI text, or metric.
- Avoid snapshots unless they are the contract.
Search local patterns:
rg -n "factory|fixture|beforeEach|setup|mock|stub|snapshot|assert|expect" tests test spec __tests__ 2>/dev/null
rg -n "describe\\(|it\\(|test\\(|expect\\(|assert" .If fails:
- Mock returns exactly what the assertion expects -> use real code or assert boundary call.
- Snapshot changed without targeted assertion -> add a direct assertion or reject it.
- Fixture is huge -> shrink it until each field has a reason.
Step 5: Match Local Test Style
Expected Output: style=<framework>, command=<narrow test command>, new_file=<path|none>
Read 2-3 nearby tests. Match imports, naming, setup, teardown, assertions, and file location.
rg --files | rg "(test|tests|spec|__tests__)"
rg -n "changedFunction|newEndpoint|newStatus|featureFlag" tests test spec __tests__ src app lib 2>/dev/nullFramework command examples:
python -m pytest tests/path/test_file.py::test_name -q
npm test -- path/to/file.test.ts
pnpm test path/to/file.spec.ts
go test ./path/to/package -run TestName -count=1
cargo test test_name -- --nocaptureIf fails:
- No nearby tests -> use the closest same-layer pattern and state the gap.
- Existing tests are poor -> match the harness but improve assertions.
- User asked for plan only -> output file paths, cases, and commands without editing tests.
Step 6: Write or Specify the Tests
Expected Output: tests=<files|plan>, assertions=<behavior assertions>, command=<narrow command>
For implementation tasks, write tests in red-green style:
write test -> run narrow command -> confirm expected failure -> implement/fix -> rerunFor planning or review tasks, specify the exact test file, setup, action, assertion, and command.
Test body checklist: name behavior and condition; create only needed state; perform the real action; assert the contract; for failures assert error and unchanged state; name the boundary value.
If fails:
- Test passes before the change -> it does not prove the new behavior; adjust the case.
- Test errors from setup -> fix setup before trusting red/green.
- Test needs many unrelated mocks -> reconsider design or test at a different level.
Step 7: Prove the Test Can Catch the Bug
Expected Output: failure_proof=<red observed|mutation observed|not possible>, evidence=<command output>
Regression tests need proof. Use one safe method:
- Run before fix if the bug is still present.
- Temporarily revert the fix, run the test, restore the fix.
- Temporarily mutate the guarded condition, run the test, restore it.
- If none is safe, state why and lower confidence.
Commands:
git diff -- path/to/file
python -m pytest tests/path/test_file.py::test_name -q
npm test -- path/to/file.test.tsIf fails:
- Cannot safely mutate/revert -> record
failure_proof=not possibleand residual risk. - Wrong failure reason -> fix until it fails for the intended behavior.
- Red proof missing but final claims say "regression protected" -> rewrite claim.
Step 8: Verify Scope and Report Residual Risk
Expected Output: coverage=<cases covered>, commands=<run/not run>, residual=<untested risks>
Run the narrow test, then the smallest wider suite:
python -m pytest tests/path/test_file.py::test_name -q
python -m pytest tests/path -q
npm test -- path/to/file.test.ts
npm test
go test ./...
cargo testReport format:
Test design:
- Contract: <behavior>.
- Cases: <success/failure/boundary/regression/security>.
- Files/commands: <paths and commands>.
- Failure proof: <red/mutation/not possible>.
- Residual risk: <manual-only, external dependency, unrun suite, or none identified>.Do not claim "covered" for cases not encoded in assertions or manual steps.
If fails:
- Narrow test fails -> fix the test or implementation before wider runs.
- Wider suite fails outside scope -> report it separately; do not claim full pass.
- Commands were not run -> mark
run/not runand name the residual risk.
Bad/Good Test Patterns
Pattern 1: Implementation Detail
Bad:
Assert `normalizePayload()` is called twice.Good:
Submit duplicate payloads and assert only one invoice row exists.Pattern 2: Happy Path Only
Bad:
Test valid checkout returns success.Good:
Test valid checkout succeeds, declined card returns 402 without order creation, and duplicate webhook is idempotent.Rationalization Table
| Rationalization | Why it fails |
| "Coverage went up, so tests are good" | Coverage measures lines, not behavior, assertions, or risk. |
| "The implementation is simple" | Simple branches still fail at boundaries, invalid input, and future changes. |
| "Snapshots cover it" | Snapshots catch broad text drift but rarely prove intended behavior. |
| "Mocking is faster" | A fast mock that hides the real boundary can prove the wrong system. |
| "E2E covers everything" | E2E is slow and brittle; it often misses exact edge cases. |
Red Flags
- You are choosing a framework before naming the behavior.
- You are writing only happy-path tests for validation, auth, money, data, or migration.
- You are asserting private calls, CSS classes, or mock calls instead of observable behavior.
- You are adding a snapshot without a targeted assertion.
- You cannot explain how the new test would fail without the fix.
- You are mocking the same boundary where the bug happened.
- You say "covered" or "probably enough" without command evidence.
- You invent a new harness instead of matching local style.
Common Pitfalls
| Symptom | Root cause | Fix |
| Test passes before implementation | The test asserts existing behavior or a mock | Change setup/action/assertion until it fails for the missing behavior |
| Bug recurs despite a regression test | Test did not encode the original failing input or assertion | Recreate the exact precondition and assert the corrected observable result |
| Suite is slow and brittle | Too many broad E2E tests for low-level logic | Move logic cases down; keep one smoke path for workflow confidence |
| Test fails only in CI | Shared state, time, order, locale, env, or resource assumptions leaked | Isolate state, control time, avoid order dependency, and run repeat checks |
| Snapshot updates hide behavior drift | Snapshot became the oracle without intent | Add direct assertions for the contract or narrow the snapshot |
| Mock-heavy test misses integration bug | The mocked boundary was the failing boundary | Use fake server, test DB, or integration harness for that boundary |
Verification Checklist
- Behavior contract names actor, input/state, action, expected result, and invariant.
- Test level is justified by risk and feedback speed.
- Case matrix includes success, failure, boundary, and regression when applicable.
- Security, permission, tenant, money, data-loss, and migration risks have explicit cases when present.
- Fixtures and mocks preserve the boundary being tested.
- Local test style and command were discovered before adding or recommending tests.
- Each test assertion checks observable behavior, not only implementation details.
- Regression test has red/mutation proof or an explicit confidence limitation.
- Narrow test command and relevant wider command are listed with run/not-run status.
- Residual untested risk is named instead of hidden.
Interaction with Other Skills
| Related Skill | Trigger | Handoff |
| requirements-clarifier | Contract vague | Clarify inputs, outputs, invariants, done conditions |
| systematic-debugging | Bug lacks root cause | Reproduce, isolate, produce regression target |
| code-review-workflow | Diff needs test review | Convert review gaps into test cases |
| observability-workflow | Signals insufficient | Add logs, metrics, traces as test oracles |
| agent-security-guard | Security boundary present | Add adversarial security cases |
| cross-model-verification | Plan high-risk or uncertain | Independent adversarial review |
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

