writing-tests
Skill0 starsChanged 51 days agoMITView on GitHub
Use when adding or changing behavior, fixing a bug, or judging whether an existing or generated test earns its place.
39 other projects use a version of this.
Adopted by
Most recently taken up by
- scheron/Dailytheir own version, first seen Nov 8, 2026
- mcp-use/mcp-usetheir own version, first seen Nov 8, 2026
- yuri-xyz/skillstheir own version, first seen Nov 8, 2026
- lox/agent-skillstheir own version, first seen Nov 7, 2026
- JetBrains/intellij-communitytheir own version, first seen Nov 7, 2026
- iliaal/ai-skillstheir own version, first seen Nov 7, 2026
Used with
Projects with it also use commits, running-tests and 4 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.
JetBrainsSkillcommits
Use this skill whenever the user asks to commit changes, write or fix a commit message, amend or rename a commit, or do a workflow that includes committing in the IntelliJ repository. This is a thin repo-specific overlay: use IntelliJ commit format, write full commit messages by default, and keep requested suffixes such as IJ-MR trailers in a final separate paragraph.
Also in 3 projects that use this
OpenAISkillrunning-tests
Guide for running tests in the openai-dotnet repository. Use this when asked to run, debug, or validate tests, or when writing new tests. Explains test modes (Playback, Record, Live), how to identify recorded vs non-recorded tests, environment variable configuration, and what to do when recordings are missing or stale.
Also in 3 projects that use this
BlockSkilldebugging
Debugging guidelines and best practices
Also in 5 projects that use this
VercelSkilltechnical-writing
Write, edit, review, or audit user-facing documentation for the eve repository. Use for changes under docs/, documentation tied to eve APIs or CLI behavior, docs work based on Slack or support feedback, and requests to make eve docs clearer, more natural, or less AI-patterned while verifying claims against current source, tests, CLI help, public releases, and repository conventions.
Also in 3 projects that use this
SentrySkillsecurity-review
Finds exploitable application security vulnerabilities in code changes. Use for Warden security scans, appsec review, OWASP-style checks, authentication or authorization bugs, injection, XSS, SSRF, path traversal, secrets, unsafe crypto, webhook verification, open redirects, or sensitive data exposure.
Also in 3 projects that use this
GoogleSkillimprove-codebase-architecture
Scan a codebase for deepening opportunities, present them as a visual HTML report, then grill through whichever one you pick.
Also in 3 projects that use this
Other versions39 projects use a version of this.
Word for word · 0
None found.
Edited · 0
None found.
Wrote their own version · 39
- remotion-dev/remotion★ 72ksame name
- PostHog/posthog★ 40ksame name
- JetBrains/intellij-community★ 21ksame name
- quarkusio/quarkus★ 16ksame name
- mcp-use/mcp-use★ 11ksame name
- DetachHead/rebased★ 6.5ksame name
- chattocorp/chatto★ 2.9ksame name
- starkware-libs/cairo★ 1.9ksame name
- bholmesdev/hubble.md★ 1.5ksame name
- amplifthq/openmeld★ 1.4ksame name
29 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 repository20 other files it gives its agents.
- CLAUDE.mdCLAUDE.md
- templates/CLAUDE.mdCLAUDE.md
- capturing-decisionsSkill
- choosing-subagent-modelsSkill
- committing-changesSkill
- debugging-systematicallySkill
- delegating-workSkill
- designing-changesSkill
- exploring-a-codebaseSkill
- injecting-dependenciesSkill
- planning-changesSkill
- pruning-testsSkill
- reflecting-on-changesSkill
- resolving-conflictsSkill
- reviewing-codeSkill
- verifying-changesSkill
- writing-commentsSkill
- writing-logsSkill
- writing-project-instructionsSkill
- writing-skillsSkill
The file
We split this skill into the rules it gives an agent
6 rules. 0 are common, 6 are distinctive, and 0 are very specific to this project.
0
Common
Most of the 39 edited versions we read keep these.
6
Distinctive
This author's own choices. Worth a look.
0
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 19
What ships broken if it is deleted?: If another test or the compiler would fail, it is redundant.
- Distinctive: line 28
One owner per rule: Test it once, at the lowest layer that owns it.
- Distinctive: line 60
Run the real engine, or fake the repository interface and test its queries on the real engine.
- Distinctive: line 92
Every test clears all ten.
- Distinctive: line 106
No sleep or bumped timeout over a race: Wait for the condition, or propose an injected clock or scheduler.
- Distinctive: line 112
Before finishing, mutate the code in your head — a wrong constant, the other branch, a missing side effect, an empty return, no check for …
“Common” is measured: kept by at least 6 in 10 of the 39 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
Writing tests
A behavior change ships with a test that fails when the change is undone — and with no test that cannot name the bug it catches. Both halves bind. Green proves nothing broke, not that the new code runs. Volume is the opposite failure: dozens of tests restating the code, each making the next refactor dearer.
Before writing a test
Answer all three, or do not write it:
- Which bug does it catch? A plausible one-line mistake a refactor or wrong fix could introduce — not "someone deletes the function". A bug, not a decision.
- What ships broken if it is deleted? If another test or the compiler would fail, it is redundant.
- Does it survive a refactor that keeps behavior? Breaking when internals move and the result does not means it pins the implementation.
How many
- One to three per behavior change. Give the reason before a fourth. No cap for concurrency and ordering, persistence and recovery, money and access gating — each interleaving that matters is a behavior.
- One owner per rule. Test it once, at the lowest layer that owns it. A higher layer gets one wiring test, unless it adds a transport or lifecycle risk.
- Tests differing in one input are one parameterized test.
- Always required: a new type, function or case carrying logic; a changed branch, predicate, mapping or constant that alters behavior; a race; persistence; money; every bug fix.
- Not required — name the test or compiler check that covers it instead: generated and vendored
code; renames, moves, formatting, comments; pure UI layout (test the view-model mapping); pure
wiring — a pass-through, a memberwise init, a property restating a
switch. A new or changed hand-off between components is not wiring. - Genuinely untestable: say so, with the reason. Never skip silently, and never write a dishonest test instead.
Order
- Test first whenever you can; watch it fail for the expected reason — the behavior missing, not a typo or import error. A test written after passes on its first run, which proves nothing.
- Code came first: break the line the test covers and watch it fail (filter item 2).
- A bug fix starts with the reproduction, failing for the reported reason. Fix came first: stash it and run the test on the unfixed code — re-breaking by hand tests only your theory. Then keep the test, fold it into a parameterized one, or discard a pure diagnostic — and say which.
Unit or component
A unit test suffices only when the behavior lives in one type. When the behavior is the collaboration, ship a component test: real collaborators in-process, faked only at the outer edges — network, clock, presentation. That covers a new component that drives others, a substantial hand-off change (new call, ordering, gate or teardown), and a bug that needs two real collaborators.
- Faking a middle collaborator is a unit test wearing a component test's name.
- A missing seam is no reason to drop to unit. Move construction to the caller —
vvkit:injecting-dependencies— or say the seam is out of scope. - The database is not an edge to fake with another engine. SQLite accepts what Postgres rejects. Run the real engine, or fake the repository interface and test its queries on the real engine.
What a test asserts
- Expected values are literals from the product rule, with inputs on the rule's boundary. An expectation computed by the code under test, its helpers, or branching on the test's parameters passes whatever the code does. A literal copied from running the code is a characterization test — say so. A locale- or OS-formatted literal tests the formatter; assert your input to it.
- No change detectors — a constant's value, exact wording, private structure, every intermediate emission, a grep over source. Test what depends on the decision: not that the retry limit is 5, but that the sixth attempt never happens.
- Your contract, not the framework's. The route you register, the query you emit.
- Fixtures mirror real data completely, and never supply what the code under test should produce.
Doubles
- Never assert on a double. Mock returns X, test asserts X: passes with the component deleted.
- Verify effects, not reads — writes, deletes, purchases, network mutations, analytics, navigation, and "never called" for an irreversible one after a failure. A call count on a read catches nothing, unless the test is about caching, single-flight or debounce.
- A double controls scheduling, not semantics. A fake with its own retry or eviction rule tests the fake.
- Fake at the right level. A fake that swallows a write the code later reads passes while production breaks.
- Specific where it matters — arguments, counts, order when they are the contract. An unstubbed real network or disk call fails loudly.
- Extend the shared double before writing another; a test-local one names the control the shared one lacks.
- Fake setup outgrowing the test: switch to a component test.
The acceptance filter
Every test clears all ten.
- It compiles and passes.
- It fails when the code is wrong. Break the covered line, confirm red, restore, confirm the
source diff is empty. Restore by reversing your edit — never
git checkoutorgit restore, which discards the uncommitted implementation. Non-negotiable for timing, callbacks and polling. - No access widening. Unreachable through the real seam is a design finding.
- No tautology: a constant; non-nil when the content is the point; your own fixture's contents; waiting for X then asserting X; what the previous line proved. If it would still pass with every function returning nothing or empty, it tests nothing. A negative test fails at the guard it names, not an earlier one.
- It lives in the target, module or package that owns the code.
- It runs in parallel, or is marked serial with the shared resource named.
- It stays green across three consecutive runs.
- No sleep or bumped timeout over a race. Wait for the condition, or propose an injected clock or scheduler. A timing test states why its interval is what it is.
- No weakened assertion, deleted test or known-issue mark to get green — unless you explain why the failure is not a bug.
- No production hook that exists only for the test.
Before finishing, mutate the code in your head — a wrong constant, the other branch, a missing side effect, an empty return, no check for empty, zero, nil, unauthorized or malformed input. A realistic mutation no test fails marks unprotected behavior. Where the project has mutation or coverage tools, run them instead.
Report
For each test added: its name and the bug it catches. Beyond three, the reason. For each behavior left untested: the test or check that covers it. For a bug fix: kept, folded or discarded.
Elsewhere
- Framework APIs and assertion shapes: the stack skill — for Swift,
vvkit-swift:swift-testing. - Deleting, merging or rewriting tests on purpose:
vvkit:pruning-tests.
Budget, owner-layer and effect-only rules adapted from sergdort's "Pragmatic Testing" agent skill
(2026), after Orta Therox's A Pragmatic Approach to iOS Testing. Negative-test and fixture rules from
OpenClaw's test-audit skill.
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.

