How to Use pytest.mark.parametrize in Python

This article provides a comprehensive overview of test parametrization using @pytest.mark.parametrize in Python test suites. You will learn what test parametrization is, how the decorator works, its core syntax, how to handle multiple parameters, and the primary benefits of using this approach to streamline your testing workflow.

What is Test Parametrization?

Test parametrization is a technique where a single test function is executed multiple times with different sets of input data and expected results. Instead of writing separate functions for every edge case or input combination, you define the test logic once and feed it a collection of arguments.

In Python, the pytest framework implements this feature primarily through the @pytest.mark.parametrize decorator.

Basic Syntax and Implementation

The @pytest.mark.parametrize decorator takes two primary arguments: a comma-separated string of parameter names matching the test function's arguments, and an iterable (usually a list of tuples) containing the corresponding data sets.

import pytest

def is_even(number):
    return number % 2 == 0

@pytest.mark.parametrize("number, expected", [
    (2, True),
    (3, False),
    (0, True),
    (-1, False),
])
def test_is_even(number, expected):
    assert is_even(number) == expected

During execution, pytest unpacks each tuple and injects the values into test_is_even(number, expected). It runs the test four separate times, treating each iteration as an independent test case.

Execution and Reporting

A key advantage of @pytest.mark.parametrize is how it handles test isolation and reporting:

Customizing Test IDs

By default, pytest generates identifiers based on the input values. When dealing with complex objects or edge cases, you can provide custom labels using the ids parameter:

@pytest.mark.parametrize(
    "value, expected",
    [(10, True), (-5, False)],
    ids=["positive_number", "negative_number"]
)
def test_positive(value, expected):
    assert (value > 0) == expected

This improves readability in test logs, especially during continuous integration (CI) builds.

Advanced Usage: Stacking Parametrizations

You can apply multiple @pytest.mark.parametrize decorators to a single test function. When stacked, pytest computes the Cartesian product of all combinations:

@pytest.mark.parametrize("x", [1, 2])
@pytest.mark.parametrize("y", [10, 20])
def test_multiply(x, y):
    assert (x * y) > 0

This configuration executes four distinct tests: (x=1, y=10), (x=2, y=10), (x=1, y=20), and (x=2, y=20).

Benefits of Using @pytest.mark.parametrize