---
name: tdd-workflow
description: Test-Driven Development workflow. Write the test first, watch it fail, write minimal code to pass, then refactor. Use when implementing any feature or bugfix where code quality and correctness matter. Enforces the red-green-refactor cycle.
triggers:
  - TDD
  - test driven
  - write tests first
  - red green refactor
  - implement with tests
---

# Test-Driven Development

## The Iron Law

```
NO PRODUCTION CODE WITHOUT A FAILING TEST FIRST
```

Write code before the test? Delete it. Start over. No exceptions.

## When to Use

**Always use for:**
- New features
- Bug fixes (write a test that reproduces the bug first)
- Refactoring (ensure tests pass before AND after)
- Behavior changes

**Exceptions (confirm with user first):**
- Throwaway prototypes
- Generated/scaffolded code
- Configuration files
- One-off scripts

## The Red-Green-Refactor Cycle

### RED: Write a Failing Test

Write ONE minimal test showing what SHOULD happen.

**Good test characteristics:**
- Tests behavior, not implementation
- Has a clear, descriptive name
- Tests one thing only
- Fails for the RIGHT reason (not a syntax error)

```python
# GOOD: Tests behavior
def test_retry_failed_operations_three_times():
    attempts = 0
    def failing_operation():
        nonlocal attempts
        attempts += 1
        raise ConnectionError("timeout")
    
    with pytest.raises(ConnectionError):
        retry(failing_operation, max_retries=3)
    
    assert attempts == 3

# BAD: Tests implementation details
def test_retry_calls_sleep():
    ...  # Brittle, breaks on refactor
```

**Verify the test fails correctly:**
- Run it. It MUST fail.
- The failure message should clearly indicate what is missing.
- If it passes immediately, the test is wrong or the feature already exists.

### GREEN: Write Minimal Code to Pass

Write the LEAST code that makes the test pass. Nothing more.

**Rules:**
- Do not write code "you'll need later"
- Do not handle edge cases not yet tested
- Do not optimize
- Do not refactor
- Just make the test green

```python
# Minimal implementation to pass the test above
def retry(operation, max_retries=3):
    for attempt in range(max_retries):
        try:
            return operation()
        except Exception:
            if attempt == max_retries - 1:
                raise
```

**Verify:**
- Run the test. It MUST pass.
- Run ALL tests. Nothing else should break.

### REFACTOR: Clean Up (While Staying Green)

Now improve the code without changing behavior:
- Remove duplication
- Improve naming
- Extract functions/classes
- Simplify logic

**Rules during refactor:**
- Run tests after EVERY change
- If tests break, undo immediately
- Do not add new behavior (that requires a new RED test)

## TDD Workflow for Bug Fixes

1. **Reproduce**: Write a test that demonstrates the bug (it should FAIL)
2. **Verify RED**: Confirm the test fails for the right reason
3. **Fix**: Write minimal code to make the test pass
4. **Verify GREEN**: All tests pass including the new one
5. **Refactor**: Clean up if needed

This guarantees the bug cannot silently return.

## TDD Workflow for Features

1. **Start with the simplest case**: What is the most basic behavior?
2. **Write one test**: Just that one case
3. **Make it pass**: Minimal code
4. **Next case**: What is the next simplest behavior?
5. **Repeat**: Build up complexity test by test

## Common Mistakes

| Mistake | Fix |
|---------|-----|
| Writing too many tests before any code | One test at a time |
| Making the test too complex | Test ONE behavior per test |
| Writing code before the test | Delete it, start over |
| Not running tests after refactor | Run after every change |
| Testing implementation, not behavior | Ask "what should happen?" not "how does it work?" |
| Skipping RED verification | Always confirm the test fails first |

## Test Organization

```
project/
├── src/
│   └── module.py
└── tests/
    ├── unit/
    │   └── test_module.py      # Fast, isolated
    ├── integration/
    │   └── test_module_api.py  # Tests boundaries
    └── conftest.py             # Shared fixtures
```

## Output

When implementing with TDD, show:
1. The failing test (RED) with its failure output
2. The minimal implementation (GREEN) with passing output
3. Any refactoring done (REFACTOR) with confirmation tests still pass
4. Summary of what was built and tested
