Py.test use monkeypatch in custom funcargs

I use py.test and really like the funcarg method to inject objects into test functions. In my testing, I need to work with Mock objects, since I have many external dependencies. I use monkeypatch to replace certain attributes with mock objects.

The problem is that I often get a bunch of tests that will use a specific funcarg and always require the same attributes to be fixed. For now, I am replacing attributes in each test function.

Is there a way to use monkeypatch in my funcarg functions and remove this duplicate code from separate 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]]) 
+4
source share
2 answers

You can use the getfuncargvalue documentation to internally use a function argument from another factory function argument:

 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 
+6
source

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 twofold:

  • We get the monkeypatch plugin using config.pluginmanager .
  • We trick the monkeypatch plugin monkeypatch thinking it was called by the py.test dependency injection code by calling its pytest_funcarg__monkeypatch() funcarg interface with our own request object.
+2
source

All Articles