是否可以动态更新参数化夹具的参数?

我想对多个夹具值运行同一组测试,但我不想在夹具定义中“硬编码”这些值。


我的用例是一个具有多个实现的接口,我想在每个实现上运行相同的测试。


例如,my_code.py


class Interface:

   def method():

      pass


class Impl1(Interface):

   def method():

      return 1


class Impl2(Interface):

   def method():

      return 2

test_interface.py:


def test_method(instance: Interface):

    assert type(instance.method()) == int

test_impl1.py


from my_code import Impl1

@pytest.fixture

def instance():

    return Impl1()

test_impl2.py


from my_code import Impl2

@pytest.fixture

def instance():

    return Impl2()

显然这段代码不起作用(因为找不到夹具“实例”)。我可以在 conftest.py 中写这样的东西


@pytest.fixture(params=[Impl1(), Impl2()])

def instance(request):

   return requst.param

但我希望能够运行 test_impl1.py 来仅测试 Impl1。另外,如果我要编写 Impl3,我不想更改 conftest.py,我只想添加简单的 test_impl3.py 如果我的实现完全在其他包中怎么办?


简而言之,我想为固定装置列表中的每个值重用我的测试,但我想在运行时更改此固定装置列表(例如,取决于可用的实现)


慕尼黑8549860
浏览 92回答 1
1回答

心有法竹

终于解决了这个问题,但不确定这是否是可靠的解决方案。test/common/test_common.py我把我的测试:def test_method(instance: Interface):    assert type(instance.method()) == int在tests/common/conftest.py我有有趣的东西:THIS_PACKAGE = 'tests/common/'def create_instance_hooks(meta_fixture, name):    tests_node_id = os.path.join(THIS_PACKAGE, '{}.py'.format(name))    def pytest_runtest_protocol(item, nextitem):        split = item.nodeid.split('::')        filename, *test_name = split        if filename == tests_node_id and 'instance' in item.fixturenames:            func_name = meta_fixture.__name__            meta = tuple(item.session._fixturemanager._arg2fixturedefs[func_name])            item._request._arg2fixturedefs['instance'] = meta    @pytest.hookimpl(hookwrapper=True)    def pytest_collect_file(path, parent):        outcome = yield        result = outcome.get_result()        if parent.parent is None:            result.append(                DoctestModule(os.path.join(parent.fspath, THIS_PACKAGE, 'conftest.py'), parent,                              nodeid=os.path.join(THIS_PACKAGE, '{}_conf.py'.format(name))))            result.append(Module(os.path.join(parent.fspath, THIS_PACKAGE, 'test_common.py'), parent,                                 nodeid=tests_node_id))    return pytest_runtest_protocol, pytest_collect_file在tests/impl1/conftest.py我有@pytest.fixturedef impl1_instance():    return Impl1()pytest_runtest_protocol, pytest_collect_file = create_instance_hooks(impl1_instance, 'impl1')在tests/impl2/conftest.py我有@pytest.fixturedef impl2_instance():    return Impl2()pytest_runtest_protocol, pytest_collect_file = create_instance_hooks(impl2_instance, 'impl2')所以基本上当tests/implN收集测试时,pytest_collect_file钩子添加测试tests/common/test_common.py ,然后当它们运行时,pytest_runtest_protocol钩子添加implN_instance夹具作为实例夹具。因此,如果我只运行 impl1 或 impl2,则运行一组测试,如果我只运行 pytest 测试,则有两组带有适当夹具的测试
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Python