Recently, we ran into an issue at work where implementing pytest in a project just wasn't working out. After some time of on-and-off troubleshooting, we discovered that it was because this project imports a module from another internal project that relies on cli arguments being present or not present. It does different things depending on the circumstances. Changing this module was impossible. It was already a workaround to ensure compatibility with client products and worked exactly as intended.
So how can we go about testing our code?
Enter some fancy manipulation with Python Fixtures! (After a week or so of troubleshooting other options and
- Python <
3.6.2has some known issues with Typings . I was testing locally on Python
3.6.0for some compatibility testing earlier and this defintely ate up a portion of my time.
- pytest >
5.0.1currently has bugs with how it interacts with VSCode. Since the majority of our developers work on VSCode, its basically meant future versions are currently broken. We'll be updating once a patch comes but pinning pytest for now.
conftest.py fixture which will import the offending module (
BADMODULE ) from our company repo. Then patch the offending method,
argparse.parse in this case, to disallow passing params.
def fixed_function(self): # do good stuff # kwargs.get('args', '') # instead of kwargs.get('args', None) # which defaults to pulling cli args print("Good Stuffs") return ['Good Stuff'] @pytest.fixture(scope="session") def global_fixture(): from BADPROJECT.badModule import BadModule patch.object(BadModule, 'BadFunction') BadModule.BadFunction = fixed_function
Then, a module level fixture in each test that imports
BADMODULE. This module level fixture can't freely pass imported objects into the actual test cases so the compromise between ease of use and clear understanding was to add imported items to
pytest.<> global variables.
@pytest.fixture(scope="module", autouse=True) def ImportModules(): from BADPROJECT.badModule import BadModule pytest.BadModule = BadModule
Now, to use the successfully imported module, just use
pytest.BadModule instead of
BadModule like you normally would.