如何在py.test中将几个参数化的灯具连接到一个新的灯具中? [英] How to concatenate several parametrized fixtures into a new fixture in py.test?
问题描述
如果我有两个参数化的灯具,我该如何创建一个测试函数,该函数首先在一个灯具的实例中调用,然后在另一个灯具的实例中调用?
If I have two parametrized fixtures, how can I create a single test function that is called first with the instances of one fixture and then with the instances of the other fixture?
我想创建一个新的灯具以某种方式将两个现有灯具连接起来是有意义的.这对于普通"灯具效果很好,但是我似乎无法使其与参数化灯具一起使用.
I guess it would make sense to create a new fixture that somehow concatenates the two existing fixtures. This works well for "normal" fixtures, but I don't seem to get it to work with parametrized fixtures.
这是我尝试过的简化示例:
Here is a simplified example of what I tried:
import pytest
@pytest.fixture(params=[1, 2, 3])
def lower(request):
return "i" * request.param
@pytest.fixture(params=[1, 2])
def upper(request):
return "I" * request.param
@pytest.fixture(params=['lower', 'upper'])
def all(request):
return request.getfuncargvalue(request.param)
def test_all(all):
assert 0, all
运行此命令时出现此错误:
When I run this I get this error:
request = <SubRequest 'lower' for <Function 'test_all[lower]'>>
@pytest.fixture(params=[1, 2, 3])
def lower(request):
> return "i" * request.param
E AttributeError: 'SubRequest' object has no attribute 'param'
...和upper()
相同的错误.
... and the same error for upper()
.
我做错了什么?
我该如何解决?
更新:
有一个可以用来解决此问题的PyTest插件: https://github. com/TvoroG/pytest-lazy-fixture .
There is a PyTest plugin that can be used to solve this problem: https://github.com/TvoroG/pytest-lazy-fixture.
pip
-安装此插件后,对上面代码的唯一必要更改如下:
After pip
-installing this plugin, the only necessary change to the above code is the following:
@pytest.fixture(params=[pytest.lazy_fixture('lower'),
pytest.lazy_fixture('upper')])
def all(request):
return request.param
但是请注意,在某些复杂的情况下它将无法工作:
Note, however, that there are some complex cases in which it will not work:
https://github.com/pytest-dev/pytest/issues/3244#issuecomment-369836702
相关的PyTest问题:
Related PyTest issues:
- https://github.com/pytest-dev/pytest/issues/349
- https://github.com/pytest-dev/pytest/issues/460
- https://github.com/pytest-dev/pytest/issues/3244
- https://github.com/pytest-dev/pytest/issues/349
- https://github.com/pytest-dev/pytest/issues/460
- https://github.com/pytest-dev/pytest/issues/3244
推荐答案
pytest-cases
中现在有一个名为fixture_union
的解决方案.这是创建示例中要求的夹具联合的方法:
There is now a solution available in pytest-cases
, named fixture_union
. Here is how you create the fixture union that you requested in your example:
from pytest_cases import fixture_union, pytest_fixture_plus
@pytest_fixture_plus(params=[1, 2, 3])
def lower(request):
return "i" * request.param
@pytest_fixture_plus(params=[1, 2])
def upper(request):
return "I" * request.param
fixture_union('all', ['lower', 'upper'])
def test_all(all):
print(all)
它按预期工作:
<...>::test_all[lower-1]
<...>::test_all[lower-2]
<...>::test_all[lower-3]
<...>::test_all[upper-1]
<...>::test_all[upper-2]
请注意,在上面的示例中,我使用了pytest_fixture_plus
,因为如果使用pytest.fixture
,则必须自己处理未实际使用灯具的情况.例如,对于upper
固定装置,该操作如下:
Note that I used pytest_fixture_plus
in the above example because if you use pytest.fixture
you will have to handle yourself the cases where a fixture is not actually used. This is done as follows, for example for the upper
fixture:
import pytest
from pytest_cases import NOT_USED
@pytest.fixture(params=[1, 2])
def upper(request):
# this fixture does not use pytest_fixture_plus
# so we have to explicitly discard the 'NOT_USED' cases
if request.param is not NOT_USED:
return "I" * request.param
有关详细信息,请参见文档. (顺便说一下,我是作者;))
See documentation for details. (I'm the author by the way ;) )
这篇关于如何在py.test中将几个参数化的灯具连接到一个新的灯具中?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!