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 stack that returns a Stack with 1, 2 and 3 pushed (in that order).
  • At least two ordinary tests that use the stack fixture.
  • A test decorated with @pytest.mark.parametrize and at least three sets of values.

The checker runs your file with pytest and counts the results.

Recap

  • @pytest.fixture prepares objects; tests receive them by parameter name.
  • Each test gets a fresh fixture, so tests stay independent.
  • @pytest.mark.parametrize turns 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.

This lesson needs your own computer. It uses features that browsers cannot provide. Run it from the course files on your own computer and follow the instructions in exercises/10-testing-and-quality/02-fixtures-and-parametrize/LESSON.md.