Tdd
Test-Driven Development workflow. Use when the user asks to work test-first, says "tdd", "/tdd", "write tests first", "red green refactor", "test-driven", or explicitly wants failing tests before implementation. Also trigger when the user says "add tests for X then implement" or "start with a test". Do NOT trigger on general coding requests that don't mention test-first intent.From its SKILL.md
npx -y skills add Stoica-Mihai/claude-skills --skill tddAssembled 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.
SKILL.md
5.9 KB, ~1.2k tokens by cl100k_base, as published. Nobody here has run it
Test-Driven Development
TDD uses tests as a design tool. The test suite is a byproduct — the real output is clean design that emerges from writing tests first. Code is only written to satisfy a failing test.
Before Starting
Gather context before writing anything. A wrong assumption means wrong tests.
- Find existing tests. Match their framework and style exactly. Only ask about tooling if nothing exists yet.
- Read code this task integrates with. Discover interfaces rather than inventing them.
- Clarify behavior if vague. If the request is ambiguous ("add authentication"), ask for a concrete scenario: "What should happen when a user logs in with the wrong password?" One focused question beats a checklist.
The Cycle: Red -> Green -> Refactor
Every unit of work follows three steps. Never skip the third.
Red — Write a failing test
- Pick the next smallest piece of behavior
- Write a test that will pass once that behavior exists
- Assert what you actually expect, not a placeholder. If you don't know the
exact value (e.g., a specific error message string), assert the contract
you care about (e.g., "raises
ValueError") rather than guess. Tweaking the assertion later to match whatever the implementation happens to emit is test-after, not test-first — see Pitfalls. - Run it — confirm it fails for the right reason (not a syntax error or import failure)
- If writing the test is hard, that's a design signal: the interface isn't clear yet
Green — Minimal code to pass
- Write only enough production code to make the failing test pass
- Inelegant or hardcoded is fine here — correctness first
- Run all tests — the new one passes and nothing else broke
Refactor — Clean up, behavior unchanged
- Improve names, remove duplication, simplify logic
- Refactor both production code and test code
- Run tests after every small change
- This step is mandatory. Skipping it turns TDD into messy code accumulation
Repeat for each new behavior.
Picking What to Test Next
Before writing any code, list the scenarios:
- What's the simplest behavior that must exist?
- What are the edge cases and boundaries?
- What should happen on invalid input?
Work simplest to most complex. Each test should force a small, specific generalization in the production code. As tests get more specific, the code gets more generic — if logically equivalent cases wouldn't pass without changes, the production code is still too specific.
For bug fixes: write a test that reproduces the bug first (it fails), fix it (it passes), refactor. The test is regression protection forever.
Test Structure: Arrange -> Act -> Assert
Arrange (Given): set up the object/state under test
Act (When): call the behavior being tested
Assert (Then): verify the result matches expectation
One behavior per test. Multiple assertions are fine if they verify the same behavior — split the test if they don't.
Test Doubles
Default to real objects. Only introduce doubles when the real dependency is:
- Slow (database, network, filesystem, external API)
- Non-deterministic (current time, randomness, third-party service)
- Hard to set up to the required state
Prefer the classical (Detroit) approach: verify state (what changed), not interactions (what was called). Over-mocking couples tests to implementation and breaks on refactoring.
Types: stub (canned return value), mock (verifies calls happened), fake (simplified working implementation), spy (records calls for later assertion).
Special Cases
Legacy code without tests
You can't safely refactor untested code. The approach:
- Write characterization tests that capture current behavior (even if buggy)
- Once covered, modify using normal Red-Green-Refactor
- For known bugs: write a test exposing the bug, then fix it
Spikes (unclear requirements)
TDD requires knowing what "correct" looks like. If you don't:
- Do a spike — exploratory code, no tests, to understand the problem
- Throw the spike away
- Write the real implementation test-first, informed by what you learned
Never let spike code become production code.
The Test Pyramid
/\
/E2E\ few, slow — critical user journeys only
/------\
/ Integr \ moderate — components work together
/----------\
/ Unit (TDD)\ many, fast, cheap — TDD's home
/--------------\
TDD unit tests are the foundation but not sufficient alone. Combine with integration and acceptance tests for full coverage.
Pitfalls
| Pitfall | Fix |
|---|---|
| Skipping refactor step | It's mandatory — the #1 TDD failure mode |
| Tests depending on each other | Each test must be fully independent |
| Testing implementation, not behavior | Test interfaces and outputs, not internal calls |
| Over-mocking | Default to real objects; mock only what's genuinely awkward |
| Writing code before a failing test | If there's no red, go back and write the test |
| Editing the test's expected value to match what the implementation produced | Tests specify the contract; implementation conforms to tests. If the assertion was wrong or over-specific, change it deliberately (back to red, then green again) — not silently while debugging to green. If the exact value was incidental, assert the looser contract (type, shape, key invariant) instead of pinning a string you guessed at. |
What ships with it
Read from the repository
Just SKILL.md. No reference files, no scripts.
Gives 4 of the 12 instructions most tdd skills give in ~1.2k tokens
Counted across 439 of the 443 authors here whose files we hold, read 2026-08-07
- Write minimal code to pass the testin 304 of 439, across 222 files
- Write a failing test firstin 174 of 439, across 111 files
- Refactor code only after tests passhere, and in 172 of 439, across 102 files
- Watch the test fail before writing codein 145 of 439, across 97 files
- Test one behavior per testhere, and in 108 of 439, across 46 files
- Refactor code while keeping tests greenin 100 of 439, across 88 files
- Delete code written before testsin 99 of 439, across 55 files
- Run tests after each refactor stepin 88 of 439, across 57 files
- Confirm the test fails for the right reasonhere, and in 66 of 439, across 62 files
- Use real code instead of mocks unless unavoidablein 60 of 439, across 17 files
- Reproduce bugs with a test before fixinghere, and in 53 of 439, across 36 files
- Write tests before implementationin 51 of 439, across 43 files
Said here and by no other author read
- assert the contract you care about rather than guessing values
- default to real objects over test doubles
- prefer verifying state over verifying interactions
- never let spike code become production code
Grouped from the skills themselves: near-identical wordings counted once, and counted by distinct author, so one author publishing three of these counts once. Length counted with cl100k_base; the agent that loads this file may tokenize it differently.