10 Common Uses of pytest.mark.parametrize for Efficient Testing
The article presents ten practical examples of using pytest.mark.parametrize in Python, ranging from basic parameter lists and named parameters to nested parameters, type conversion, exception testing, fixture parametrization, large data sets, custom ID generation, and combining marks, illustrating how to write concise and maintainable test code.
pytest.mark.parametrize is a powerful feature that allows running the same test function multiple times with different parameters, helping to write concise and maintainable test code. Below are ten typical usages demonstrating its flexibility and practicality.
1. Basic usage
The simplest form directly passes a list of parameter values.
import pytest
@pytest.mark.parametrize("x, y, expected", [(1, 2, 3), (4, 5, 9)])
def test_add(x, y, expected):
assert x + y == expected2. Using named parameters
Assign names to parameters to improve readability.
@pytest.mark.parametrize("x, y, expected", [
pytest.param(1, 2, 3, id='positive_numbers'),
pytest.param(-1, -1, -2, id='negative_numbers'),
])
def test_add_named(x, y, expected):
assert x + y == expected3. Nested parameters
Supports nested parameter lists for multidimensional testing.
@pytest.mark.parametrize("x", [1, 2])
@pytest.mark.parametrize("y", [3, 4])
def test_multiply(x, y):
assert x * y in [3, 4, 6, 8]4. Parameter combinations
Use pytest.param to explicitly control parameter combinations and identifiers.
@pytest.mark.parametrize("a, b, expected", [
pytest.param(1, 2, 3, id="integers"),
pytest.param(1.5, 2.5, 4.0, id="floats"),
])
def test_add_combinations(a, b, expected):
assert a + b == expected5. Parameter type conversion
Automatically converts parameter types before passing them to the test function.
@pytest.mark.parametrize("x, y", [("1", "2"), ("3", "4")], ids=["str-str", "str-str"])
def test_add_str_converted(x, y):
x = int(x)
y = int(y)
assert x + y in [3, 7]6. Exception testing
Use pytest.raises to check for specific exceptions.
@pytest.mark.parametrize("x, y", [(1, 'a')])
def test_add_exception(x, y):
with pytest.raises(TypeError):
x + y7. Parametrized fixture
Parametrize a fixture so that each call uses a different input.
@pytest.fixture(params=[1, 2])
def number(request):
return request.param
def test_number(number):
assert number in [1, 2]8. Large‑scale data testing
Generate parameters dynamically from external data sources such as files or databases.
import pandas as pd
data = pd.read_csv('data.csv')
@pytest.mark.parametrize("x, y", data.values.tolist())
def test_large_dataset(x, y):
assert some_complex_calculation(x) == y9. Custom ID generation
Define a custom idfn function to generate test IDs.
def idfn(val):
if isinstance(val, tuple):
return f"{val[0]}-{val[1]}"
return str(val)
@pytest.mark.parametrize("x, y", [(1, 2), (3, 4)], ids=idfn)
def test_custom_id(x, y):
assert x + y in [3, 7]10. Combining marks
Add extra marks to specific parameter combinations.
@pytest.mark.parametrize("x, y", [
(1, 2, pytest.mark.smoke),
(3, 4),
], indirect=True)
def test_marks(x, y):
assert x + y in [3, 7]Note that the indirect=True example is simplified for demonstration; in practice, marks are usually attached directly to parameter lists rather than through indirect fixture parametrization.
Test Development Learning Exchange
Test Development Learning Exchange
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.