Pytest: How to parametrize a test with a list that is returned from a fixture?

This seems to be a duplicate of this question.

By design, this is not possible: the concept of "fixtures" is reserved to test execution, while the concept of "parameters" is reserved to test collection. Please see my detailed answer here.


The short answer is that you can't do it the way you want, i.e., through fixtures: https://github.com/pytest-dev/pytest/issues/2155. Basically, the number of things yielded or returned has to be known up front for pytest to properly compute the fixture and test dependency graph.

It appears that the only way is to fix the list elements before passing them to any of pytests's decorators. Here is an example, related to your other question, showing that the problem can not be solved by say a generator:

import pytest

def gen_lines():
    with open('file_that_does_not_exist') as f:
        yield from f

@pytest.fixture(scope='session')
def create_file():
    with open('file_that_does_not_exist', 'w') as f:
        print('ABC', file=f)
        print('DEF', file=f)

@pytest.fixture(params=gen_lines())
def line_fixture(request):
    return request.param

def test_line(line_fixture):
    assert True

This will fail at collection time when pytest turns your generator into a list. Adding a dependency to line_fixture on create_file won't help either for the same reason.

Your only real option at this point is to run create_file at module load time or before.

import pytest

def gen_lines():
    with open('file_that_does_not_exist') as f:
        yield from f

def create_file():
    with open('file_that_does_not_exist', 'w') as f:
        print('ABC', file=f)
        print('DEF', file=f)

create_file()

@pytest.fixture(params=gen_lines())
def line_fixture(request):
    return request.param

def test_line(line_fixture):
    assert True

The list does not have to be static per-se. It just can't be created by a fixture. But don't let that stop you. You can put the code for defining and running create_file into a separate module, and just import it wherever you need it as a utility. That will obscure all the messy details and make your code look about as clean as it would with fixtures.

Tags:

Python

Pytest