test-driven-development

Automate the Red-Green-Refactor cycle with mandatory failing tests before production code.

270k|24.1k|Updated Oct 9, 2025
One-click install
npx skills add https://github.com/obra/superpowers --skill test-driven-development-obra
Or copy as Structured Prompt for Agent
Please help me install this Agent Skill.
Skill: test-driven-development
Source: https://github.com/obra/superpowers/tree/main/skills/test-driven-development
Command: npx skills add https://github.com/obra/superpowers --skill test-driven-development-obra

SYSTEM DOCUMENTATION & REQUIREMENTS

What problem does it solves? This Skill eliminates the risk of writing untested code and ensures your tests genuinely verify behavior. It prevents the common pitfall of writing tests after implementation, which often leads to incomplete or incorrect coverage, saving you debugging time and rework.

Core Features & Use Cases

  • RED-GREEN-REFACTOR Cycle: Guides you through the fundamental TDD process: write a failing test, then minimal code to pass it, and finally refactor for cleanliness.
  • Behavior-Driven Testing: Forces you to focus on the desired behavior of your code before implementation, ensuring tests are relevant and effective.
  • Regression Prevention: Ensures every bug fix or new feature has a test that proves it works and prevents future regressions, building a robust codebase.
  • Use Case: When implementing a new user authentication flow, you'd first write a test for a successful login, watch it fail, then write the minimal code to make it pass, ensuring your feature is correctly tested from the start.

Quick Start

Example: Implementing a retry operation

You: I'm using the test-driven-development skill to implement this feature.

RED - Write failing test

test('retries failed operations 3 times', async () => { let attempts = 0; const operation = () => { attempts++; if (attempts < 3) throw new Error('fail'); return 'success'; }; const result = await retryOperation(operation); expect(result).toBe('success'); expect(attempts).toBe(3); });

Verify RED - Watch it fail (MANDATORY)

npm test path/to/test.test.ts # Expected: FAIL (e.g., "retryOperation not defined")

GREEN - Write minimal code

async function retryOperation<T>(fn: () => Promise<T>): Promise<T> { for (let i = 0; i < 3; i++) { try { return await fn(); } catch (e) { if (i === 2) throw e; } } throw new Error('unreachable'); }

Verify GREEN - Watch it pass (MANDATORY)

npm test path/to/test.test.ts # Expected: PASS

REFACTOR - Clean up (e.g., improve variable names, extract helpers)

Frequently Asked Questions about test-driven-development

High-intent search queries and answers about installing and using this skill.

FAQPage Schema
How do I write tests before implementing code?

Test-driven development starts by writing a failing test that describes the desired behavior, then writing minimal code to pass it. This Red-Green-Refactor cycle ensures your implementation matches the test specification from the start, catching bugs early and preventing untested code.

Why should I write tests first instead of after implementation?

Writing tests after code often results in incomplete coverage and tests that verify what was built rather than what should be built. TDD forces you to define behavior upfront, ensuring tests are relevant, complete, and genuinely validate that your code works as intended.

How does the Red-Green-Refactor cycle work?

Red: write a failing test. Green: write minimal code to pass it. Refactor: clean up the code while tests remain passing. This three-step cycle ensures every feature has test coverage, code is intentional, and technical debt is managed incrementally.

Can I use TDD for bug fixes and refactoring?

Yes. TDD applies to bug fixes by writing a test that reproduces the bug before fixing it, and to refactoring by ensuring tests pass throughout code cleanup. This prevents regressions and proves the fix or refactor works correctly.

What's the difference between TDD and writing tests after code?

TDD writes tests first to define behavior, then implements code to satisfy tests. Post-implementation testing often misses edge cases and tests the code as written rather than as intended. TDD catches failures earlier and produces more robust, maintainable code.

How does TDD prevent regressions?

Every bug fix and new feature gets a test that proves it works before code is merged. This test suite runs continuously, catching any change that breaks existing behavior and ensuring your codebase remains stable as it grows.