If you reuse a @pytest.mark.parametrize many times, it might be time to define a parametrized fixture instead.

The trick is to use the params argument to the pytest.fixture decorator and then access it using pytest’s request fixture:

@pytest.fixture(name="number", params=(1, 2))
def _number(request):
    return request.param

Every time a test requires number, it gets called twice, once with 1 and once with 2 passed for number.

So the following test:

def test_parametrized_fixture(number):
    assert number in {1, 2}

Runs twice and passes:

test.py::test_parametrized_fixture[1] PASSED            [ 50%]
test.py::test_parametrized_fixture[2] PASSED            [100%]

You can use such a simple parametrized fixture for more complex fixtures by combining the param value with some kind of factory.


You can also alias the call to parametrize:

numbers = pytest.mark.parametrize("numbers", (1, 2))

@numbers
def test_alias(numbers):
    

But that requires you to apply the aliased decorator to every single test method, adding an extra line each. I also find the naming of parametrization aliases awkward.


The somewhat cumbersomely explicit name="number" and private function name _number are to prevent having the fixture name both in global and function scope with different types.

That can lead to confusing errors when you forget to specify the fixture as a parameter and your test uses the global fixture function of the same name instead. Naming the function differently ensures an idiomatic NameError.