# Test Driven Development

> Test-Driven Development

- Skill: `kumaran-is/test-driven-development` (Agent Skill, multi-file: 5 files)
- Install (CLI): `npx skillmds@latest add kumaran-is/test-driven-development`
- Raw SKILL.md: https://api.skillmd.com/api/skills/kumaran-is/test-driven-development/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: kumaran-is (https://skillmd.com/u/kumaran-is)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/kumaran-is/test-driven-development

---


# Test-Driven Development

## Iron Law

**NO IMPLEMENTATION WITHOUT A FAILING TEST FIRST**

Write the test. Run it. See it fail (RED). Then implement until it passes (GREEN). Then refactor.

## When TDD Applies

**DO use TDD for:**
- New features and new logic
- Bug fixes (write a test that reproduces the bug first)
- Any code path that has business logic

**DO NOT use TDD for:**
- Config changes, renames, formatting
- Trivial one-line fixes with no logic
- See `leverage-patterns.md` Test-First section for the full rule

## Red-Green-Refactor Cycle

```
RED   -> Write a test that FAILS for the right reason
         Run it. Confirm it fails. If it passes without code -> test is wrong.

GREEN -> Write the MINIMUM code to make the test pass
         No extras. No "while I'm here" additions.

REFACTOR -> Clean up code without changing behavior
            Run tests again. Must still pass.
```

> For verifying regression tests are genuine (not vacuous): see `verification-before-completion` Red-Green protocol.
> For TDD during bug investigation: see `systematic-debugging` Phase 4 — Create Failing Test Case.

## Test Naming Convention

Pattern: `test_<what>_<when>_<expected>` (or `should_<expected>_when_<condition>`)

```
# Java
@Test void createUser_withDuplicateEmail_throwsConflictException()

# NestJS/Jest
it('should throw ConflictException when email already exists', ...)

# Python/pytest
def test_create_user_with_duplicate_email_raises_conflict():

# Flutter
test('createUser throws ConflictException when email is duplicate', ...)
```

## Stack Dispatch

| Stack | Reference File | Load When |
|-------|---------------|-----------|
| Java 21 / Spring Boot WebFlux | `references/tdd-patterns-java.md` | Writing tests for Spring Boot, WebFlux, reactive Java |
| NestJS 11 / TypeScript | `references/tdd-patterns-nestjs.md` | Writing tests for NestJS, TypeScript, Fastify |
| Python 3.14 / FastAPI | `references/tdd-patterns-python.md` | Writing tests for FastAPI, Pydantic, async Python |
| Flutter / Dart | `references/tdd-patterns-flutter.md` | Writing tests for Flutter widgets, Riverpod providers, Dart |

## Quick Checklist

Before claiming a test is real:
- [ ] Test FAILED before implementation (you saw the red output)
- [ ] Test PASSES after implementation (you saw the green output)
- [ ] Test name describes behavior, not implementation
- [ ] One assertion per logical outcome (not 10 assertions in one test)
- [ ] Mocks are used for external dependencies only (not to avoid writing logic)

