I use py.test and really like the funcarg approach to inject objects into test functions. In my testing I need to work with Mock objects, as I have a lot external dependencies. I use monkeypatch to replace certain attributes with the mock objects.
The problem I have is, that I will often end up with a bunch of tests that will use a certain funcarg and always require the same attributes patched. So far I replace the attributes in every test function.
Is there a way to use monkeypatch in my funcarg functions, and remove this duplicated code from the individual tests?
import sys
import pytest
from mock import Mock
#----------------------------------------------------------------------
def pytest_funcarg__api(request):
""""""
api = myclass()
#do some initialisation...
return api
#----------------------------------------------------------------------
def test_bla1(monkeypatch, api):
""""""
monkeypatch.setattr(api,"get_external_stuff",Mock())
monkeypatch.setattr(api,"morestuff",Mock())
api.do_something1()
assert not api.a
#----------------------------------------------------------------------
def test_bla2(monkeypatch, api):
""""""
monkeypatch.setattr(api,"get_external_stuff",Mock())
monkeypatch.setattr(api,"morestuff",Mock())
api.do_something2()
assert api.b
if __name__=='__main__':
pytest.main(args=["-v",sys.argv[0]])
You can use the documented getfuncargvalue function to internally use a function argument from another function argument's factory:
def pytest_funcarg__api(request):
api = myclass()
#do some initialisation...
mp = request.getfuncargvalue("monkeypatch")
mp.setattr(api,"get_external_stuff", Mock())
mp.setattr(api,"morestuff", Mock())
return api
This should work:
def pytest_funcarg__api(request):
""""""
api = myclass()
#do some initialisation...
mp_plugin = request.config.pluginmanager.getplugin("monkeypatch")
monkeypatch = mp_plugin.pytest_funcarg__monkeypatch(request)
monkeypatch.setattr(api,"get_external_stuff",Mock())
monkeypatch.setattr(api,"morestuff",Mock())
return api
The trick here is two-fold:
monkeypatch
plugin using config.pluginmanager
.monkeypatch
plugin into thinking its called by py.test's dependency injection code, by calling its pytest_funcarg__monkeypatch()
funcarg-interface with our very own request object.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