Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can pytest hooks use fixtures?

Tags:

python

pytest

I know fixtures can use other fixtures, but can a hook use a fixture? I searched a lot on net but could not get any help. Can someone please point if I am doing any mistake here?

#conftest.py

@pytest.fixture()
def json_loader(request):   
    """Loads the data from given JSON file"""
    def _loader(filename):
        import json
        with open(filename, 'r') as f:
            data = json.load(f)
        return data
    return _loader



def pytest_runtest_setup(item,json_loader): #hook fails to use json_loader
    data = json_loader("some_file.json") 
    print(data) 
    #do something useful here with data

I get the following error when I run it.

pluggy.manager.PluginValidationError: Plugin 'C:\some_path\conftest.py' for hook 'pytest_runtest_setup' hookimpl definition: pytest_runtest_setup(item, json_loader) Argument(s) {'json_loader'} are declared in the hookimpl but can not be found in the hookspec

Even if I do not pass json_loader as an arg to pytest_runtest_setup(), I get an error saying "Fixture "json_loader" called directly. Fixtures are not meant to be called directly"

like image 585
vasanth kumar c Avatar asked Mar 29 '19 08:03

vasanth kumar c


1 Answers

It seems the only current supported way to dynamically instantiate fixtures is via the request fixture, specifically the getfixturevalue method

This isn't accessible before test time in a pytest hook, but you can accomplish the same by using a fixture yourself

Here's a (contrived) example:

import pytest

@pytest.fixture
def load_data():
    def f(fn):
        # This is a contrived example, in reality you'd load data
        return f'data from {fn}'
    return f


TEST_DATA = None


@pytest.fixture(autouse=True)
def set_global_loaded_test_data(request):
    global TEST_DATA
    data_loader = request.getfixturevalue('load_data')
    orig, TEST_DATA = TEST_DATA, data_loader(f'{request.node.name}.txt')
    yield   
    TEST_DATA = orig


def test_foo():
    assert TEST_DATA == 'data from test_foo.txt'
like image 51
Anthony Sottile Avatar answered Sep 29 '22 21:09

Anthony Sottile