TDD Command
Overview
Use this skill to execute the existing workflow migrated from tdd.md.
Follow the playbook below and adapt commands to the current repository context.
Playbook
Codex Invocation Mapping
If this playbook references slash commands (for example /plan or /tdd), treat them as skill names in Codex. Ask Codex directly to run the equivalent skill workflow.
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/`