Test-Driven Development in Python with pytest

Write the test, watch it fail, make it pass. TDD with pytest — the discipline that makes systems boring and reliable.

Test-driven development flips the order: write the test first, watch it fail, then write the code to make it pass. It's the single habit that most improved the reliability of what we ship — we build every system this way.

The red-green-refactor loop

  1. Red — write a failing test.
  2. Green — write the minimum code to pass it.
  3. Refactor — clean up, keeping it green.

Write the failing test first

python
# test_cart.py
from cart import Cart

def test_add_item_increases_total():
    cart = Cart()
    cart.add("widget", price=5.0, qty=2)
    assert cart.total() == 10.0

def test_remove_item():
    cart = Cart()
    cart.add("widget", price=5.0)
    cart.remove("widget")
    assert cart.total() == 0.0

Run it — both fail, because Cart doesn't exist yet. That's the red.

Make it pass

python
# cart.py
class Cart:
    def __init__(self):
        self._items = {}

    def add(self, name, price, qty=1):
        self._items[name] = self._items.get(name, 0) + price * qty

    def remove(self, name):
        self._items.pop(name, None)

    def total(self):
        return sum(self._items.values())
bash
pip install pytest
pytest -q         # 2 passed in 0.01s

Fixtures — shared setup

python
import pytest

@pytest.fixture
def cart():
    c = Cart()
    c.add("widget", price=5.0, qty=2)
    return c

def test_total_with_fixture(cart):
    assert cart.total() == 10.0

Parametrise — many cases, one test

python
@pytest.mark.parametrize("qty,expected", [
    (1, 5.0), (2, 10.0), (0, 0.0), (3, 15.0),
])
def test_total_for_qty(qty, expected):
    cart = Cart()
    cart.add("widget", price=5.0, qty=qty)
    assert cart.total() == expected
Test behaviour, not implementation. If you have to rewrite a test every time you refactor, the test is too tightly coupled.

TDD isn't about more tests — it's about designing code you can prove. We've found the systems that rarely need maintenance are the ones built this way.

Your move

Want us to build this for you?

We turn tutorials like these into production systems every day. Tell us what you need.

Start a project →