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