| name | tdd |
| description | TDD workflow skill enforcing RED to GREEN to REFACTOR. Use when implementing any feature test-first, writing unit or integration tests, or building with a test-heavy stack like Jest, Vitest, pytest, or RSpec. Prevents writing implementation before a failing test exists. |
TDD Skill
The Only Rule
Never write implementation code without a failing test that demands it.
This rule has no exceptions. If you find yourself writing a function before a test, stop, write the test first, watch it fail, then write the function.
The Cycle
RED → GREEN → REFACTOR → repeat
Each cycle is one behavior, not one file. Keep cycles small.
Phase 1: RED — Write a Failing Test
-
State the behavior in plain English first:
"A logged-in user can view their order history"
-
Write the smallest test that captures this behavior:
it('returns order history for authenticated user', async () => {
const user = await createTestUser({ authenticated: true });
const response = await request(app)
.get('/api/orders')
.set('Authorization', `Bearer ${user.token}`);
expect(response.status).toBe(200);
expect(response.body.orders).toBeInstanceOf(Array);
});
-
Run the test suite and confirm it FAILS:
npx vitest run --reporter=verbose
-
If the test passes without implementation, the test is wrong. Delete it and reconsider.
Exit criteria: At least one clearly failing test.
Phase 2: GREEN — Make It Pass (Minimal Code Only)
-
Write the minimum code needed to make the test pass — no more, no less
- Hardcoded return values are acceptable temporarily
- No premature abstractions
- No "while I'm here" improvements
-
Run the full test suite:
npx vitest run
-
If new failures appear, the implementation broke something. Fix it before continuing.
-
Do not refactor yet — getting to green is the only goal of this phase.
Exit criteria: All tests pass, including your new one.
Phase 3: REFACTOR — Improve Without Breaking
Only after tests are green:
- Eliminate duplication — extract shared logic, merge similar patterns
- Improve naming — variables, functions, classes should be self-documenting
- Simplify conditionals — if you need a comment to explain an
if, refactor it
- Remove dead code — no commented-out code, no unused variables
- Apply abstractions — only when the same logic appears 3+ times
After every refactor, run tests:
npx vitest run
Tests must remain green throughout. If they go red, undo the refactor.
Exit criteria: Tests still green, code is cleaner than before.
Repeat
Go back to Phase 1 with the next behavior.
Test Quality Checklist
Before calling a test "done":
When TDD Feels Hard
"I don't know what to test" — Write the interface first (function signature, API contract), then test that contract.
"The test requires too much setup" — That's a design signal. Decouple the code, reduce dependencies.
"I need to test a private function" — Don't. Test the public behavior that exercises it.
"I'll write tests after" — No. Green code without a test is unverified code. Do not skip the red phase.