Skip to content

Class scoped fixture is called multiple times with mutable values and parameterisation #7175

Description

@JSchulte01
  • [ x] a detailed description of the bug or suggestion
  • [ x] output of pip list from the virtual environment you are using
  • [ x] pytest and operating system versions
  • [ x] minimal example if possible

When setting up test parameterisation using a combination of pytest_generate_test hooks and fixture decorators, along with pytest.mark.parameterize decorators I'm seeing inconsistent behaviour with the fixtures which have scope='class'. In the application context these fixtures load large tables of data which takes quite a long time.

When an immutable object is passed as the fixture parameter - the fixtures behave as expected, however when mutable object, like a list is passed, the class fixture gets called repeatedly. The workaround identified in #896 did not seem to make a difference so I have opened a new issue.

If this is expected behaviour or a known bug I would like to add a warning to the docs to make this clear.

Possibly Related

#3678, #896

LSB Release

Distributor ID:	Ubuntu
Description:	Ubuntu 16.04.6 LTS
Release:	16.04
Codename:	xenial

PIP Freeze >>

attrs==19.3.0
importlib-metadata==1.6.0
more-itertools==8.2.0
packaging==20.3
pluggy==0.13.1
py==1.8.1
pyparsing==2.4.7
pytest==5.4.1
six==1.14.0
wcwidth==0.1.9
zipp==3.1.0

Minimum Reproducible Example

import pytest

def pytest_generate_tests(metafunc):

    if 'fixture_a' in metafunc.fixturenames:
        metafunc.parametrize(
            'fixture_a',
            [1, ('a',), ['b']],
            scope='class',
            indirect=True,
        )


@pytest.fixture(scope='session')
def fixture_a(request):
    print('fixture_a CALLED')
    return request.param


class TestExp:

    @pytest.fixture(scope='class')
    def fixture_d(self, fixture_a):
        print('fixture_d CALLED')
        return fixture_a

    def test_func_one(self, fixture_d):
        print(fixture_d)

    @pytest.mark.parametrize(
        'param_a',
        ['*', '+']
    )
    def test_func_two(self, fixture_d, param_a):
        print(fixture_d, ' -> ', param_a)

Output of Test

platform linux -- Python 3.6.8, pytest-5.4.1, py-1.8.1, pluggy-0.13.1 -- ...
cachedir: .pytest_cache
rootdir: ...
collected 9 items                                                                                                                                                                                          

test_mre.py::TestExp::test_func_one[1] 
fixture_a CALLED
fixture_d CALLED
1
PASSED
test_mre.py::TestExp::test_func_two[1-*] 1  ->  *
PASSED
test_mre.py::TestExp::test_func_two[1-+] 1  ->  +
PASSED

test_mre.py::TestExp::test_func_one[fixture_a1] 
fixture_a CALLED
fixture_d CALLED
('a',)
PASSED
test_mre.py::TestExp::test_func_two[fixture_a1-*] ('a',)  ->  *
PASSED
test_mre.py::TestExp::test_func_two[fixture_a1-+] ('a',)  ->  +
PASSED

test_mre.py::TestExp::test_func_one[fixture_a2] 
fixture_a CALLED
fixture_d CALLED
['b']
PASSED
test_mre.py::TestExp::test_func_two[fixture_a2-*]               <<< ---- Class scoped fixture called twice
fixture_a CALLED
fixture_d CALLED
['b']  ->  *
PASSED
test_mre.py::TestExp::test_func_two[fixture_a2-+] ['b']  ->  +
PASSED

Activity

  1. added
    status: help wanteddevelopers would like help from experts on this topic
    topic: fixturesanything involving fixtures directly or indirectly
    on May 10, 2020
  2. symonk commented on May 23, 2020

    @symonk
    Member

    smells like fixture caching / is vs == checks at a glance - will investigate

  3. Zac-HD commented on Jul 22, 2026

    @Zac-HD
    Member

    Closing as resolved: the fixture reordering/caching rework in #11231, part of the pytest 8.0 fixture-scoping overhaul alongside #11220/#10771, keys fixture reuse on a hashable param index instead of the raw parametrize value, so mutable/unhashable values no longer cause duplicate setup.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    status: help wanteddevelopers would like help from experts on this topictopic: fixturesanything involving fixtures directly or indirectlytopic: parametrizerelated to @pytest.mark.parametrize

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions