Skip to content
Back to skills

Add Unit Test

ASecurity

Use when a ticket asks for new unit tests, or when an acceptance criterion requires test coverage for a function/module/component and none exists. Invoke for "add tests for X", "cover the Y edge case", or raising coverage on a specific unit — one test per criterion that fails if that criterion's behaviour breaks.

  • 2 stars
  • 0 votes
  • 0 copies
  • 1 view
  • Added September 5, 2026
ai-agentstypescriptgonodetestinggitapi

Works with

  • api

Security analysis

A100/100

Scanned September 29, 2026

npx -y skills add tmj-90/gaffer --skill add-unit-test --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Add Unit Test?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Add Unit Test
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/tmj-90-add-unit-test/badge)](https://www.skillsdirectory.com/skills/tmj-90-add-unit-test)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: add-unit-test
description: Use when a ticket asks for new unit tests, or when an acceptance criterion requires test coverage for a function/module/component and none exists. Invoke for "add tests for X", "cover the Y edge case", or raising coverage on a specific unit — one test per criterion that fails if that criterion's behaviour breaks.
stack: []
area: testing
---

# Add a unit test

A unit test earns its place when it would **fail if the behaviour the acceptance
criterion names broke** (Kent Beck's "behavioural" and "structure-insensitive" test
desiderata). The recurring defect in live runs was not missing test files but tests that
never exercised the criterion's own behaviour — they called the function and asserted
something incidental, and the reviewer approved.

## Procedure

1. **Find the unit and its existing tests.** Locate the source file and any sibling test.
   Read one or two existing tests to copy the framework, file naming, location and
   assertion style (Vitest/Jest/`node:test`/pytest/JUnit/`go test`). Call `search_lore`
   for the repo's testing conventions. Never add a second framework or runner.
2. **Map every AC to the behaviour that proves it.** For each criterion write one line:
   _input/state → action → observable outcome_. That outcome is what the test asserts.
   An AC that says "rejects duplicate names" is proven by a duplicate being rejected, not
   by the create function returning something.
3. **Enumerate the cases per behaviour:** the happy path, each branch the AC implies,
   boundary values (0, 1, max, max+1, empty, unicode), and each documented error. If the
   AC is a rule over many inputs ("round-trips", "never throws"), add a property test
   (the `property-based-test` skill).
4. **Write the tests.** One behaviour per test, Arrange-Act-Assert, a name that states the
   behaviour (`rejects a duplicate name with 409`). Include the AC id or wording in the
   test or describe name so the reviewer can map test → criterion. Use real collaborators
   when they are fast and deterministic (a "sociable" unit test); substitute only slow,
   non-deterministic or external ones (network, clock, randomness, filesystem when not the
   subject).
5. **Prove each test can fail (the break-it check).** For every AC test, temporarily break
   the behaviour — invert the condition, return early, drop the write — run the test, see
   it fail for the right reason, then undo the edit and confirm `git diff` shows only your
   intended changes. A test that stays green against broken code is deleted or rewritten.
   (This is manual mutation testing; where the repo has Stryker/mutmut/PIT, run it on the
   unit instead. An independent tester never edits implementation files and skips this.)
6. **Run the repo's test command** from the context packet's verification commands, not
   the tool directly. Iterate until green. If a test reveals a real bug, fix it only when
   the ticket scopes it; otherwise note it.
7. **Evidence and stop.** Use the `record-evidence` skill: one `test_output` row per AC
   naming the command, the pass summary and the test(s) that prove that AC. The runner —
   not you — submits for review.

## Done when

- Every AC in scope has at least one named test that exercises its own behaviour.
- Each of those tests failed under the break-it check and passes on the real code.
- The repo's test command passes in this session, and nothing was skipped to get there.

## TypeScript and async specifics

- **Await everything.** `await` the call and assert on the resolved value, or
  `await expect(fn()).rejects.toThrow(...)`. A floating promise lets the test finish
  before the assertion runs.
- **A meaningful assertion** pins the observable outcome: the returned value, a thrown
  error, state read back through the public API, or a call to a genuine collaborator
  _with the expected arguments_. `expect(mock).toHaveBeenCalled()` on a mock you fully
  control tests the mock, not the unit.
- **Fake time and randomness** (`vi.useFakeTimers()`, injected clock, seeded RNG) so
  timing- and random-dependent behaviour is deterministic.

## Anti-patterns a reviewer will send back

- Tests named after the function (`test createUser`) instead of the behaviour.
- Asserting only `toBeDefined()`, `not.toThrow()`, or a snapshot of whatever came back.
- Mocking the unit under test, or asserting private fields and call counts that pin the
  implementation instead of the outcome.
- A concurrency, persistence or failure AC "covered" by a sequential happy-path unit test —
  those need the real schedule (the `add-integration-test` skill).
- Weakening, skipping (`.skip`, `xit`, `@pytest.mark.skip`) or deleting a test to go green.

## Rules

- Match existing conventions; no new framework, runner or assertion library.
- Keep scope to the ticket; do not refactor source unless an AC requires it.
- Work on the delivery branch the runner prepared (the `create-branch` skill); never a
  protected branch.

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.