Assertions & Test Structure
Clear test structure makes failures diagnosable in seconds. pytest's plain assert statements plus the arrange-act-assert pattern are the foundation of readable Python tests.
Search across all documentation pages
Clear test structure makes failures diagnosable in seconds. pytest's plain assert statements plus the arrange-act-assert pattern are the foundation of readable Python tests.
def test_discount_applied():
# Arrange
price = Decimal("100.00")
# Act
result = apply_discount(price, pct=10)
# Assert
assert result == Decimal("90.00")When to reach for this:
from decimal import Decimal
import pytest
from myapp.billing import apply_discount, DiscountError
class TestApplyDiscount:
def test_ten_percent_off(self):
price = Decimal("50.00")
result = apply_discount(price, pct=10)
assert result == Decimal("45.00")
def test_zero_percent_unchanged(self):
price = Decimal("50.00")
assert apply_discount(price, pct=0) == price
def test_invalid_percent_raises(self):
with pytest.raises(DiscountError, match="pct must be 0-100"):
apply_discount(Decimal("10"), pct=-1)What this demonstrates:
pytest.raises for exception testing with message matchtest_* methods)pytest rewrites assert to show values on failure:
assert result == expected
# AssertionError: assert Decimal('45.00') == Decimal('50.00')| Instead of | Use |
|---|---|
assert x == True | assert x |
assert len(items) == 0 | assert not items |
assert type(x) == str | assert isinstance(x, str) |
bare pytest.raises(Error) | pytest.raises(Error, match="...") |
assert x in items, f"{x} not in {items}".pytest.approx(3.14, rel=1e-6).| Alternative | Use When | Don't Use When |
|---|---|---|
| unittest assertions | stdlib-only | You want introspection |
| hypothesis | Property-based checks | Simple input/output |
| snapshot testing | Complex output structures | Pure logic units |
Setup data (arrange), call the code under test (act), verify the result (assert).
Optional. Classes group related tests; functions are fine for simple modules.
with pytest.raises(ValueError): or pytest.raises(ValueError, func, arg).
assert result == pytest.approx(3.14).
Yes. pytest enhances assert failures automatically. No need for self.assertEqual.
5-15 lines ideal. If longer, extract setup into fixtures.
Yes. test_discount_over_100_raises not test_discount_3.
with pytest.warns(DeprecationWarning):.
assert result is None (identity), not == None.
Compare keys individually or use pytest.approx on numeric values.
Stack versions: This page was written for Python 3.14.0, FastAPI 0.115+, Django 5.2, Flask 3.1, Pydantic 2, PyTorch 2.6+, pandas 2.2+, Polars 1.x, ruff 0.9+, and uv 0.6+.
Reviewed by Chris St. John·Last updated Jul 19, 2026