是否可以在 pytest 中使用参数化导入?

Is it possible to use parameterize imports with pytest?

我正在使用 pytest 来测试我正在处理的项目。我有一个像

这样的项目结构
|my_project
||__init__.py
||my_code.py
||test.py

test.py看起来像

# contents of test.py
import .my_code

def test_function():
  ...
...

要运行 测试,我可以从这个目录运行 python -m pytest。到目前为止一切顺利。

但是对于远程 运行 的代码,我必须使用 Pants 构建一个虚拟环境,这样导入语句实际上看起来像:

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

我想确保代码在这个虚拟环境中仍然有效,所以现在我有一个名为 test_venv.py 的不同文件,具有相同的测试,唯一的区别是导入。

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

def test_function():
   ...
...

这确实有效,但是有两个几乎相同的测试文件很烦人。有没有办法使导入语句参数化,这样我就可以告诉 pytest 我想在 运行 测试时从哪里导入?

您可以合并导入。做一种方式,捕获异常,做另一种方式。

try:
    import .my_code
except ImportError:
    import long.path.to.my_project.my_code as my_code

def test_function():
   ...
...

我不确定,也许应该是

try:
    import long.path.to.my_project.my_code as my_code
except ImportError:
    import .my_code

在尝试了@morhc 的使用 this 的建议后,我想出了一个办法。它涉及使用参数化装置和 importlib。我按如下方式设置夹具。

@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")

然后编写测试以请求 fixture,如下所示。

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