Skip to content

fixture finalizer dependency incorrect when using autouse or getfuncargvalue #1489

Closed
@amosonn

Description

@amosonn

Calling fixture finalizers in the correct order works by dependent fixtures registering their finalizer in their dependency (see python.FixtureDef.execute+10).
However, this only happens for fixtures explicitly requested in args, not for autouse or getfuncargvalue fixtures.
This code:

import pytest

@pytest.fixture(scope="session")
def global_dict():
    return {}

@pytest.fixture(scope="session", autouse=True)
def add_1(global_dict):
    global_dict[1] = "a"
    print("add_1 setup", global_dict)
    yield global_dict
    print("add_1 teardown", global_dict)
    del global_dict[1]

@pytest.fixture(scope="session")
def change_1_to_2(global_dict):
    global_dict[2] = global_dict.pop(1)
    print("change_1_to_2 setup", global_dict)
    yield global_dict
    print("change_1_to_2 teardown", global_dict)
    global_dict[1] = global_dict.pop(2)

def test1(change_1_to_2):
    assert change_1_to_2[2] == "a"

def test2(global_dict):
    assert global_dict[2] == "a"

gives with py.test --capture=no test.py:

============================= test session starts ==============================
platform linux2 -- Python 2.7.11, pytest-2.9.1, py-1.4.31, pluggy-0.3.1
rootdir: /home/amos/git/test_py, inifile: 
collected 2 items 

test.py add_1 setup {1: 'a'}
change_1_to_2 setup {2: 'a'}
..add_1 teardown {2: 'a'}
change_1_to_2 teardown {2: 'a'}
E

==================================== ERRORS ====================================
__________________________ ERROR at teardown of test2 __________________________

global_dict = {1: 'a'}

    @pytest.yield_fixture(scope="session", autouse=True)
    def add_1(global_dict):
        global_dict[1] = "a"
        print "add_1 setup", global_dict
        yield global_dict
        print "add_1 teardown", global_dict
>       del global_dict[1]
E       KeyError: 1

test.py:14: KeyError
====================== 2 passed, 1 error in 0.01 seconds =======================

as does this code:

import pytest

@pytest.fixture(scope="session")
def global_dict():
    return {}

@pytest.yield_fixture(scope="session")
def add_1(global_dict):
    global_dict[1] = "a"
    print "add_1 setup", global_dict
    yield global_dict
    print "add_1 teardown", global_dict
    del global_dict[1]

@pytest.yield_fixture(scope="session")
def change_1_to_2(request):
    add_1 = request.getfuncargvalue("add_1")
    add_1[2] = add_1.pop(1)
    print "change_1_to_2 setup", add_1
    yield add_1
    print "change_1_to_2 teardown", add_1
    add_1[1] = add_1.pop(2)

def test1(change_1_to_2):
    assert change_1_to_2[2] == "a"

def test2(global_dict):
    assert global_dict[2] == "a"

Metadata

Metadata

Assignees

No one assigned

    Labels

    topic: fixturesanything involving fixtures directly or indirectlytype: bugproblem that needs to be addressed

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions