test
Skill2 starsChanged 3 months agoMITView on GitHub
Author new tests or refactor existing ones — layer classification, inventory & gap analysis, test-design table, AAA/naming/mock discipline, async safety, antipattern cleanup, and coverage verification. Covers both writing tests from scratch and improving the quality of tests that already exist. TRIGGER when: the user wants to write/add/generate tests for a file, directory, or feature, OR to audit/refactor/clean up existing tests. DO NOT TRIGGER when: the user wants to build NEW code test-first (use /tdd), only wants to run the existing suite, or wants to debug a specific failure (use /diagnose — but come back here to lock the fix with a test).
179 other projects use a version of this.
Adopted by
Most recently taken up by
- tyrantpiper/travel-pwatheir own version, first seen Nov 8, 2026
- phuthuycoding/kanban-flowtheir own version, first seen Nov 8, 2026
- pche-broken-artist/forge-of-thoughttheir own version, first seen Nov 8, 2026
- PMDevSolutions/Flaviantheir own version, first seen Nov 8, 2026
- domengabrovsek/agent-configtheir own version, first seen Nov 8, 2026
- domengabrovsek/claudetheir own version, first seen Nov 8, 2026
Used with
Projects with it also use agent-context-isolation, agentica-infrastructure and 10 more.
Other files people use alongside this one.
Files found in the same public projects as a version of this one, more often than they turn up anywhere else. Each project counts once, large collections count for less, and this file's own repository is left out.
parcadeiSkillagent-context-isolation
Agent Context Isolation
Also in 3 projects that use this
parcadeiSkillagentica-infrastructure
Reference guide for Agentica multi-agent infrastructure APIs
Also in 3 projects that use this
- +10 more from parcadei
Other versions179 projects use a version of this.
Word for word · 0
None found.
Edited · 0
None found.
Wrote their own version · 179
- react/react★ 252ksame name
- facebook/react★ 252ksame name
- apache/skywalking★ 25ksame name
- livewire/livewire★ 24ksame name
- NVIDIA/TensorRT★ 13ksame name
- FalkorDB/FalkorDB★ 10ksame name
- FastLED/FastLED★ 7.5ksame name
- fleetdm/fleet★ 7.2ksame name
- parcadei/Continuous-Claude★ 3.9ksame name
- parcadei/Continuous-Claude-v2★ 3.9ksame name
169 more not listed
How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.
In this repository48 other files it gives its agents.
- analystSkill
- api-designSkill
- arch-healthSkill
- audit-qualitySkill
- audit-securitySkill
- bootstrapSkill
- clean-mvpSkill
- close-epicSkill
- codebase-designSkill
- code-reviewSkill
- decomposeSkill
- deploySkill
- depsSkill
- diagnoseSkill
- discoverSkill
- distillSkill
- domain-modelSkill
- epic-statusSkill
- grillSkill
- grill-with-docsSkill
- handoffSkill
- ideaSkill
- implementSkill
- incidentSkill
- onboardSkill
- perfSkill
- preflightSkill
- prepareSkill
- prompt-masterSkill
- prototypeSkill
- refactorSkill
- retroSkill
- revisitSkill
- rolloutSkill
- scaffoldSkill
- select-techSkill
- spikeSkill
- sweepSkill
- tddSkill
- teardownSkill
- test-specSkill
- threat-modelSkill
- to-issuesSkill
- to-prdSkill
- triageSkill
- update-kitSkill
- which-skillSkill
- writing-skillsSkill
The file
We split this skill into the rules it gives an agent
11 rules. 0 are common, 7 are distinctive, and 4 are very specific to this project.
0
Common
Most of the 154 edited versions we read keep these.
7
Distinctive
This author's own choices. Worth a look.
4
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 27
If $ARGUMENTS is empty, ask what to test and stop.
- Very specific: line 51
Use the test command, test layout, and layers from PROJECT.md everywhere below.
- Distinctive: line 111
Before writing any fixture, check the project's factory/fixture location (from PROJECT.md / stack rules) — reuse existing builders instead …
- Distinctive: line 132
Never mock your own domain logic or same-module internals — that tests the mock, not behavior.
- Very specific: line 167
Properties over examples, where an invariant exists: if the unit has a nameable invariant ("output stays sorted", "sums are conserved", …
- Distinctive: line 175
Fixture scope: default to per-test (fresh) scope.
- Distinctive: line 180
Isolation: no shared mutable module-level state.
- Distinctive: line 198
Use the framework's async test setup (per stack rules).
- Very specific: line 204
No real sleeps/timers — inject or mock the clock.
- Distinctive: line 234
When converting, split merged assertions into focused tests and replace per-case copies with one parametrized test.
- Distinctive: line 281
Run via PROJECT.md → Commands — never hardcode commands:
“Common” is measured: kept by at least 6 in 10 of the 154 edited versions of this file we could read. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Test Authoring & Refactoring
Target: $ARGUMENTS — one of:
- A source file/dir (
<src>/foo) → write tests for it. - A test file/dir → audit and refactor existing tests.
- A description (
"login error isolation") → write targeted scenarios. staged→ audit/cover the test or source files in staged changes.- A plan/card file with a scope note → pin the scoped modules, then write the log back into that file (see Persist to the artifact).
If $ARGUMENTS is empty, ask what to test and stop. Work the phases in order; Phases 1–3
are investigative (plan before writing), 4–7 implement, 8 verifies.
Progressive loading. Phases 1–3 and 8 need nothing but this file. Phases 4–7 carry the
rules inline and the worked examples in reference/, read only when the target calls for
it — each phase below names its file and its short-circuit. A run that writes three
synchronous unit tests should never open the async reference.
Phase 0 — Load profile
Make this generic workflow concrete from project facts:
- Read
.claude/PROJECT.md— Stack, Commands (test,test:targeted/test:one), and Architecture (modules/layers, and the test layout: where tests, fixtures, and factories live). - Read
.claude/rules/_generic/testing.md. - If
CONTEXT.mdexists, read it so test names use the project's domain vocabulary. - Read every stack testing rule whose
pathsfrontmatter matches the target. These packs carry the concrete framework, assertion style, fixtures, and factory locations — never hardcode them here. - If
PROJECT.mdis missing or stillTEMPLATE, fall back to the rootCLAUDE.md(always in context) when it carries the stack, test command, and test layout — note you're running without a kit profile. Only if neither has them, run/bootstrapfirst.
Use the test command, test layout, and layers from PROJECT.md everywhere below. Apply the
stack-specific test patterns from the installed .claude/rules/* — do not invent framework
idioms in this skill.
Phase 1 — Classify
Mode:
- Source file/feature given → new tests (Phase 2, then 4–7).
- Existing test file/dir given → refactoring (Phase 2, then 6).
- Both → do both, in that order.
- Source with no tests and nothing stating what it should do (no spec, ticket, docstring or sibling
test) → legacy mode: read
reference/legacy-mode.md, characterize first.
Layer of the code under test (use the layers named in PROJECT.md → Architecture):
| Layer | Examples | Test approach |
| Pure / domain | calculations, transforms, validators, value objects | Pure unit tests — no mocks, deterministic inputs from factories |
| Service / use-case | commands, queries, orchestration | Mock only the external boundary; test the real domain logic they call |
| Infra / IO | network, DB, filesystem, queues, clock | Mock the boundary for its callers; async-aware where the language has async. Every persistence mapping still gets one real create/read/update/delete round-trip in the integration lane — nothing else catches SQL drifting out of step with the code |
| UI | components, views | Render + behavior via public output; query by role/text, not internals |
The layer decides the strategy: unit (no mocks) vs mock-boundary vs async-aware vs render. Find existing coverage before planning — map the target to its expected test path by the project's naming convention and grep the test tree for references to the units.
Phase 2 — Inventory & gap analysis
For new tests, list every public unit (function, method, class, exported symbol) and mark coverage. For refactoring, list the existing tests and the antipatterns they carry.
| Unit | Kind | Covered? | Verdict |
process_order | pure | partial | unit-test thoroughly |
OrderResult | value object | yes | — |
fetch_remote | io | no | one integration test |
Kind: pure (deterministic, no side effects) · stateful (mutates state) · async ·
io (network/file/DB/clock).
Verdict — two axes, never a coverage percentage per layer. Complexity/domain significance against
the number of collaborators (mutable or out-of-process; values do not count, implicit ones through
statics do). High + few → unit-test thoroughly. Low + few → do not test it at all. Low + many → one
integration test. High + many → a design defect: report it and route to /refactor before any test.
Evidence before the audit (refactoring mode) — gather with the stack's own idioms (from the
installed testing rule / CONTEXT.md), never a hardcoded framework token. Grep the target test
tree for:
- test functions with no assertion / no expected-exception (the stack's assert/raises idiom).
- real sleeps and real-clock reads (
sleep,now,time()), and unseeded randomness. - hardcoded temp/output paths instead of the framework's temp-dir helper.
- mocks that patch the project's own modules/layers (from PROJECT.md → Architecture), not boundaries.
- legacy xUnit-style setup/teardown/assert calls where the stack prefers plain asserts.
Record each hit as a row that feeds the Phase 6 findings table.
Before writing any fixture, check the project's factory/fixture location (from PROJECT.md / stack rules) — reuse existing builders instead of constructing domain objects inline.
For large or unfamiliar targets, delegate to the test-gap-finder agent to enumerate
untested paths and rank them by risk, then design tests for the critical gaps it reports.
Phase 3 — Test design
Plan every test as a row before writing code:
| Unit | Scenario | Expected | Type | Mock boundary |
process_order | no items | empty result, no charge | unit | none |
process_order | valid items | total computed, 1 charge | unit | none |
fetch_remote | network error | propagates after retry | integration | network client |
handle_event | subscriber callback raises | engine does not propagate | async unit | none |
Mock decision — five rules:
- Mock external boundaries only: network, DB, filesystem, clock/
now, sleep. - Never mock your own domain logic or same-module internals — that tests the mock, not behavior.
- Several doubles in one test is a report about the design, not a lane to change — name the defect
first (
skills/tdd/mocking.md§Smell: too many mocks), then widen only if the seam is truly wide. - Prefer a fake over a mock for a collaborator you own but must stand in for (a repository, a queue, a store): a small working in-memory implementation exercises real behavior, where a mock only replays a scripted return and asserts on the script.
- A client for an external provider → test the contract from your side in two halves that never
call it:
reference/writing-patterns.md§Prefer a fake over a mock.
Which scenario gets the integration test. Cover a scenario's edge cases with unit tests and give
it one integration test — the longest happy path, crossing the most out-of-process dependencies;
add another only to reach a dependency that path misses. A failure that crashes on the first run in
any environment and cannot corrupt data needs no test: declare the skip under Remaining Gaps.
Fixture vs local helper: reusable across ≥2 files → shared fixture/setup in the nearest common location; used once → local helper at the top of the file; complex domain object → the project's factory location.
Phase 4 — Writing rules
Load on demand: writing new tests → read
reference/writing-patterns.md (worked good/bad shapes for
naming, AAA, parametrize, fixture scope, mock discipline, fakes, assertion quality, isolation).
Refactor-only runs skip it except its §Refactoring conversions (Phase 6).
- Naming: a statement of fact about behaviour in domain words (
delivery_with_a_past_date_is_invalid); method-name template only for utility code; an enforced stack shape wins. Notest_works,test_case_1. - AAA: Arrange → Act → Assert, no interleaving. One logical assertion target per test
(several
assertlines for the same outcome are fine). Never call the unit inside the assertion — store the result first. Delete arrange that the act doesn't use. - Parametrize: same logic over ≥2 inputs → one parametrized/table-driven test, not N
copy-pasted functions and not a
forloop inside one test. - Properties over examples, where an invariant exists: if the unit has a nameable
invariant ("output stays sorted", "sums are conserved", "encode∘decode = identity" —
rules/_generic/core.md), add one property test asserting it across generated inputs — the stack's generator library if PROJECT.md/rules name one (Hypothesis, fast-check, StreamData…), else a seeded loop over randomized + boundary inputs. Example tests pin points; the property pins the region between them. A second trigger: values that must be present but could be swapped for any others mark a property, not an example — state the invariant, generate them, keep the real boundaries as explicit cases. - Fixture scope: default to per-test (fresh) scope. Wider scope (module/session) only for expensive read-only setup — never for fixtures that mutate state.
- Mock discipline: patch at the call site, not the definition site. Assert call count/args only when the side effect (not the return value) is the thing under test. Use the framework's teardown-safe mocking from the stack rules.
- Isolation: no shared mutable module-level state; each test passes independently and in any order. Filesystem → the framework's temp-dir helper, never hardcoded paths. Randomness → always seed. Time → freeze/inject, never read the real clock in assertions.
- Assertion quality: assert specific values, not
is not None/len > 0. Compare floats with an approx/tolerance helper. For exceptions, assert both type and message (message must contain the offending value). A unit whose only visible effect is a developer-facing log line has no observable behaviour — record a coverage gap, never assert on log prose; logs read by operators or the business are contract, so assert the named event or level+key.
Phase 5 — Async test safety (where the language has async)
Load on demand: the target actually contains async code → read
reference/async-patterns.md (async test shapes, the invariant
checklist, orphaned-task cleanup, the mocked-clock hang). Short-circuit: a synchronous
target skips this phase and that file entirely.
- Use the framework's async test setup (per stack rules); don't block the loop.
- Subscriber/callback failure is isolated — the engine/orchestrator must not propagate it.
- Cancellation propagates: a cancellation signal must never be swallowed by a bare
catch-all
except/catch. - Parallel fan-out: one task's failure must not kill its siblings (collect, don't crash).
- Ordering invariants: state is persisted before events are emitted to subscribers.
- No real sleeps/timers — inject or mock the clock; real
sleepmakes tests slow and flaky. - A mocked sleep/clock returns instantly, so an unbounded retry/poll loop under test spins at
full speed (a runaway CPU/memory hang). Guard such tests with the framework's per-test timeout
and a real termination condition (e.g. a call-count ceiling) — never
sleep(0), which is mocked too.
Phase 6 — Refactoring existing tests
Audit the target and produce a severity-ordered findings table. Severities:
- CRITICAL — false confidence (passes regardless of behavior), crashes, or masks bugs.
- STRUCTURAL — maintainability/clarity failures that make tests hard to change safely.
- STYLE — minor; fix while touching the file, not a standalone change.
| Antipattern | Severity | Fix |
| Test with no assertion / no expected-exception | CRITICAL | Add a real assertion or delete it — it proves nothing |
| Mocks the unit's own domain logic / same-module internals | CRITICAL | Remove the mock; exercise the real implementation |
| Assertions weakened to make a flaky test pass | CRITICAL | Restore the real expectation; fix the code or premise |
Trivial/always-true assertions (is not None, len > 0) | CRITICAL | Assert the actual expected value |
| Setup hides the Arrange (shared mutable setup assigning state) | STRUCTURAL | Extract to a fixture or local builder; keep Arrange visible |
| Order-dependent / shared module-level state | STRUCTURAL | Each test builds its own state in Arrange |
| Real sleep / real clock / real network in a unit test | STRUCTURAL | Mock the boundary or mark as integration |
| Hardcoded temp/output paths | STRUCTURAL | Use the framework's temp-dir helper |
| Unseeded randomness | STRUCTURAL | Seed it for repeatability |
| Loop over cases inside one test | STRUCTURAL | Extract to parametrized/table-driven cases |
| Same complex object built inline in many tests | STRUCTURAL | Move to the project's factory location |
| Legacy xUnit assert style where the stack prefers plain asserts | STYLE | Convert per stack rules |
When converting, split merged assertions into focused tests and replace per-case copies with one parametrized test. Mock only at the external boundary; keep the domain real.
Load on demand: a multi-line conversion (xUnit class style → plain assertions, parametrize
extraction) → read reference/writing-patterns.md
§Refactoring conversions. A one-line severity fix needs no reference file.
F.I.R.S.T. audit (refactor mode only)
Principle definitions live in rules/_generic/testing.md. What this phase adds is that four of
the five are mechanically greppable — run them over the target instead of eyeballing, using
the project's own paths and idioms (PROJECT.md → Stack, test layout):
| Principle | How to find violations | Fix |
| Fast | the runner's slowest-tests report (--durations-style flag) | mock at the boundary, use in-memory data, or move it to the integration lane |
| Independent | grep the target for class/module-level state assigned outside a test body, and for the framework's module-level setup hooks | build the state inside each test's Arrange |
| Repeatable | grep for RNG calls without a seed argument, and for reads of the real clock (now, today, monotonic timers) | seed the RNG; freeze or inject the clock |
| Self-validating | grep for tests whose only output is printing/logging, with no assertion or expected-exception | every test asserts, or it proves nothing |
Timely is a process principle, not a greppable one: new functions arrive with their tests. It shows up here only as a gap in Phase 2's inventory, never as a finding in an existing file.
Report each hit as a Phase 6 finding with its severity, not as a silent fix — an unseeded RNG in a test that has never flaked is still CRITICAL-adjacent, and the user decides whether it is worth touching now.
Phase 7 — Self-review checklist
- Every test name states a behaviour fact in domain words (method-name template only for utility code / enforced stack shape).
- No test without at least one real assertion / expected-exception.
- No domain logic or same-module internals mocked — boundaries only.
- Randomness seeded; time frozen/injected; no hardcoded paths; no real sleeps.
- Floats compared with tolerance; exceptions assert type + message.
- Reusable fixtures and object builders live in shared/factory locations, not inline.
- Tests that touch IO boundaries are marked/categorized per stack convention.
- Mutation thinking: for each critical-path test, name one plausible bug that would still
pass it (off-by-one, wrong branch, swallowed error) — a survivor means the assertion is too
weak; assert exact values, resulting state, or the side effect itself. Once for the whole
suite: the dumbest implementation that still passes every test names a missing case (
/tdd).
Phase 8 — Coverage verification
Run via PROJECT.md → Commands — never hardcode commands:
- Run the targeted test command on the new/changed tests first; all pass.
- Run the full test command; no new failures.
- Check coverage for the target if the project defines a coverage command.
- Write each new test black-box from the requirement it defends, not from the branch coverage pointed at.
- A gap no requirement defends is a dead-code candidate: propose deleting the branch, not covering it.
Coverage is a floor, not a goal — a passing suite with no real assertions is worthless. Prioritize: correctness of existing tests > coverage of new critical paths > style.
Output
## Test Design — <target>
| Unit | Scenario | Expected | Type | Mock boundary | (the Phase 3 table)
## Refactoring Actions (omit if target = new code)
| Antipattern | File:Line | Severity | Fix |
## Files
- written: <paths>
- changed: <paths>
## Test Run
<targeted result> · <full-suite result> · <coverage before→after if available>
## Remaining Gaps
<units/paths still untested and why, or "none">Persist to the artifact
(Mandatory when $ARGUMENTS or the session brief names a plan, card or spec file.) Follow ../implement/reference/work-log.md. Keep a ledger on disk from the first phase and record deviations the moment they are decided. Before the final reply, append ## Test Log — <date> — <verdict> to that file; its ### Result is the pins written (test → behaviour pinned), defects found while pinning (pinned as current behaviour) with a suggested owner, coverage before → after if measured, and any floors or budgets changed. Anything you could not observe yourself goes under Re-check later, with its command and today's baseline: a post-deploy log grep, a soak count, a UI gesture. The chat output is a copy of the log, never the only record. No planning artifact → skip this section.
See also
test-gap-finderagent — enumerate and rank untested paths before designing tests./tdd— build NEW code test-first (red → green → refactor); this skill covers/refactors tests for code that already exists./code-review— quality pass on the new tests and the code under test./diagnose— for a reported bug, root-cause it there; reproduce with a failing test first, then return here to lock the fix in.
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.

