An agent skill that makes AI coding agents write unit tests — and therefore production code — to a discipline you recognise, instead of the average of their training data.
Ask most agents for a unit test and you get ten-plus lines of setup and mock wiring
pasted inline into every test, copied and slightly drifted from the one above it,
asserting whatever the code happens to do. This skill replaces that default with
London School TDD (Growing Object-Oriented Software, Guided by Tests — Freeman &
Pryce) and strict Osherove AAA (The Art of Unit Testing, 3rd ed.): makeFactory()
owns the whole Arrange phase, every collaborator is mocked at the class boundary, and
each test asserts exactly one thing.
It is not a prompt to paste. It is a file your agent loads on every code change, so the conventions are taught once instead of re-explained every session.
Why it exists: Trusting agent code: the unit-test skill — the quality gap that kept me off coding agents for two years, and what closed it.
| Path | What it is |
|---|---|
SKILL.md |
The skill itself — the checklist, the philosophy, the no-comments rule |
reference/principles.md |
The full rules with worked examples: the factory pattern, one assertion per test, isolation, determinism, behaviour-not-implementation, regression tests, UI component testing |
example/ |
A runnable project demonstrating the patterns — npm install && npm test |
The skill is a directory the agent reads. Copy it into your agent's skills folder:
git clone https://github.com/rdok/unit-test-skill.git
# Claude Code
cp -R unit-test-skill ~/.claude/skills/unit-test
# Copilot CLI
cp -R unit-test-skill ~/.copilot/skills/unit-test
# Grok
cp -R unit-test-skill ~/.grok/skills/unit-test
# OpenCode
cp -R unit-test-skill ~/.config/opencode/skills/unit-testOr, for a single project, commit it into the repository and point your agent's
AGENTS.md (or CLAUDE.md) at it.
cd example
npm install
npm testFive tests over one small unit — charging an order through a payment provider — showing the factory-owned Arrange, scenario overrides, a frozen clock, mocked collaborators, and specification-style names.
The tests are worth breaking on purpose: change order.amount === 0 to
order.amount < 0 in src/orderCharge.ts and exactly two tests fail, the two that name
that behaviour. That is what a green suite is supposed to mean, and it is worth
confirming rather than assuming.
One expect() per test. Two assertions is two tests. When a test fails, one
assertion tells you exactly which behaviour regressed; several hide which one broke.
No code comments — a comment is a missing test title. Anything you would write as a comment about what the code does belongs in a test title instead. A comment is static prose that drifts out of sync and nothing fails when it becomes wrong. A test title is bound to an assertion, so when the behaviour changes, the test goes red — the documentation cannot go stale, because the suite enforces it.
The examples use TypeScript with Jest (jest-mock-extended, jest.useFakeTimers()) and
React on the frontend, but nothing in the discipline is framework-specific — the rules
port directly to Vitest, pytest, PHPUnit, RSpec or JUnit. Rewrite the examples in your
stack and keep the rules.
MIT — see LICENSE.