Test-Driven Development
TDD is not "writing tests". TDD is using tests to drive design.
The loop
- RED. Write a test that describes the behavior you want. Run it. It must fail — and fail for the right reason (the assertion, not a syntax error).
- GREEN. Write the minimum code to make the test pass. Not the elegant version. Not the general version. The minimum.
- REFACTOR. With the test green, clean up the code. The test keeps you honest — if it goes red, you broke something while cleaning.
Repeat at the next level of detail.
Why failing first matters
A test you never saw fail is not a test. It may be passing for reasons unrelated to your change. The "watch it fail" step is the only proof the test is wired up correctly.
When to write the test
- Before implementation for any new feature.
- Before the fix for any reported bug — the bug report becomes a failing test.
- Before any refactor of untested code — characterize the current behavior first.
When NOT to TDD
- One-shot scripts that will be deleted after running.
- Spikes where you're exploring what is even possible — but throw the spike away and restart with TDD once you know the shape.
- UI pixel-pushing where the test would just assert the DOM you just wrote.
Anti-patterns
- Writing the implementation, then retro-fitting a test that trivially passes.
- Tests that assert
mock.wasCalled()instead of asserting real behavior. - Tests that pass against mocks but not against the real collaborator (integration is where bugs live).
- Skipping refactor because "it works" — the test is license to refactor, use it.
Source
https://github.com/obra/superpowers/blob/main/skills/test-driven-development/SKILL.md