agentsclimarketplace

Test driven development

Skill yyykf/spellbook-skills/skills/test-driven-development

Claude Code and Codex skills for daily engineering workflows: worktrees, merge requests, code review, YApi lookup, and Java DDD guidance.

Install
npx -y skills add yyykf/spellbook-skills --skill test-driven-development

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

One thing to look at

  • 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

What its author says it does

Copied from the file, not written here

Use when implementing a feature, fixing a bug, or changing behavior — write a failing test first, watch it fail, write minimal code to pass, then refactor. Adds Kent Beck's Tidy First (separate structural vs behavioral changes) and a Canon test list. Language-agnostic core; per-language notes under references/languages/. Not for throwaway prototypes, generated code, or pure config changes (ask first).

SKILL.md

10.3 KB, as published. Nobody here has run it

Test-Driven Development (TDD)

Overview

Write the test first. Watch it fail. Write minimal code to pass. Then tidy.

Core principle: If you didn't watch the test fail, you don't know if it tests the right thing.

Announce at start: "I'm using the test-driven-development skill to drive this change test-first."

This skill is language-agnostic. The discipline below holds in every language; concrete framework, runner, and idiom examples live in references/languages/ — load the one matching your project.

Prerequisites

  • A working test runner for your stack (see the matching references/languages/<lang>.md)
  • Ability to run a single test and watch its output
  • For mocks/test doubles, read references/testing-anti-patterns.md first

When to Use

Always:

  • New features
  • Bug fixes
  • Refactoring
  • Behavior changes

Exceptions (ask your human partner first):

  • Throwaway prototypes (then throw them away and restart with TDD)
  • Generated code
  • Pure configuration changes

Thinking "skip TDD just this once"? Stop. That's rationalization.

The Iron Law

NO PRODUCTION CODE WITHOUT A FAILING TEST FIRST

Wrote code before the test? Delete it. Start over.

No exceptions: don't keep it as "reference", don't "adapt" it while writing the test, don't even look at it. Delete means delete. Implement fresh from the test.

Workflow

Phase 1: Build a Test List (Canon TDD)

Before writing any test, list the behaviors you need to cover — the basic case plus every variant you can think of ("what if the input is empty? what if the service times out? what if the key is missing?").

  • This is behavioral analysis, not implementation design.
  • Keep the list visible. Add to it whenever you discover a new case mid-cycle.
  • Turn exactly one item into a concrete test at a time — never convert the whole list up front (reworking speculative tests when an early decision changes is wasted effort).

Phase 2: Red-Green-Refactor — one list item at a time

pick one item  →  RED  →  verify red  →  GREEN  →  verify green  →  REFACTOR  →  back to the list

Run tests in the quietest mode that still surfaces failures. Verbose pass logs burn context you don't need — quiet runners stay silent on green and print full detail on red, so you keep the failures without the noise. Switch to verbose (-v / -s / --nocapture) only when isolating one test's output. Per-language quiet flags are in each references/languages/<lang>.md.

RED — write one failing test

One behavior, a name that describes that behavior (e.g. shouldRetryThreeTimesThenSucceed, not test1), real code over mocks. Work backwards from the assertion. See your language file for concrete framework syntax.

Verify RED — watch it fail (MANDATORY, never skip)

Run the single test. Confirm:

  • It fails, not errors (no typos/missing imports)
  • It fails for the expected reason — the behavior is missing, not the setup is broken

Test passes already? You're testing existing behavior. Fix the test.

GREEN — minimal code to pass

Write the simplest code that makes this test (and all previous tests) pass. No speculative APIs, no extra options, no "while I'm here" cleanup. YAGNI.

Verify GREEN — watch it pass (MANDATORY)

Run the test. Confirm it passes, all previous tests still pass, and output is pristine (no warnings/errors). Test fails? Fix the code, not the test.

REFACTOR — only on green

Remove duplication, improve names, extract helpers. Keep every test green. Don't add behavior here — that's the next RED.

Then mark the item done and return to the list. Repeat until the list is empty.

Phase 3: Tidy First — separate structural from behavioral changes

Kent Beck's distinction. Every change is one of two kinds — never mix them in one commit:

KindWhat it isReversible?
StructuralRearranging without changing behavior: rename, extract method, move code, organize importsUsually yes
BehavioralAdding or changing what the system actually doesNo
  • When you need both, make the structural change first, on green.
  • Validate a structural change didn't alter behavior by running the tests before and after — they stay green throughout.
  • If a change is a tangle of both, untangle it (or redo it) into a structural step then a behavioral step.

Phase 4: Commit Discipline

Commit only when:

  • All tests pass and all compiler/linter warnings are resolved
  • The change is a single logical unit
  • The commit message states whether it is structural or behavioral

Prefer small, frequent commits over large, infrequent ones. (For this repo's commit format, the git-commit skill applies — structural vs behavioral maps cleanly onto its refactor: vs feat:/fix: types.)

Why Test-First (Not Test-After)

Tests written after code pass immediately — and passing immediately proves nothing: they may test the wrong thing, test the implementation instead of behavior, or miss the edge case you forgot. You never saw them catch anything.

Test-after answers "what does this do?" Test-first answers "what should this do?" — and forces edge-case discovery before you implement. 30 minutes of tests-after gives you coverage but loses the proof the test works.

Common Rationalizations

ExcuseReality
"Too simple to test"Simple code breaks. The test takes 30 seconds.
"I'll test after"Tests passing immediately prove nothing.
"Tests after achieve the same goals"Tests-after = "what does this do?" Tests-first = "what should this do?"
"Already manually tested"Ad-hoc ≠ systematic. No record, can't re-run.
"Deleting X hours is wasteful"Sunk cost. Keeping unverified code is the real debt.
"Keep it as reference, write tests first"You'll adapt it. That's testing after. Delete means delete.
"Need to explore first"Fine. Throw away the exploration, restart with TDD.
"Hard to test = need to push through"Hard to test = hard to use. Listen to the test; simplify the design.
"TDD will slow me down"TDD is faster than debugging in production.
"This case is different because…"It isn't. Start over with TDD.

Anti-Cheating Checks

Test-first only works if you don't game it. These failures are especially tempting for AI agents under pressure — treat each as a STOP:

  • Deleting or weakening an assertion to make a test "pass" — make it pass for real.
  • Pasting the computed actual value into the expected slot — that defeats the double-check that gives TDD its value. Derive the expected value independently.
  • Writing a test with no assertion just for coverage.
  • Mixing refactoring into the green step — two hats: make it run, then make it right.
  • Branching production code on test-only artifacts (env flags, test IDs) to fake green.

For bug fixes, add at least one test that reproduces the bug and fails first — never fix a bug without a failing test that proves the fix.

Red Flags — STOP and start over

  • Code written before the test
  • Test passes on the very first run
  • Can't explain why the test failed
  • "I already manually tested it"
  • "It's about the spirit, not the ritual"
  • "Keep as reference" / "adapt the existing code"
  • Tidied and changed behavior in the same commit
  • Edited the test to match the code instead of the code to match the test

Language-Specific Guidance

The discipline above is the same everywhere. For framework choice, runner commands, idioms, and language-specific anti-patterns, load only the file matching your project — and only when you actually need that detail:

Project languageRead
Javareferences/languages/java.md
TypeScript / JavaScriptreferences/languages/typescript.md
Pythonreferences/languages/python.md
Goreferences/languages/go.md
Rustreferences/languages/rust.md

No file for your language? The core skill is sufficient — apply the same red-green-refactor and Tidy First discipline with your stack's idiomatic runner.

Testing Anti-Patterns

When adding mocks or test utilities, read references/testing-anti-patterns.md — cross-language pitfalls like testing mock behavior instead of real behavior, test-only methods on production classes, and incomplete mocks.

When Stuck

ProblemSolution
Don't know how to test itWrite the wished-for API in the test first. Ask your human partner.
Test is too complicatedThe design is too complicated. Simplify the interface.
Must mock everythingCode is too coupled. Use dependency injection.
Test setup is hugeExtract helpers; if still complex, the design needs simplifying.

Verification Checklist

Before marking work complete:

  • Every new behavior has a test
  • Watched each test fail first, for the expected reason
  • Wrote minimal code to pass each test
  • All tests pass; output is pristine (no warnings/errors)
  • Tests use real code (mocks only when unavoidable; see anti-patterns)
  • Edge cases from the test list are covered
  • Structural and behavioral changes are in separate commits

Can't check every box? You skipped TDD. Start over.

Attribution

  • Red-green-refactor discipline, the Iron Law, rationalization/anti-pattern tables, and testing-anti-patterns.md are adapted from superpowers (MIT).
  • The Canon test list, Tidy First (structural vs behavioral separation), and commit discipline are from Kent Beck — Canon TDD and Augmented Coding: Beyond the Vibes (tidyfirst.substack.com).

Gives 4 of the 12 instructions most tdd skills give

Counted across 439 of the 443 authors here whose files we hold, read 2026-08-06

  • write minimal code to pass the testhere, and in 302 of 439, across 218 files
  • write a failing test firstin 176 of 439, across 112 files
  • refactor code only after tests passhere, and in 171 of 439, across 101 files
  • watch the test fail before writing codehere, and in 142 of 439, across 93 files
  • test one behavior per testin 106 of 439, across 44 files
  • refactor code while keeping tests greenin 99 of 439, across 86 files
  • delete code written before testshere, and in 98 of 439, across 54 files
  • run tests after each refactor stepin 85 of 439, across 54 files
  • Use real code instead of mocks unless unavoidablein 64 of 439, across 21 files
  • confirm the test fails for the right reasonin 64 of 439, across 60 files
  • reproduce bugs with a test before fixingin 53 of 439, across 36 files
  • write tests before implementationin 48 of 439, across 39 files

Said here and by no other author read

  • convert one list item into a test at a time
  • commit only when all tests and linter checks pass

Grouped from the skills themselves: near-identical wordings counted once, and counted by distinct author, so one author publishing three of these counts once.

Keep looking

Skills are one crate of 328,083. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.