Testing with pytest & Next Steps
Why pytest
pytest is the de-facto Python test framework: plain functions, plain assert, brilliant failure output. Install it and create a test file — pytest auto-discovers anything named test_*.py:
pip install pytest# cart.py
def add_item(cart, item, price):
if price < 0:
raise ValueError("price cannot be negative")
cart[item] = cart.get(item, 0) + price
return cart
def total(cart):
return sum(cart.values())# test_cart.py
from cart import add_item, total
def test_add_item():
cart = add_item({}, "course", 199)
assert cart == {"course": 199}
def test_total_empty():
assert total({}) == 0pytest # run everything
pytest -v # verbose
pytest -k total # only tests matching "total"When an assert fails, pytest shows both sides of the comparison — no assertEqual boilerplate needed.
Testing Exceptions
import pytest
def test_negative_price_rejected():
with pytest.raises(ValueError, match="negative"):
add_item({}, "course", -5)Parametrize — One Test, Many Cases
@pytest.mark.parametrize("items,expected", [
({}, 0),
({"a": 100}, 100),
({"a": 100, "b": 99}, 199),
])
def test_total(items, expected):
assert total(items) == expectedFixtures — Reusable Setup
@pytest.fixture
def filled_cart():
return {"django": 199, "react": 149}
def test_total_filled(filled_cart): # injected by name
assert total(filled_cart) == 348Fixtures replace setup/teardown methods: tests declare what they need as parameters, pytest builds it. Fixtures can depend on other fixtures, and yield-style fixtures handle teardown.
Habits That Make Tests Worth Having
- Test behaviour through public functions, not private internals.
- Name tests as specifications:
test_negative_price_rejected. - Keep tests fast — a slow suite stops getting run.
- Run pytest in CI on every push so broken code can’t merge.
Where to Go From Here
You now have the full core of Python: types, control flow, functions, the data structures, OOP, modules, files, exceptions, generators, decorators, environments, and tests. Pick a track and build:
- Web — the Django tutorial on this site takes you from models to production deployment.
- Data — the Data Science series (NumPy, pandas, statistics, scikit-learn).
- AI — the AI & ML series, then the LLM Engineering series.
The only way to consolidate a language is to ship something real with it. Pick a project this week and build it end to end.