Skip to content

metafunc parametrization with session scope causes multiple fixture teardowns #8102

@bluetech

Description

@bluetech

Originally posted by @Idanjc in #8089

Hi,

I'm not sure if this is something I'm doing wrong, a bug or known behaviour in recent versions of pytest, so trying to post here first.
Apologies in advanced if it's not the right place for it.

When I'm using metafunc.parametrize on session scoped fixtures it causes a teardown after each test function, instead of after the entire session.
This causes a heavy setup I have that should only run once per configuration (could have several configs in a single run) to run after every test function.

It doesn't happen in pytest 5.3.5, but does happen in pytest 5.4+ versions (reproduced on 5.4.3 & 6.1.2).

Reproduction code example:

# conftest.py

def pytest_addoption(parser):
    parser.addoption('--config', action='store', type=str,
                     help='load configuration for tests from some file (yaml/json etc)')

@pytest.fixture(scope='session')
def my_fixture(setup):
    # would yield a specific test object , e.g. db
    yield 'my_fixture'

@pytest.fixture(scope='session')
def setup(config):
    # do some setup to use in tests
    # actually yield an orchestration holding all the needed objects in tests after setup (server, db etc)
    yield 

@pytest.fixture(scope='session', autouse=True)
def config(request):
    conf = request.param
    # build final config
    yield conf

def pytest_generate_tests(metafunc):
    if metafunc.config.getoption('--config'):
        # load configurations from some file
        confs = [{'key1': 'val1'}, {'key2': 'val2'}]
        confs_ids = ['conf1', 'conf2']
        metafunc.parametrize('config', confs, ids=confs_ids, indirect=True)
# test_param.py

def test_foo(my_fixture):
    print('\n test_foo \n')


def test_bar(my_fixture):
    print('\n test_bar \n')

Running with: pytest -s --setup-show --config 'path/to/file'

Output from pytest version 5.3.5:

test_param.py 
SETUP    S config[{'key1': 'val1'}]
SETUP    S setup (fixtures used: config)
SETUP    S my_fixture (fixtures used: setup)
        test_param.py::test_foo[conf1] (fixtures used: config, my_fixture, request, setup)
 test_foo 

.
        test_param.py::test_bar[conf1] (fixtures used: config, my_fixture, request, setup)
 test_bar 

.
TEARDOWN S my_fixture
TEARDOWN S setup
TEARDOWN S config[{'key1': 'val1'}]
SETUP    S config[{'key2': 'val2'}]
SETUP    S setup (fixtures used: config)
SETUP    S my_fixture (fixtures used: setup)
        test_param.py::test_foo[conf2] (fixtures used: config, my_fixture, request, setup)
 test_foo 

.
        test_param.py::test_bar[conf2] (fixtures used: config, my_fixture, request, setup)
 test_bar 

.
TEARDOWN S my_fixture
TEARDOWN S setup
TEARDOWN S config[{'key2': 'val2'}]

Output from pytest versions 5.4.3 & 6.1.2:

test_param.py 
SETUP    S config[{'key1': 'val1'}]
SETUP    S setup (fixtures used: config)
SETUP    S my_fixture (fixtures used: setup)
        test_param.py::test_foo[conf1] (fixtures used: config, my_fixture, request, setup)
 test_foo 

.
TEARDOWN S my_fixture
TEARDOWN S setup
TEARDOWN S config[{'key1': 'val1'}]
SETUP    S config[{'key1': 'val1'}]
SETUP    S setup (fixtures used: config)
SETUP    S my_fixture (fixtures used: setup)
        test_param.py::test_bar[conf1] (fixtures used: config, my_fixture, request, setup)
 test_bar 

.
TEARDOWN S my_fixture
TEARDOWN S setup
TEARDOWN S config[{'key1': 'val1'}]
SETUP    S config[{'key2': 'val2'}]
SETUP    S setup (fixtures used: config)
SETUP    S my_fixture (fixtures used: setup)
        test_param.py::test_foo[conf2] (fixtures used: config, my_fixture, request, setup)
 test_foo 

.
TEARDOWN S my_fixture
TEARDOWN S setup
TEARDOWN S config[{'key2': 'val2'}]
SETUP    S config[{'key2': 'val2'}]
SETUP    S setup (fixtures used: config)
SETUP    S my_fixture (fixtures used: setup)
        test_param.py::test_bar[conf2] (fixtures used: config, my_fixture, request, setup)
 test_bar 

.
TEARDOWN S my_fixture
TEARDOWN S setup
TEARDOWN S config[{'key2': 'val2'}]

Thanks, appreciate the help,
Idanjc

Metadata

Metadata

Assignees

No one assigned

    Labels

    topic: fixturesanything involving fixtures directly or indirectly

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions