Clear failure output is what makes a failing test quick to fix, and float comparison is a classic source of flaky tests.
pytest rewrites assert statements in test modules so that a failing assert shows the values involved. assert result == expected on two dicts prints which keys differ; on lists, the first differing index; on long strings, a diff. You get this from a bare assert, so there's no need for special assertion methods.
You can add a message as the second operand, assert x > 0, "balance must be positive", shown alongside the introspection.
Floating point arithmetic is inexact: 0.1 + 0.2 == 0.3 is False. Use pytest.approx:
assert 0.1 + 0.2 == pytest.approx(0.3)uses a relative tolerance of 1e-6 by default.approx(value, rel=1e-3)orabs=0.01sets the tolerance.- It works on lists, tuples, dicts and NumPy arrays:
assert result == approx([0.33, 0.67], abs=0.01).
Some patterns to avoid:
assert (x, "message")with parentheses: that's a non-empty tuple, always true. pytest warns about it.- Very long boolean expressions: split them into several asserts so the failure points at the actual problem.
- Comparing against
Truewith==; justassert is_valid(x).
Assertion rewriting only applies to test modules and conftest files by default; helper modules need registration, as covered in the internals lesson.
Example
# test_stats.py
import pytest
def mean(xs):
return sum(xs) / len(xs)
def test_mean_float():
assert mean([0.1, 0.2]) == pytest.approx(0.15)
def test_split():
assert [x / 3 for x in (1, 2)] == pytest.approx([0.333, 0.667], abs=1e-3)
def test_report():
got = {"n": 3, "mean": 2.0, "max": 4}
assert got == {"n": 3, "mean": 2.0, "max": 5}
# $ pytest -q
# E AssertionError: assert {'n': 3, 'mean': 2.0, 'max': 4} == {'n': 3, 'mean': 2.0, 'max': 5}
# E Omitting 2 identical items, use -vv to show
# E Differing items:
# E {'max': 4} != {'max': 5}
# 1 failed, 2 passedRemember
- Plain assert gives rich failure diffs thanks to assertion rewriting
- Use pytest.approx for floats, with rel= or abs= tolerances
- approx works on sequences and dicts too
- Never wrap assert and its message in parentheses
Watch out for
- Writing assert (a == b, 'msg'), which always passes.