description: Enforce test-driven development workflow. Scaffold interfaces, generate tests FIRST, then implement minimal code to pass. Ensure 80%+ coverage.
TDD Command
This command invokes the tdd-guide agent to enforce test-driven development methodology.
What This Command Does
- •Scaffold Interfaces - Define types/interfaces first
- •Generate Tests First - Write failing tests (RED)
- •Implement Minimal Code - Write just enough to pass (GREEN)
- •Refactor - Improve code while keeping tests green (REFACTOR)
- •Verify Coverage - Ensure 80%+ test coverage
When to Use
Use /tdd when:
- •Implementing new features
- •Adding new functions/components
- •Fixing bugs (write test that reproduces bug first)
- •Refactoring existing code
- •Building critical business logic
How It Works
The tdd-guide agent will:
- •Define interfaces for inputs/outputs
- •Write tests that will FAIL (because code doesn't exist yet)
- •Run tests and verify they fail for the right reason
- •Write minimal implementation to make tests pass
- •Run tests and verify they pass
- •Refactor code while keeping tests green
- •Check coverage and add more tests if below 80%
TDD Cycle
code
RED → GREEN → REFACTOR → REPEAT RED: Write a failing test GREEN: Write minimal code to pass REFACTOR: Improve code, keep tests passing REPEAT: Next feature/scenario
Example Usage
code
User: /tdd I need a function to calculate market liquidity score
Agent (tdd-guide):
# TDD Session: Market Liquidity Score Calculator
## Step 1: Define Interface (SCAFFOLD)
```typescript
// lib/liquidity.ts
export interface MarketData {
totalVolume: number
bidAskSpread: number
activeTraders: number
lastTradeTime: Date
}
export function calculateLiquidityScore(market: MarketData): number {
// TODO: Implementation
throw new Error('Not implemented')
}
Step 2: Write Failing Test (RED)
typescript
// lib/liquidity.test.ts
import { calculateLiquidityScore } from './liquidity'
describe('calculateLiquidityScore', () => {
it('should return high score for liquid market', () => {
const market = {
totalVolume: 100000,
bidAskSpread: 0.01,
activeTraders: 500,
lastTradeTime: new Date()
}
const score = calculateLiquidityScore(market)
expect(score).toBeGreaterThan(80)
expect(score).toBeLessThanOrEqual(100)
})
it('should return low score for illiquid market', () => {
const market = {
totalVolume: 100,
bidAskSpread: 0.5,
activeTraders: 2,
lastTradeTime: new Date(Date.now() - 86400000) // 1 day ago
}
const score = calculateLiquidityScore(market)
expect(score).toBeLessThan(30)
expect(score).toBeGreaterThanOrEqual(0)
})
it('should handle edge case: zero volume', () => {
const market = {
totalVolume: 0,
bidAskSpread: 0,
activeTraders: 0,
lastTradeTime: new Date()
}
const score = calculateLiquidityScore(market)
expect(score).toBe(0)
})
})
Step 3: Run Tests - Verify FAIL
bash
npm test lib/liquidity.test.ts
FAIL lib/liquidity.test.ts
✕ should return high score for liquid market (2 ms)
Error: Not implemented
1 test failed, 0 passed
✅ Tests fail as expected. Ready to implement.
Step 4: Implement Minimal Code (GREEN)
typescript
// lib/liquidity.ts
export function calculateLiquidityScore(market: MarketData): number {
// Handle zero volume edge case
if (market.totalVolume === 0) {
return 0
}
// Calculate component scores (0-100 scale)
const volumeScore = Math.min(market.totalVolume / 1000, 100)
const spreadScore = Math.max(100 - (market.bidAskSpread * 1000), 0)
const traderScore = Math.min(market.activeTraders / 10, 100)
// Recent activity bonus
const hoursSinceLastTrade = (Date.now() - market.lastTradeTime.getTime()) / (1000 * 60 * 60)
const recencyScore = Math.max(100 - (hoursSinceLastTrade * 10), 0)
// Weighted average
const score = (
volumeScore * 0.4 +
spreadScore * 0.3 +
traderScore * 0.2 +
recencyScore * 0.1
)
return Math.min(Math.max(score, 0), 100) // Clamp to 0-100
}
Step 5: Run Tests - Verify PASS
bash
npm test lib/liquidity.test.ts PASS lib/liquidity.test.ts ✓ should return high score for liquid market (3 ms) ✓ should return low score for illiquid market (2 ms) ✓ should handle edge case: zero volume (1 ms) 3 tests passed
✅ All tests passing!
Step 6: Refactor (IMPROVE)
typescript
// lib/liquidity.ts - Refactored with constants and better readability
const WEIGHTS = {
VOLUME: 0.4,
SPREAD: 0.3,
TRADERS: 0.2,
RECENCY: 0.1,
} as const
const SCALE_FACTORS = {
VOLUME: 1000,
SPREAD: 1000,
TRADERS: 10,
RECENCY_PENALTY: 10,
} as const
function clamp(value: number, min: number, max: number): number {
return Math.min(Math.max(value, min), max)
}
export function calculateLiquidityScore(market: MarketData): number {
if (market.totalVolume === 0) return 0
const volumeScore = Math.min(market.totalVolume / SCALE_FACTORS.VOLUME, 100)
const spreadScore = clamp(100 - (market.bidAskSpread * SCALE_FACTORS.SPREAD), 0, 100)
const traderScore = Math.min(market.activeTraders / SCALE_FACTORS.TRADERS, 100)
const hoursSinceLastTrade = (Date.now() - market.lastTradeTime.getTime()) / (1000 * 60 * 60)
const recencyScore = clamp(100 - (hoursSinceLastTrade * SCALE_FACTORS.RECENCY_PENALTY), 0, 100)
const weightedScore =
volumeScore * WEIGHTS.VOLUME +
spreadScore * WEIGHTS.SPREAD +
traderScore * WEIGHTS.TRADERS +
recencyScore * WEIGHTS.RECENCY
return clamp(weightedScore, 0, 100)
}
Step 7: Verify Tests Still Pass
bash
npm test lib/liquidity.test.ts PASS lib/liquidity.test.ts ✓ should return high score for liquid market (3 ms) ✓ should return low score for illiquid market (2 ms) ✓ should handle edge case: zero volume (1 ms) 3 tests passed
✅ Refactoring complete, tests still passing!
Step 8: Check Coverage
bash
npm test -- --coverage lib/liquidity.test.ts File | % Stmts | % Branch | % Funcs | % Lines ---------------|---------|----------|---------|-------- liquidity.ts | 100 | 100 | 100 | 100 Coverage: 100% ✅ (Target: 80%)
✅ TDD session complete!
code
## TDD Best Practices **DO:** - ✅ Write the test FIRST, before any implementation - ✅ Run tests and verify they FAIL before implementing - ✅ Write minimal code to make tests pass - ✅ Refactor only after tests are green - ✅ Add edge cases and error scenarios - ✅ Aim for 80%+ coverage (100% for critical code) **DON'T:** - ❌ Write implementation before tests - ❌ Skip running tests after each change - ❌ Write too much code at once - ❌ Ignore failing tests - ❌ Test implementation details (test behavior) - ❌ Mock everything (prefer integration tests) ## Test Types to Include **Unit Tests** (Function-level): - Happy path scenarios - Edge cases (empty, null, max values) - Error conditions - Boundary values **Integration Tests** (Component-level): - API endpoints - Database operations - External service calls - React components with hooks **E2E Tests** (use `/e2e` command): - Critical user flows - Multi-step processes - Full stack integration ## Coverage Requirements - **80% minimum** for all code - **100% required** for: - Financial calculations - Authentication logic - Security-critical code - Core business logic ## Important Notes **MANDATORY**: Tests must be written BEFORE implementation. The TDD cycle is: 1. **RED** - Write failing test 2. **GREEN** - Implement to pass 3. **REFACTOR** - Improve code Never skip the RED phase. Never write code before tests. ## Integration with Other Commands - Use `/plan` first to understand what to build - Use `/tdd` to implement with tests - Use `/build-and-fix` if build errors occur - Use `/code-review` to review implementation - Use `/test-coverage` to verify coverage ## Related Agents This command invokes the `tdd-guide` agent located at: `~/.claude/agents/tdd-guide.md` And can reference the `tdd-workflow` skill at: `~/.claude/skills/tdd-workflow/`