0
0
PytestHow-ToBeginner ยท 4 min read

How to Use Indirect Parametrize in pytest for Flexible Testing

In pytest, use @pytest.mark.parametrize with the indirect=True option to pass parameters to fixtures instead of directly to test functions. This lets fixtures receive and process parameters before the test runs, enabling more flexible setup and reuse.
๐Ÿ“

Syntax

The @pytest.mark.parametrize decorator is used with the indirect=True argument to tell pytest to send the parameter values to the fixture instead of the test function directly.

Syntax parts explained:

  • argnames: The name(s) of the parameter(s) as string(s).
  • argvalues: A list of values to pass.
  • indirect=True: Tells pytest to treat the parameters as inputs to fixtures.
python
@pytest.mark.parametrize('param', [value1, value2], indirect=True)
def test_example(param):
    # test code using fixture 'param'
    pass
๐Ÿ’ป

Example

This example shows how to use indirect parametrize to pass different strings to a fixture that processes them before the test runs.

python
import pytest

@pytest.fixture
def data(request):
    # Fixture receives parameter via request.param
    return request.param.upper()

@pytest.mark.parametrize('data', ['hello', 'world'], indirect=True)
def test_uppercase(data):
    assert data.isupper()
    assert isinstance(data, str)
Output
============================= test session starts ============================== collected 2 items test_example.py .. [100%] ============================== 2 passed in 0.03s ===============================
โš ๏ธ

Common Pitfalls

Common mistakes when using indirect parametrize include:

  • Not setting indirect=True, so parameters go directly to the test, causing errors if the test expects a fixture.
  • Using indirect=True without a matching fixture name, leading to pytest errors.
  • Trying to indirect parametrize multiple arguments without specifying which ones are indirect.

Correct usage requires matching the parameter name to a fixture and setting indirect=True properly.

python
import pytest

@pytest.fixture
def number(request):
    return request.param * 2

# Wrong: missing indirect=True
@pytest.mark.parametrize('number', [1, 2])
def test_wrong(number):
    # This will fail because 'number' is not processed by fixture
    assert number % 2 == 0

# Right: with indirect=True
@pytest.mark.parametrize('number', [1, 2], indirect=True)
def test_right(number):
    assert number % 2 == 0
Output
============================= test session starts ============================== collected 2 items test_example.py F. [100%] =================================== FAILURES =================================== ______________________________ test_wrong[1] ________________________________ number = 1 def test_wrong(number): > assert number % 2 == 0 E assert 1 % 2 == 0 E + where 1 = number test_example.py:11: AssertionError ============================== 1 failed, 1 passed in 0.04s ======================
๐Ÿ“Š

Quick Reference

Summary tips for using indirect parametrize in pytest:

  • Use indirect=True to pass parameters to fixtures.
  • Parameter names must match fixture names.
  • You can indirect parametrize multiple fixtures by passing a list to indirect.
  • Fixtures receive parameters via request.param.
FeatureDescription
@pytest.mark.parametrizeDecorator to define test parameters
indirect=TrueSend parameters to fixtures instead of test function
request.paramAccess parameter inside fixture
Matching namesParameter name must match fixture name
Multiple indirectUse indirect=["arg1", "arg2"] for multiple fixtures
โœ…

Key Takeaways

Use @pytest.mark.parametrize with indirect=True to pass parameters to fixtures.
Fixture names must match the parameter names for indirect parametrization to work.
Access the parameter inside the fixture with request.param.
Without indirect=True, parameters go directly to the test function, causing errors if a fixture is expected.
You can indirect parametrize multiple fixtures by passing a list to the indirect argument.