Use when implementing complex logic that needs test coverage - write the test first, watch it fail, write minimal code to pass; ensures tests actually verify behavior by requiring failure first; NOT for UI components, simple CRUD, or straightforward code
View on GitHubSelect agents to install to:
npx add-skill https://github.com/udecode/dotai/blob/main/.claude-plugin/plugins/test/skills/tdd/SKILL.md -a claude-code --skill tddInstallation paths:
.claude/skills/tdd/# Test-Driven Development (TDD)
## Overview
Write the test first. Watch it fail. Write minimal code to pass.
**Core principle:** If you didn't watch the test fail, you don't know if it tests the right thing.
**When to use:** Only for complex logic where bugs are likely, or when user explicitly requests tests.
## When to Use
**Use TDD when:**
1. **User explicitly requests tests**
2. **Complex logic where bugs are likely:**
- Complex algorithms
- Business logic with edge cases
- Data transformations
- Critical paths that could break silently
**Skip TDD for:**
- ❌ UI components (React components, hooks)
- ❌ Simple CRUD operations
- ❌ Straightforward mappings
- ❌ Anything you're 100% certain is correct
- ❌ Throwaway prototypes
- ❌ Configuration files
**Verification alternatives when skipping:**
- Typecheck with `npm run typecheck`
- Lint with `npm run lint`
- Manual testing for UI changes
- Code review confidence
## The Rule (When Using TDD)
```
WHEN WRITING TESTS: NO CODE WITHOUT A FAILING TEST FIRST
```
**When you've decided to use TDD** (complex logic, user request):
Write code before the test? Delete it. Start over.
**No exceptions when using TDD:**
- 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.
**When NOT using TDD** (UI, simple code):
- Write code directly
- Verify with typecheck/lint
- Skip the test
## Red-Green-Refactor
```dot
digraph tdd_cycle {
rankdir=LR;
red [label="RED\nWrite failing test", shape=box, style=filled, fillcolor="#ffcccc"];
verify_red [label="Verify fails\ncorrectly", shape=diamond];
green [label="GREEN\nMinimal code", shape=box, style=filled, fillcolor="#ccffcc"];
verify_green [label="Verify passes\nAll green", shape=diamond];
refactor [label="REFACTOR\nClean up", shape=box, style=filled, fillcolor="#ccccff"];
next [label="Next", shape=ellipse];
red -> verify_red;
verify_red