Use this skill when writing new features, fixing bugs, or refactoring code. Enforces test-driven development with 80%+ coverage including unit, integration, and E2E tests.
Use this skill when writing new features, fixing bugs, or refactoring code. Enforces test-driven development with 80%+ coverage including unit, integration, and E2E tests.
Test-Driven Development Workflow
This skill ensures all code development follows TDD principles with comprehensive test coverage.
Agent counterpart: Use the tdd-guide agent for interactive, step-by-step TDD guidance during feature development. This skill provides the reference patterns and examples; the agent enforces the workflow.
When to Activate
Writing new features or functionality
Fixing bugs or issues
Refactoring existing code
Adding API endpoints
Creating new components
Setting up coverage thresholds in CI to enforce the 80%+ minimum
Reviewing a PR where tests were written after the implementation (anti-pattern)
Onboarding a developer who is unfamiliar with the Red-Green-Refactor cycle
Core Principles
1. Tests BEFORE Code
ALWAYS write tests first, then implement code to make tests pass.
2. Coverage Requirements
Minimum 80% coverage (unit + integration + E2E)
All edge cases covered
Error scenarios tested
Boundary conditions verified
3. Test Types
Unit Tests
Individual functions and utilities
Component logic
Pure functions
Helpers and utilities
Integration Tests
API endpoints
Database operations
Service interactions
External API calls
E2E Tests (Playwright)
Critical user flows
Complete workflows
Browser automation
UI interactions
TDD Workflow Steps
Step 1: Write User Journeys
As a [role], I want to [action], so that [benefit]
Example:
As a user, I want to search for markets semantically,
so that I can find relevant markets even without exact keywords.
Step 2: Generate Test Cases
For each user journey, create comprehensive test cases:
describe('Semantic Search', () => {
it('returns relevant markets for query', async () => {
// Test implementation
})
it('handles empty query gracefully', async () => {
// Test edge case
})
it('falls back to substring search when Redis unavailable', async () => {
// Test fallback behavior
})
it('sorts results by similarity score', async () => {
// Test sorting logic
})
})
Step 3: Run Tests (They Should Fail)
npm test# Tests should fail - we haven't implemented yet
Step 4: Implement Code
Write minimal code to make tests pass:
// Implementation guided by testsexportasyncfunctionsearchMarkets(query: string) {
// Implementation here
}
Step 5: Run Tests Again
npm test# Tests should now pass
Step 6: Refactor
Improve code quality while keeping tests green:
Remove duplication
Improve naming
Optimize performance
Enhance readability
Step 7: Verify Coverage
npm run test:coverage
# Verify 80%+ coverage achieved
// Resilient to changesawait page.click('button:has-text("Submit")')
await page.click('[data-testid="submit-button"]')
❌ WRONG: No Test Isolation
// Tests depend on each othertest('creates user', () => { /* ... */ })
test('updates same user', () => { /* depends on previous test */ })
✅ CORRECT: Independent Tests
// Each test sets up its own datatest('creates user', () => {
const user = createTestUser()
// Test logic
})
test('updates user', () => {
const user = createTestUser()
// Update logic
})
Continuous Testing
Watch Mode During Development
npm test -- --watch
# Tests run automatically on file changes
Pre-Commit Hook
# Runs before every commit
npm test && npm run lint
For mock patterns (Supabase, Redis, OpenAI, vi.mock patterns) — see skill typescript-testing.
For anti-patterns (code before tests, testing internals, waitForTimeout, chained tests, mocking the SUT), success metrics, and the full reminder — see skill tdd-workflow-advanced.