Change a way fixtures are called in pytest

Here is an example of running my conftest.py function that prints "A" before my test function that prints "B".

cd to the parent directory, for this example it is py_tests and run.

pytest -s -v

The output is:

A
setting up
B
PASSED

With directory structure:

py_tests
 -conftest.py
 -tests
  --tests.py

Files:

conftest.py

import pytest

@pytest.fixture(scope="function")
def print_one():
    print("\n")
    print("A")

test.py

import pytest

class Testonething:

    @pytest.fixture(scope="function", autouse=True)
    def setup(self, print_one):
        print("setting up")

    def test_one_thing(self):
        print("B")
        assert True

Since your _wrapper is a function-scoped autouse fixture: it will be instantiated before other fixtures within the same scope. So, hot fix is to define _wrapper without autouse=True and try to call that decorator implicitly like:

def test_abc(_wrapper):
    assert 1==0

Autouse source

[Update] If you don't have an ability to change your test suites, I suggest you just wipe all local specific _wrapper and refactor your conftest-specified fixture to call _wrapper, because fixture functions can use other fixtures themselves. Your conftest.py will be look like this:

# conftest.py
@pytest.fixture(scope="function", autouse=True)
def _wrapper(pause_on_assert):
    print("pre condition")
    yield
    print("post condition")

@pytest.fixture()
def pause_on_assert():
    yield
    if hasattr(sys, 'last_value') and isinstance(sys.last_value, AssertionError):
        tkinter.messagebox.showinfo(sys.last_value)

Modularity source


If you want to ensure a piece of code runs after the test function, but before all fixtures teardown, I'd advise to use the pytest_runtest_teardown hook instead. Replace the pause_on_assert fixture in your conftest.py with:

def pytest_runtest_teardown(item, nextitem):
    if hasattr(sys, 'last_value') and isinstance(sys.last_value, AssertionError):
        tkinter.messagebox.showinfo(sys.last_value)