Search code examples
pythonpytestfixtures

How to run fixture once for each run of other fixture


Conftest.py

@pytest.fixture(scope="module")
def fixture2(request):
    do something

@pytest.fixture(scope="session", params=[ 1, 2, 3 ])
def fixture1(request):
    do something else

test_file.py

@pytest.mark.usefixtures('fixture2', 'fixture1')
class TestSomething1(object):
    def test_1(self):
        pass

    def test_2(self):
        pass

@pytest.mark.usefixtures('fixture1')
class TestSomething2(object):
    def test_3(self):
        pass

    def test_4(self):
        pass

what happens is I get 3 sets of tests (1 set for each invocation of fixture1), but fixture2 only runs once for all 3 sets of tests (at least thats my understanding). I'm not sure how to make it run once for each run of fixture1 (not once for each test).

What I ended up doing:

@pytest.fixture(scope="module")
def fixture2(request, fixture1):
    do something

@pytest.fixture(scope="session", params=[ 1, 2, 3 ])
def fixture1(request):
    do something else

Solution

  • Change @pytest.fixture(scope="module") to something else like @pytest.fixture(scope="class") or @pytest.fixture(scope="function"). Module scope means its run once per module.

    From the fixture arguments documentation:

    scope – the scope for which this fixture is shared, one of "function" (default), "class", "module", "package" or "session".

    "package" is considered experimental at this time.

    Pytest documentation on scopes

    make fixture1 dependant on fixture2 and use the same scopes if you want one fixture to be called once for each time the other is called.