Search code examples
pythonpytestvirtualenvpython-module

Is it possible to use parameterize imports with pytest?


I am using pytest to test a project I am working on. I have a project structure like

|my_project
||__init__.py
||my_code.py
||test.py

and test.py looks like

# contents of test.py
import .my_code

def test_function():
  ...
...

To run the tests, I can just run python -m pytest from this directory. So far so good.

But for the code to run remotely, I have to use Pants to build a virtual environment so that the import statement will actually look like:

import long.path.to.my_project.my_code as my_code

I want to make sure that the code still works in this virtual environment as well, so right now I have a different file called test_venv.py with identical tests, where the only difference is the import.

# contents of test_venv.py
import long.path.to.my_project.my_code as my_code

def test_function():
   ...
...

This does work, but it's very annoying to have two almost identical test files. Is there a way to make the import statement parameterized, so that I can tell pytest where I want to import from when I run the test?


Solution

  • After playing around with @morhc's suggestion to use this, I figured out a way. It involves using parameterized fixtures and importlib. I set up the fixture as follows.

    @pytest.fixture(scope='module', params=['local', 'installed'])
    def my_code_module(request):
        if request.param == 'local':
            return importlib.import_module("my_code")
        if request.param == 'installed':
            return importlib.import_module("long.path.to.my_project.my_code")
    

    Then write the tests to request the fixture as follows.

    def test_code(my_code_module):
        assert my_code_module.whatever() == ...