pytest
pytest is a testing tool that finds functions whose names start with test_, runs them, and reports every assert that fails.
Last updated: 30 Sep, 2026 · Python 3.14 · pytest 9.1
Every lesson so far checked its code by reading the output. A test does that reading for you, the same way every time. In your project folder, activate the environment from Virtual environments and pip with source .venv/bin/activate and install pytest with pip install pytest.
Syntax:
def test_something():
assert actual == expectedWriting the first tests
Start with categorise from Functions, in its own file:
def categorise(text):
text = text.lower()
if "charged" in text or "refund" in text:
return "billing"
if "parcel" in text or "arrived" in text:
return "shipping"
return "other"Tests go in a file whose name starts with test_:
from triage import categorise
def test_charge_is_billing():
assert categorise("I was charged twice for one order") == "billing"
def test_parcel_is_shipping():
assert categorise("My parcel has not arrived") == "shipping"
def test_password_is_other():
assert categorise("How do I change my password?") == "other"A test is a function whose name starts with test_. assert checks that something is true. If it is, nothing happens; if not, the test fails.
Running pytest
pytest -q... [100%] 3 passed in 0.00s
pytest finds every test_ file and function by itself and runs them. -q keeps the report short: one dot per passing test.
Reading a failing test
A customer writes I want my money back. That is a billing ticket, so add this test to the end of test_triage.py:
def test_money_back_is_billing():
assert categorise("I want my money back") == "billing"pytest -q...F [100%]
================================= FAILURES =================================
________________________ test_money_back_is_billing ________________________
def test_money_back_is_billing():
> assert categorise("I want my money back") == "billing"
E AssertionError: assert 'other' == 'billing'
E
E - billing
E + other
test_triage.py:17: AssertionError
========================= short test summary info ==========================
FAILED test_triage.py::test_money_back_is_billing - AssertionError: asser...
1 failed, 3 passed in 0.01sThe F marks the failure. pytest shows the assert that failed and both sides of it: categorise returned 'other' where the test wanted 'billing'. The other three still pass.
This is the order to work in. The test describes what should happen, it fails, and then you change triage.py until it passes, knowing the three older tests will tell you if the change broke them.
Reading output vs a test
| Reading the output | A pytest test | |
|---|---|---|
| Who checks | You, each time | pytest, every run |
| After a change | Read everything again | pytest -q |
| A broken case | Easy to miss | An F and the failing assert |
Where tests show up in AI code
- Checking the code around a model: parsing, routing, saving results.
- Running on every change in CI, so a broken prompt parser is caught before it ships.
test_*.py and functions named test_*. A test called check_billing is silently skipped.Related
- Previous: Virtual environments and pip
- Next: pytest.raises and parametrize
- Reference: Get Started in the pytest docs
- Add
"money back"to the billing check intriage.pyand runpytest -qagain. - Run
pytest -vto see every test by name. - Break
triage.pydeliberately, say by returning"Billing"with a capital, and count the failures.
Little by little, you're building something great.