On this page
The core idea
pytest discovers functions whose names start with test_ and reports each one that fails, along with the assertion that failed and the values involved. When tests are named after behaviour, such as test_expired_coupon_is_rejected, the failure report reads like a broken requirement. When they are named test_1 or test_coupon, someone has to read the code to understand what went wrong. Small tests that each check one behaviour, with clear arrange, act and assert sections, make a suite easy to maintain and trust.
A practical approach
Step 1
Name each test after the behaviour and condition it checks, in plain language.
Step 2
Structure the body in three parts: set up the inputs, perform one action and assert the expected outcome.
Step 3
Use plain assert statements; pytest shows the compared values when they differ.
Step 4
Use pytest.mark.parametrize for the same behaviour across several inputs, and give cases readable ids.
Step 5
Use fixtures for shared setup, but keep the important values visible in the test so readers do not have to hunt for them.
Worked example
A pricing module has one test named test_prices that checks twelve scenarios in a loop. When it fails, the report says only that one of the assertions was false. Splitting it into parametrised tests with ids such as 'student-discount', 'expired-coupon' and 'zero-price-course' makes the failure report state exactly which rule broke, and a new team member can read the tests as a list of pricing rules.
A mistake to avoid
Do not test private implementation details, such as the exact internal helper calls, when you can test observable behaviour. Implementation-focused tests break whenever code is refactored, even when behaviour is unchanged.
Try it yourself
Open one test file and rename each test so its name states a behaviour and condition. Split any test that checks more than one behaviour, and convert a loop of cases into parametrize with ids.
Your implementation checklist
- Test names describe behaviour and condition
- Each test checks one behaviour
- Arrange, act and assert are easy to see
- Repeated cases use parametrize with readable ids
- Tests target observable behaviour, not internals
Share or cite this guide
Innovate with Ajay Editorial (2026-10-07). Write pytest Tests That Explain the Behaviour They Protect. https://innovatewithajay.com/blogs/write-pytest-tests-that-explain-behaviour
