---
name: tdd
description: "TDD with red-green-refactor loop and vertical slices. Triggers: TDD, test-first, red-green-refactor, test driving development."
user-invocable: true
effort: high
argument-hint: "[feature or behavior to implement]"
allowed-tools: Read, Write, Edit, Grep, Glob, Bash, Agent
---

# Test-Driven Development

$ARGUMENTS

Build features using strict RED → GREEN → REFACTOR cycles with vertical slices.

## Usage

```
/tdd [feature or behavior to implement]
```

## The Iron Law

```
NO PRODUCTION CODE WITHOUT A FAILING TEST FIRST
```

Write code before the test? **Delete it. Start over.**

**No exceptions:**
- Don't keep it as "reference"
- Don't "adapt" it while writing tests
- Don't look at it
- Delete means delete

Implement fresh from tests. Period.

**Violating the letter of this rule is violating the spirit of this rule.**

## Philosophy

**Core principle**: Tests verify behavior through public interfaces, not implementation details. Code can change entirely; tests shouldn't.

**Good tests**: Integration-style, exercise real code paths through public APIs. Describe _what_ the system does, not _how_. Read like specifications. Survive refactors.

**Bad tests**: Coupled to implementation. Mock internal collaborators, test private methods, verify through external means. Warning sign: test breaks on refactor but behavior is unchanged.

See [reference/tests.md](reference/tests.md) for examples, [reference/mocking.md](reference/mocking.md) for mocking guidelines.

## Anti-Pattern: Horizontal Slices

**DO NOT write all tests first, then all implementation.**

```
WRONG (horizontal):
  RED:   test1, test2, test3, test4, test5
  GREEN: impl1, impl2, impl3, impl4, impl5

RIGHT (vertical):
  RED→GREEN: test1→impl1
  RED→GREEN: test2→impl2
  RED→GREEN: test3→impl3
```

Tests written in bulk test _imagined_ behavior. Vertical slices let each test respond to what you learned from the previous cycle.

## Workflow

### 1. Planning

Before writing any code:

- [ ] Confirm with user what interface changes are needed
- [ ] Confirm which behaviors to test (prioritize — you can't test everything)
- [ ] Identify opportunities for [deep modules](reference/deep-modules.md)
- [ ] Design interfaces for [testability](reference/interface-design.md)
- [ ] List behaviors to test (not implementation steps)
- [ ] Get user approval

### 2. Tracer Bullet

Write ONE test that confirms ONE thing:

```
RED:   Write test for first behavior → test fails
GREEN: Write minimal code to pass → test passes
```

This proves the path works end-to-end.

### 3. Incremental Loop

For each remaining behavior:

```
RED:   Write next test → fails
GREEN: Minimal code to pass → passes
```

| Rule | Description |
|------|-------------|
| One at a time | One test per cycle |
| Minimal | Only enough code to pass current test |
| No anticipation | Don't code for future tests |
| Behavioral | Tests focus on observable behavior |

### 4. Refactor

After all tests pass, look for [refactor candidates](reference/refactoring.md):

- [ ] Extract duplication
- [ ] Deepen modules (complexity behind simple interfaces)
- [ ] Apply SOLID where natural
- [ ] Run tests after each refactor step

**Never refactor while RED.** Get to GREEN first.

## Checklist Per Cycle

```
[ ] Test describes behavior, not implementation
[ ] Test uses public interface only
[ ] Test would survive internal refactor
[ ] Code is minimal for this test
[ ] No speculative features added
```

## Rules

- One RED→GREEN cycle at a time — never batch
- Tests assert on observable outcomes, not internal state
- Mock only at system boundaries (see [reference/mocking.md](reference/mocking.md))
- Each cycle leaves the codebase in a working state

## Red Flags — STOP and Start Over

If you catch yourself doing ANY of these, **delete the code and restart with TDD**:

- Writing production code before a failing test
- Writing tests after implementation
- Test passes immediately (you're testing existing behavior — fix the test)
- Can't explain why the test failed
- Tests added "later"
- Rationalizing "just this once"
- "I already manually tested it"
- "Keep as reference" or "adapt existing code"

## Common Rationalizations

| Excuse | Reality |
|--------|---------|
| "Too simple to test" | Simple code breaks. Test takes 30 seconds. |
| "I'll test after" | Tests passing immediately prove nothing. |
| "Tests after achieve 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 fallacy. Keeping unverified code is technical debt. |
| "Need to explore first" | Fine. Throw away exploration, start with TDD. |
| "TDD will slow me down" | TDD faster than debugging. Pragmatic = test-first. |
| "This is different because..." | No. Apply the Iron Law. |

## Verification Checklist

Before marking work complete:

- [ ] Every new function/method has a test
- [ ] Watched each test fail before implementing
- [ ] Each test failed for expected reason (feature missing, not typo)
- [ ] Wrote minimal code to pass each test
- [ ] All tests pass
- [ ] Output pristine (no errors, warnings)
- [ ] Tests use real code (mocks only at system boundaries)
- [ ] Edge cases and errors covered

Can't check all boxes? You skipped TDD. Start over.

## Related Skills
- Feature complete? → `/review` to get a code review
- Need to plan the feature first? → `/plan` for task breakdown
- Want a full test coverage sweep? → `/workflow test-coverage`
- Debugging a test failure? → `/debug` for systematic root cause analysis
