---
title: "Test-Driven Development"
type: "architectural-pattern"
slug: "test-driven-development"
url: "http://localhost:3000/en/architectural-patterns/test-driven-development.md"
also_known_as: "TDD, Red-Green-Refactor"
description: "A development discipline where you write a failing test before the code that makes it pass, then refactor — letting tests drive the design in short, tight cycles."
languages: ["python"]
---
# Test-Driven Development

_Also known as: TDD, Red-Green-Refactor_

> A development discipline where you write a failing test before the code that makes it pass, then refactor — letting tests drive the design in short, tight cycles.

## Intent

Drive the design and verify the correctness of code by writing a failing test for each small piece of behavior _before_ writing the code that satisfies it, then improving the design while the tests keep you safe.

## Problem

Code written without tests is risky to change: there is no quick way to know whether an edit broke something. Tests written _after_ the fact tend to be shallow, shaped to fit code that may already be hard to test, and they rarely influence the design.

Without a forcing function, designs also tend to grow tangled and hard to exercise in isolation.

## Solution

Work in a short **Red-Green-Refactor** cycle:

1. **Red** — write a small test for the next bit of behavior and watch it fail.
2. **Green** — write the simplest code that makes the test pass, even if it is ugly.
3. **Refactor** — clean up the code (and the tests) now that they are green, with the suite guarding against regressions.

Repeat in minutes-long loops. Because tests come first, the code is testable by construction and the suite documents the intended behavior.

## Structure

* **The cycle** — Red → Green → Refactor, repeated continuously.
* **Test list** — the running list of behaviors still to cover.
* **Arrange–Act–Assert** — the shape of a focused unit test.
* **Unit under test** — the small slice of behavior each test pins down.

## Applicability

* Use it for code with real **logic and branching**, and for long-lived code that will change often.
* Especially valuable where a fast feedback loop and regression safety matter.
* **Less suited** to throwaway spikes or exploratory UI work where the design is still in flux.

## How to Implement

1. Pick the next small behavior from your test list.
2. Write a test that asserts it, and run the suite to see it fail (red).
3. Write the minimum code needed to pass; run the suite (green).
4. Refactor production and test code while keeping the suite green.
5. Repeat, adding behaviors to the list as you discover them.

## Pros

* High test coverage as a by-product, not an afterthought.
* Fast feedback catches regressions within seconds.
* Encourages decoupled, testable designs.
* The suite acts as living, executable documentation.

## Cons

* Slower initial pace, and a genuine learning curve.
* Can over-emphasize isolated units while missing integration gaps.
* Tests are code too — they must be maintained and refactored.
* Not a substitute for exploratory, integration or end-to-end testing.
## Relations

**Related patterns**

- [Spec-Driven Development](/en/architectural-patterns/spec-driven-development.md)

## Code Examples

### python

```python
# Red: write the failing test first.
def test_slugify_lowercases_and_hyphenates():
    assert slugify('Hello World') == 'hello-world'

# Green: the simplest code that passes.
def slugify(text: str) -> str:
    return text.lower().replace(' ', '-')

# Refactor later (e.g. strip punctuation) with the test as a safety net.
```

