Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Change a way fixtures are called in pytest

I am having a fixture in conftest.py

@pytest.fixture(scope="function", autouse=True)
@pytest.mark.usefixtures
def pause_on_assert():
    yield
    if hasattr(sys, 'last_value') and isinstance(sys.last_value, AssertionError):
        tkinter.messagebox.showinfo(sys.last_value)

Similarly there are many other fixures in the conftest.py with scope as session, module

My test cases looks like this

test.py

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

def test_abc():
    assert 1==0

Problem is I want my fixture that is there in conftest.py to run before yield of fixture that is in my testcase

How can i change order in the way fixture are executed

like image 406
Sumit Avatar asked Dec 18 '19 11:12

Sumit


3 Answers

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
like image 74
Jortega Avatar answered Nov 04 '22 10:11

Jortega


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)
like image 32
hoefling Avatar answered Nov 04 '22 11:11

hoefling


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

like image 25
storenth Avatar answered Nov 04 '22 09:11

storenth