pythonpytestfixtures

Condition in pytest fixture depending on some test-suite results


Imagine the following test-suite:

import pytest


@pytest.fixture(scope="session")
def global_resource():
    yield
    if ...:
        print("output generated by this resource.")


def test_foo():
    assert False


def test_bar(global_resource):
    assert True


def test_baz(global_resource):
    assert True

In my actual setup, global_resource starts a docker container that produces a ton of output. If a test that uses that fixture fails, I want to print that output. If none of the tests that use this fixture fail, I do not want to print it.

In other words:

foo bar baz print?
True True True no
True True False yes
True False True yes
True False False yes
False True True no
False True False yes
False False True yes
False False False yes

Is there something that I can put into the condition after global_resource's yield in order to learn if I want to print or no? I am aware that at this point tests may still fail due to issues in their teardown, that is ok.


Solution

  • global_resource is in session scope, so you will have only the bottom line of the tests in request fixture, something like testsfailed=3, testscollected=6

    You can use pytest_runtest_makereport hook in conftest.py to check every test

    FAILED_GLOBAL_RESOURCE_TEST = False
    
    
    @pytest.fixture(scope='session')
    def global_resource():
        yield
        if FAILED_GLOBAL_RESOURCE_TEST :
            print('output generated by this resource.')
    
    
    @pytest.hookimpl(hookwrapper=True)
    def pytest_runtest_makereport(item, call):
        global FAILED_GLOBAL_RESOURCE_TEST 
        outcome = yield
        result = outcome.get_result()
        if result.failed and result.when == 'call' and 'global_resource' in item.fixturenames:
            FAILED_GLOBAL_RESOURCE_TEST = True
    

    This will print the docker output only once, but if you wanted to print on every test failure you need only minor changes (keep the output from global_resource and use it in pytest_runtest_makereport).