unit-testing
Skill0 starsChanged 21 days agoMITView on GitHub
Writes, fixes, and reviews unit tests that check behavior, fail when the code is wrong, and give the same result on every run. Defaults to Vitest for JavaScript and TypeScript when a repo has no test runner yet. Covers proving a test can fail, test-first bug fixes, what to mock, removing nondeterminism, and fixing a failing test without weakening it. Use when adding or changing code that needs tests, fixing a bug, a unit test is failing or flaky, or reviewing tests in a diff.
20 other projects use a version of this.
Adopted by
Most recently taken up by
- reddygopalkrishna/developer-agent-skillstheir own version, first seen Nov 8, 2026
- petrkindlmann/qa-skillstheir own version, first seen Oct 25, 2026
- r-portas/skillstheir own version, first seen Oct 20, 2026
- prinx/agentstheir own version, first seen Oct 20, 2026
- sb-dev/narrative-production-skillstheir own version, first seen Oct 20, 2026
- pulsejet/memoriestheir own version, first seen Oct 17, 2026
Used with
Projects with it also use database-testing, contract-testing and 3 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.
petrkindlmannSkilldatabase-testing
Validate database integrity, test migrations forward and backward, verify schema constraints, manage seed data, detect migration drift, and identify query performance issues. Covers PostgreSQL, MySQL, MongoDB with Prisma, TypeORM, Drizzle, and SQLAlchemy, plus Testcontainers test databases. Use when: "database test," "migration test," "migration rollback," "rollback test," "data integrity," "SQL test," "schema validation," "seed data," "query performance," "Testcontainers." Not for: synthetic data generation/masking at scale — use test-data-management; Docker/IaC test-environment provisioning — use test-environments; SQL injection — use security-testing. Related: test-data-management, test-environments, security-testing, ci-cd-integration.
Also in 3 projects that use this
petrkindlmannSkillcontract-testing
Implement consumer-driven contract testing with Pact-JS (v16). Covers consumer test writing, broker-driven provider verification, Pact Broker setup, can-i-deploy as a deployment gate, webhook-triggered verification, pending pacts, and schema-first vs consumer-first approaches (OpenAPI/Ajv, Schemathesis). Use when: "contract test," "Pact," "consumer-driven," "API contract," "provider verification," "can-i-deploy." Not for: stubbing or mocking a dependency to isolate a test — use service-virtualization; general REST/GraphQL endpoint assertions against your own API — use api-testing. Related: api-testing, service-virtualization, ci-cd-integration, test-environments.
Also in 3 projects that use this
jarosser06Skilltest-strategy
Plans pytest test strategies for Drift's 90%+ coverage requirement using coverage analysis, edge case identification, and test suite design. Use when determining what tests to write, analyzing coverage gaps, or planning test strategies.
Also in 4 projects that use this
Microsoft AzureSkillrelease-readiness
Complete ODIN release documentation and validation checks before declaring user-visible work complete, preparing a release, or opening the Release-to-main pull request.
Also in 3 projects that use this
Microsoft AzureSkillgit-workflow
Squad branching model: dev-first workflow with insiders preview channel
Also in 4 projects that use this
Other versions20 projects use a version of this.
Word for word · 0
None found.
Edited · 0
None found.
Wrote their own version · 20
- pulsejet/memories★ 3.9ksame name
- lichtblick-suite/lichtblick★ 1.2ksame name
- javierbrea/eslint-plugin-boundaries★ 1ksame name
- petrkindlmann/qa-skills★ 209same name
- kid-sid/claude-spellbook★ 190same name
- reddygopalkrishna/developer-agent-skills★ 8same name
- dprakash2101/dotnet-production-agent-skills★ 4same name
- ffsshhttiikk/opencode-agents-skills★ 2same name
- sb-dev/narrative-production-skills★ 2same name
- axross/skills★ 1same name
10 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 repository8 other files it gives its agents.
- adding-a-skillSkill
- e2e-testingSkill
- generating-roadmapsSkill
- githubSkill
- pr-reviewSkill
- repo-setupSkill
- roadmap-dashboardSkill
- wikiSkill
The file
Show its rules and text
We split this skill into the rules it gives an agent
18 rules. 0 are common, 14 are distinctive, and 4 are very specific to this project.
0
Common
Most of the 17 edited versions we read keep these.
14
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 19
Use the repository's test runner, file layout, naming, helpers, and fixtures.
- Very specific: line 26
When the repo has no unit test runner yet, use Vitest for JavaScript and TypeScript.
- Distinctive: line 32
Test behavior through the unit's public interface: given these inputs, it returns this, throws that, or produces this side effect at a …
- Distinctive: line 45
Write the cases the code actually handles or should handle.
- Distinctive: line 54
Assert the exact result: Check the value, not that something is truthy.
- Very specific: line 58
No logic in tests: No loops or conditionals that decide what to assert.
- Distinctive: line 64
Before trusting a new test, see it fail for the right reason:
- Distinctive: line 66
Bug fix: write the test first, run it against the unfixed code, and confirm it fails with the bug's symptom.
- Distinctive: line 71
If the test still passes with the code broken, it isn't testing that code.
- Distinctive: line 82
Prefer a small fake (an in-memory store, a fixed clock) over a mock that scripts every call.
- Distinctive: line 98
Remove the usual causes:
- Distinctive: line 102
Order: don't depend on the order of tests, of hash or set iteration, or of concurrent work.
- Distinctive: line 106
Real I/O: no real network. Use a fresh temp directory per test for file work.
- Very specific: line 107
Waiting: never sleep to wait for async work.
- Distinctive: line 117
If the code is wrong, fix the code.
- Distinctive: line 118
If the test is wrong (it encodes a mistaken expectation, or the behavior changed on purpose), change the test, and say in the commit why …
- Distinctive: line 121
Never get to green by deleting or skipping a test, loosening an assertion, catching the error, or copying the actual output into the …
- Distinctive: line 129
Before handing over tests, or when reviewing them:
“Common” is measured: kept by at least 6 in 10 of the 17 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
Unit testing
A unit test exists to fail when the code is wrong. One that passes no matter what the code does is worse than none, because it tells the next person the code is covered. Everything here serves two properties: the test fails for a real bug, and it gives the same answer on every run.
The sister skill e2e-testing covers tests that drive the
whole system through a browser, a CLI, or an API. When a behavior can be checked at either
level, check it here. Unit tests are faster, more precise, and less flaky.
Repo rules come first
Use the repository's test runner, file layout, naming, helpers, and fixtures. Read a few
existing tests near the code before writing one, and match them. AGENTS.md,
CONTRIBUTING.md, and the package scripts say how tests are run. Where they conflict with
this skill, they win. Don't add a second test framework or assertion library.
Default tool
When the repo has no unit test runner yet, use Vitest for JavaScript
and TypeScript. For other languages, use the ecosystem's standard runner, such as pytest
for Python or go test for Go. Examples here use Vitest. The rules apply with any runner.
What to test
Test behavior through the unit's public interface: given these inputs, it returns this, throws that, or produces this side effect at a boundary. Don't test private helpers directly, and don't assert on internal call order or call counts unless the call is itself the behavior (a request sent, a message published).
For each behavior, think through the cases that tend to break:
- empty, one, and many;
- the boundaries of every range: zero, negatives, the maximum, off by one;
- invalid input and every error path the code handles on purpose;
- inputs that look the same but aren't:
nulland missing,0and"", Unicode, whitespace, time zones.
Write the cases the code actually handles or should handle. Don't pad the suite to raise a coverage number.
How to write one
- One behavior per test, named for that behavior:
rejects an expired token, nottest validate 3. A failure message should say what broke without opening the file. - Arrange, act, assert. Build inputs in the test, or with a helper whose name says what it builds, so a reader sees the important values without jumping elsewhere.
- Assert the exact result. Check the value, not that something is truthy. Check an error's type or message, not only that something was thrown.
- Await everything async. A test that starts a promise and doesn't await it, or asserts inside a callback that never runs, passes without checking anything.
- No logic in tests. No loops or conditionals that decide what to assert. Use the
runner's parameterized tests for many cases:
test.eachin Vitest,@pytest.mark.parametrizein pytest, table tests in Go.
Prove it can fail
Before trusting a new test, see it fail for the right reason:
- Bug fix: write the test first, run it against the unfixed code, and confirm it fails with the bug's symptom. Then fix the code and watch it pass.
- New code: break the code on purpose (flip a condition, return early, change a constant), run the test, confirm it fails, then undo the change.
If the test still passes with the code broken, it isn't testing that code. Fix the test.
Mocks and fakes
Replace things at the edges of the system, not inside it:
- Replace: the network, the clock, randomness, the file system when it's slow or shared, and third-party services.
- Keep real: the unit under test, and the code it calls inside the same module or package. Mocking those tests the mock.
Prefer a small fake (an in-memory store, a fixed clock) over a mock that scripts every
call. Where the code reads the time, a random value, or the environment, pass it in or
use the runner's tools, rather than patching globals ad hoc. In Vitest that's
vi.useFakeTimers() and vi.setSystemTime() for time, vi.stubEnv() for environment
variables, vi.spyOn() for a single function, and vi.mock() for a module at a boundary.
Each needs its own cleanup after every test, because one doesn't undo the others:
- fake timers:
vi.useRealTimers(); - environment:
vi.unstubAllEnvs(), orunstubEnvs: truein the config; - spies:
vi.restoreAllMocks(), orrestoreMocks: truein the config; vi.mock()applies to the whole test file, so put tests that need the real module in another file.
Same answer every run
A test that sometimes fails costs everyone time and teaches people to ignore red builds. Remove the usual causes:
- Time: freeze the clock, and set the time zone and locale when output depends on them.
- Randomness: seed it, or inject the source.
- Order: don't depend on the order of tests, of hash or set iteration, or of concurrent work. Sort before comparing when order isn't the behavior.
- Shared state: reset globals, singletons, module caches, environment variables, and temp files after every test. Each test must pass alone and in any order.
- Real I/O: no real network. Use a fresh temp directory per test for file work.
- Waiting: never
sleepto wait for async work. Await it, or advance fake timers.
To check a fix for a flaky test, run that test many times in a row, and in random order if
the runner supports it, before calling it fixed. In Vitest, give the test a repeats
option and run the suite with --sequence.shuffle.
When a test fails
Find out which is wrong, the code or the test, before changing either.
- If the code is wrong, fix the code. The test did its job.
- If the test is wrong (it encodes a mistaken expectation, or the behavior changed on purpose), change the test, and say in the commit why the old expectation no longer holds.
- Never get to green by deleting or skipping a test, loosening an assertion, catching the error, or copying the actual output into the expected value without checking it. Delete a test only when the behavior it checks was removed on purpose.
- Snapshot updates get the same care: read the snapshot diff, and accept it only when every change is intended.
Checklist
Before handing over tests, or when reviewing them:
- Each new test was seen to fail, against the bug or a deliberate break.
- Tests check behavior through the public interface, not internals.
- Assertions are exact, and every async call is awaited.
- Only boundaries are mocked.
- No real time, randomness, network, or shared state. Each test passes alone.
- No test was skipped, deleted, or weakened to get green.
- The single test, then the whole suite, pass with the repo's own command.
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.

