Parametrizing Tests in pytest

Parametrizing in pytest enables you to test a function with multiple sets of input data. This approach reduces code duplication and ensures thorough testing across various scenarios.


Parametrizing Test Functions with @pytest.mark.parametrize

The @pytest.mark.parametrize decorator allows you to run a single test function multiple times with different input values.

Syntax

@pytest.mark.parametrize("parameter_name", [value1, value2, ...])

You can also test with multiple parameters:

@pytest.mark.parametrize("param1, param2", [(value1, value2), (value3, value4)])

Example: Single Parameter

import pytest
 
@pytest.mark.parametrize("number", [1, 2, 3, 4, 5])
def test_is_even(number):
    assert number % 2 == 0, f"{number} is not even"

This test runs five times, once for each number in the list.

Example: Multiple Parameters

@pytest.mark.parametrize("base, exponent, expected", [
    (2, 3, 8),
    (3, 2, 9),
    (5, 0, 1),
    (1, 10, 1),
])
def test_power(base, exponent, expected):
    assert base ** exponent == expected

Here, test_power runs four times, using each tuple of values.


Parametrizing Fixtures for Dynamic Test Scenarios

You can also parametrize fixtures to dynamically provide data to your tests. This is useful for testing with varying setups.

Defining a Parametrized Fixture

Use the params argument in @pytest.fixture to define multiple inputs for a fixture.

Example:

@pytest.fixture(params=["apple", "banana", "cherry"])
def fruit(request):
    return request.param
 
def test_fruit_length(fruit):
    assert len(fruit) > 0
  • The request object provides access to the current parameter value.
  • This test runs three times, once for each fruit.

Combining Fixture Parametrization with @pytest.mark.parametrize

You can use both techniques together for powerful test scenarios.

Example:

@pytest.fixture(params=[2, 3, 5])
def multiplier(request):
    return request.param
 
@pytest.mark.parametrize("number, expected", [(10, 20), (15, 30), (7, 14)])
def test_multiplication(number, expected, multiplier):
    assert number * multiplier == expected * multiplier

This test combines parametrized inputs from the fixture and the decorator.


Benefits of Parametrization

  • Efficiency: Write one test function to cover multiple scenarios.
  • Clarity: Reduce repetitive code and improve readability.
  • Scalability: Test functions adapt easily to changing requirements by modifying input sets.

Summary

  • Use @pytest.mark.parametrize to test functions with multiple input sets.
  • Parametrize fixtures with the params argument for dynamic setups.
  • Combine both methods for complex test cases requiring diverse data inputs.

Parametrization is a cornerstone of robust testing in pytest, ensuring your code handles a wide variety of scenarios without repetitive or redundant test definitions.