Fixtures and Parametrize: Tests Without Repetition
About 20 minutes
Why this matters
As test files grow, two kinds of repetition appear: the same setup code at the top of every test, and the same test copied with different numbers. pytest has a tool for each: fixtures and parametrize.
The idea
A fixture is a function that prepares something your tests need. A test asks for it by naming it as a parameter, and pytest calls the fixture and passes the result in:
import pytest
@pytest.fixture
def numbers():
return [3, 1, 2]
def test_sorting(numbers):
assert sorted(numbers) == [1, 2, 3]
def test_length(numbers):
assert len(numbers) == 3
Every test gets its own fresh copy, so tests cannot affect each other. Fixtures can also create temporary files, open connections and clean up afterwards (with yield). pytest’s built-in tmp_path and capsys are fixtures.
parametrize runs one test function with many inputs, and reports each as its own test:
@pytest.mark.parametrize("text, expected", [
("a", 1),
("abc", 3),
("", 0),
])
def test_length_of_text(text, expected):
assert len(text) == expected
The first argument names the parameters, the second is a list of value sets. A failure tells you exactly which set failed.
Try it
This lesson uses real pytest features that the in-browser runner does not offer, so it runs on your own computer. Run the example in a file with pytest -v and look at the names in the output.
Your turn
The starter has a working Stack class. Write the tests below it:
- A fixture called
stackthat returns aStackwith1,2and3pushed (in that order). - At least two ordinary tests that use the
stackfixture. - A test decorated with
@pytest.mark.parametrizeand at least three sets of values.
The checker runs your file with pytest and counts the results.
Recap
@pytest.fixtureprepares objects; tests receive them by parameter name.- Each test gets a fresh fixture, so tests stay independent.
@pytest.mark.parametrizeturns one test into many.- Both remove copy-paste from test files.
Common mistakes
- Calling the fixture like a function (
stack()) instead of asking for it as a parameter. - Sharing mutable state between tests through a global variable.
- Parametrize names that do not match the test’s parameter names.