使用可变导入路径定义装置

问题描述 投票:0回答:1

我正在测试来自不同模块的函数,这些模块使用从

helpers.py
导入的辅助函数。 我在每个模块函数的测试中对此辅助函数进行了猴子修补(请参见下文)。 我想将
setup_do_thing()
mock_do_thing()
放入
conftest.py
文件中以减少重复并删除
general_mocks.py
,但由于
monkeypatch.setattr()
中提供给
test_module_1.py
的导入路径不同,我无法执行此操作和
test_module_2.py

有没有办法将夹具放在一个文件中并提供给多个测试模块?

app/helper.py

def do_thing():
    #do_thing

app/module1.py

from helper import do_thing

def use_do_thing_for_x():
    ...
    do_thing()
    ...

app/module2.py

from helper import do_thing

def use_do_thing_for_y():
    ...
    do_thing
    ...

tests/general_mocks.py

def mock_do_thing():
    #do_other_thing

tests/test_module_1.py

from general_mocks import mock_do_thing

@pytest.fixture
def setup_do_thing(monkeypatch):
    monkey_patch.setattr('app.module1.do_thing', 
                         mock_do_thing)
    
def test_use_do_thing_for_x(setup_do_thing):
    ...

tests/test_module_2.py

from general_mocks import mock_do_thing

@pytest.fixture
def setup_do_thing(monkeypatch):
    monkey_patch.setattr('app.module2.do_thing', 
                         mock_do_thing)
    
def test_use_do_thing_for_y(setup_do_thing):
    ...
python pytest monkeypatching pytest-fixtures
1个回答
0
投票

如果你想这样做,你必须以某种方式参数化你的灯具,因为它无法猜测正确的模块。首先想到的是间接参数化,例如像这样的东西:

conftest.py

@pytest.fixture
def setup_do_thing(monkeypatch, request):
    # error handling omitted
    monkeypatch.setattr(f"app.{request.param}.do_thing",
                        mock_do_thing)

test_module1.py

@pytest.mark.parametrize("setup_do_thing", ["module1"], indirect=True)
def test_use_do_thing_for_x(setup_do_thing):
    use_do_thing_for_x()

如果您不喜欢,因为它有点误用参数化,您可以例如定义自己的标记:

conftest.py

def pytest_configure(config):
    # register your marker
    config.addinivalue_line(
        "markers", "do_thing_module: module where 'do_thing' resides"
    )

@pytest.fixture
def setup_do_thing(monkeypatch, request):
    mark = request.node.get_closest_marker("do_thing_module")
    if mark:
        # use the first marker argument as module name
        # error handling omitted
        monkeypatch.setattr(f"app.{mark.args[0]}.do_thing",
                            mock_do_thing)

test_module1.py

@pytest.mark.do_thing_module("module1")
def test_use_do_thing_for_x(setup_do_thing):
    use_do_thing_for_x()

可能有更多的可能性可以做到这一点,但首先想到的是这些。

© www.soinside.com 2019 - 2024. All rights reserved.