我正在测试来自不同模块的函数,这些模块使用从
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):
...
如果你想这样做,你必须以某种方式参数化你的灯具,因为它无法猜测正确的模块。首先想到的是间接参数化,例如像这样的东西:
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()
可能有更多的可能性可以做到这一点,但首先想到的是这些。