I am monkey patching a database connection class as a fixture. What I want to accomplish is to have some parameters passed to my monkey patched fixture since different tests will all require the same monkeypatch but with different return values.
@pytest.fixture
def data():
    now = datetime.datetime.now()
    data = Data(now)
    return data
@pytest.fixture
def patch_db(monkeypatch):
    class FakeDbConnection:
        def __init__(*args, **kwargs):
            pass
        def fetchall(self):
            return [1,2,3]
    monkeypatch.setattr(DbConnection, 'execute', FakeDbConnection)
def test_get_somevalue(patch_db, data):
    userids = data.get_userids()
    assert userids == [1,2,3]
def test_get_something_else(patch_db, data):
    userids = data.get_userids()
    assert userids == [6,7,8]
The problem I am having is that since my fetchall function only returns [1,2,3]. I tried to have patch_db fixture take params:
@pytest.fixture(scope='module', params=[[1, 2, 3], [4, 5, 6]])
def patch_db(monkeypatch, test_values):
    class FakeDbConnection:
        def __init__(*args, **kwargs):
            pass
        def fetchall(self):
            return test_values.param
    monkeypatch.setattr(DbConnection, 'execute', FakeDbConnection)
but I get the following errors:
ScopeMismatch: You tried to access the 'function' scoped fixture 'monkeypatch' with a 'module' scoped request object, involved factories
monkeypatch can be used to patch functions dependent on the user to always return a specific value. In this example, monkeypatch. setattr is used to patch Path. home so that the known testing path Path("/abc") is always used when the test is run. This removes any dependency on the running user for testing purposes.
conftest.py is where you setup test configurations and store the testcases that are used by test functions. The configurations and the testcases are called fixture in pytest.
pytest allows you to create custom plugins for this sort of functionality. But it also allows you to register those same plugin hooks in your conftest.py files. The above code in your tests/conftest.py file will do the trick. pytest_configure() registers a new marker ( focus ).
pytest. fixture decorator makes it possible to inject the return value in the test functions whose have in their signature the decorated function name. Easy, isn't it? You can potentially generate and create everything you need in these fixture-functions and then use it in all the tests you need.
You can't use a function fixture from a module fixture, as the the message says. 
If you change patch_db's scope to function it will run, but this approach won't work as you expect, because test_get_somevalue would receive two patch_db fixtures, one patched with [1, 2, 3] and the other with [4, 5, 6].
I suggest that you add a function to FakeDbConnection that lets tests set what they want fetchall to return instead. Here's the full example:
@pytest.fixture
def data():
    now = datetime.datetime.now()
    data = Data(now)
    return data
@pytest.fixture
def patch_db(monkeypatch):
    class FakeDbConnection:
        def __init__(*args, **kwargs):
            pass
        def fetchall(self):
            return fetch_result.values
    monkeypatch.setattr(DbConnection, 'execute', FakeDbConnection)
    class FetchResult:
        pass
    fetch_result = FetchResult()
    fetch_result.values = None
    return fetch_result
def test_get_somevalue(patch_db, data):
    patch_db.values = [1,2,3]
    userids = data.get_userids()
    assert userids == [1,2,3]
def test_get_something_else(patch_db, data):
    patch_db.values = [6,7,8]
    userids = data.get_userids()
    assert userids == [6,7,8]
                        If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With