Python 是否可以动态更新参数化夹具';谁是情妇?

Python 是否可以动态更新参数化夹具';谁是情妇?,python,pytest,Python,Pytest,我想对多个fixture值运行同一组测试,但我不想在fixture定义中“硬编码”这些值 我的用例是一个具有多个实现的接口,我希望在每个实现上运行相同的测试 例如,my_code.py 类接口: def方法(): 通过 类IMP1(接口): def方法(): 返回1 类IMP2(接口): def方法(): 返回2 test_interface.py: def测试方法(实例:接口): 断言类型(instance.method())==int test_impl1.py 从我的代码导入Impl1

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

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

例如,my_code.py

类接口:
def方法():
通过
类IMP1(接口):
def方法():
返回1
类IMP2(接口):
def方法():
返回2
test_interface.py:

def测试方法(实例:接口):
断言类型(instance.method())==int
test_impl1.py

从我的代码导入Impl1
@pytest.fixture
def实例():
返回Impl1()
test_impl2.py

从我的代码导入Impl2
@pytest.fixture
def实例():
返回Impl2()
显然,这段代码不起作用(因为找不到fixture“instance”)。我可以在conftest.py中编写类似的内容

@pytest.fixture(参数=[Impl1(),Impl2()])
def实例(请求):
返回请求参数
但是我希望能够运行test_impl1.py来只测试impl1。另外,如果我要编写Impl3,我不想更改conftest.py,我只想添加简单的test\u Impl3.py 如果我的实现完全在另一个包中呢


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

最终解决了这个问题,但不确定这是否是可靠的解决方案。 在
test/common/test\u common.py
中,我放置了我的测试:

def测试方法(实例:接口):
断言类型(instance.method())==int
tests/common/conftest.py
中,我有一些有趣的东西:

THIS_PACKAGE='tests/common/'
def创建实例挂钩(元夹具,名称):
tests_node_id=os.path.join(此_包“{}.py.”格式(名称))
def pytest_运行测试_协议(项目,nextitem):
split=item.nodeid.split(“:”)
文件名,*test_name=split
如果filename==测试item.fixturenames中的节点id和实例:
func\u name=meta\u fixture.\uu name__
meta=tuple(item.session.\u fixturemanager.\u arg2fixturedefs[func\u name])
项目._请求._arg2fixturedefs['instance']=meta
@pytest.hookimpl(hookwrapper=True)
def pytest_collect_文件(路径,父级):
结果=产量
结果=结果。获取结果()
如果parent.parent为无:
result.append(
DoctestModule(os.path.join(parent.fspath,此_包'conftest.py'),parent,
nodeid=os.path.join(此_包“{}_conf.py.”格式(名称)))
append(模块(os.path.join(parent.fspath,THIS_包'test_common.py')、parent、,
nodeid=测试(节点id))
返回pytest\u runtest\u协议、pytest\u collect\u文件
tests/impl1/conftest.py

@pytest.fixture
def impl1_实例():
返回Impl1()
pytest\u runtest\u协议,pytest\u collect\u file=create\u instance\u hook(impl1\u instance,'impl1')
tests/impl2/conftest.py

@pytest.fixture
def impl2_实例():
返回Impl2()
pytest\u runtest\u协议,pytest\u collect\u file=create\u instance\u hook(impl2\u instance,'impl2')
因此,基本上,当收集
tests/implN
测试时,
pytest\u collect\u文件
hook从
tests/common/test\u common.py

然后当它们运行时,
pytest\u runtest\u协议
hook将
implN\u实例
fixture添加为实例fixture。因此,如果我只运行impl1或impl2,则会运行一组测试,如果我只运行pytest测试,则会有两组带有适当夹具的测试

从该
test\u方法
生成一个helper函数,相同但没有test\u2前缀,并创建使用
impl1()
参数调用它的test\u1方法,等等。实际上我有60多个测试。此外,我希望能够将测试添加到test_impl.py,以便自动将这些测试添加到每个实现测试集。您可以使用
pytest\u generate_tests
hook将动态生成的值传递到夹具。这个钩子在测试收集和执行之前被调用。您可以在其中编写一些自定义代码,例如基于命令行args,并构造参数列表以参数化夹具。看一看db fixture在何处用列表参数化。示例中的列表是硬编码的,但您可以加入一些逻辑来动态构建它。谢谢你的帮助