当调用pytest中的班级参数化固定装置时,类固定固定装置的意外行为
我在类中有一个带有参数化的间接<代码>类的测试 scoped固定装置。当另一个常规类
范围固定在调用参数化固定装置时,其执行似乎更函数
scop。表示每种测试方法再次调用常规固定装置。在删除参数化的灯具调用时,它将按预期执行一次。
我知道固定的生命周期,如在这里,但是我没有离开班级。我在这里缺少什么?
PYTEST-7.0.1,PYTEST-ASYNCIO-0.17.2
代码:
@pytest_asyncio.fixture(scope='class')
async def some_fixture(request, iteration): # <---- when not using 'iteration', works as expected
print(f'-some_fixture-{request.scope}-start')
yield
print(f'-some_fixture-{request.scope}-end')
@pytest_asyncio.fixture(scope='class')
async def iteration(self, request):
print(f'-iteration-{request.scope}-start')
yield request.param
print(f'-iteration-{request.scope}-end')
@pytest.mark.parametrize('iteration', range(1, ITERATIONS + 1), indirect=True) # <---- tried adding scope='class', no success
@pytest.mark.asyncio
class Something:
async def test_something(self, iteration, some_fixture):
print(test_body)
输出:
test_foo.py::test_something[1] -iteration-class-start
-some_fixture-class-start
-test_body
PASSED
test_foo.py::test_something[2] -some_fixture-class-end # <---- why it end here?
-iteration-class-end
-iteration-class-start
-some_fixture-class-start # <--- called twice
-test_body
PASSED
-some_fixture-class-end
-iteration-class-end
I have a test in a class with parametrized indirect class
scoped fixture. When another regular class
scoped fixture is calling the parametrized fixture, its execution seems to be more function
scoped. Meaning the regular fixture is called again, for every test method. When removing the parametrized fixture call, it is executed once per class as expected.
I am aware of fixture life cycle as explained here, but I am not exiting the class. What I am missing here?
pytest-7.0.1, pytest-asyncio-0.17.2
Code:
@pytest_asyncio.fixture(scope='class')
async def some_fixture(request, iteration): # <---- when not using 'iteration', works as expected
print(f'-some_fixture-{request.scope}-start')
yield
print(f'-some_fixture-{request.scope}-end')
@pytest_asyncio.fixture(scope='class')
async def iteration(self, request):
print(f'-iteration-{request.scope}-start')
yield request.param
print(f'-iteration-{request.scope}-end')
@pytest.mark.parametrize('iteration', range(1, ITERATIONS + 1), indirect=True) # <---- tried adding scope='class', no success
@pytest.mark.asyncio
class Something:
async def test_something(self, iteration, some_fixture):
print(test_body)
Output:
test_foo.py::test_something[1] -iteration-class-start
-some_fixture-class-start
-test_body
PASSED
test_foo.py::test_something[2] -some_fixture-class-end # <---- why it end here?
-iteration-class-end
-iteration-class-start
-some_fixture-class-start # <--- called twice
-test_body
PASSED
-some_fixture-class-end
-iteration-class-end
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
这是参数化灯具的预期行为。可以将固定装置直接进行参数化(通过夹具装饰器中的
params
参数)或通过测试间接参数(如问题所示)。两种情况在语义上都是等效的,意味着将以不同的参数调用固定装置并产生不同的结果。因此,必须分别评估每个参数的固定装置 - 您可以将其视为每个参数而不是单个夹具的单独固定装置。如果固定设备(示例中的
some_fixture
)是从参数化的固定装置“派生”的,则也将被参数化,因为每个参数都会为每个参数计算一个单独的结果,也将是相同的。为了说明这一点,您可以将参数添加到输出中的固定装置中。这是一个稍有变化的示例来证明这一点:我删除了异步部分,因为它与问题无关,因此将参数添加到固定装置输出中,并在类中添加了第二个测试(还对测试名称进行了调整以识别。由pytest)。
输出的是:
请注意,即使多次使用(在两次测试中,在这种情况下两次),每个参数仅适用于每个参数一次。如您所见,它的确表现得像类固定装置,如果具有不同参数的固定装置被视为不同的固定装置(如应该)。
This is the expected behavior for parametrized fixtures. A fixture can be directly parametrized (via the
params
argument in the fixture decorator) or indirectly parametrized by a test (as shown in the question). Both cases are semantically equivalent, and mean that a fixture will be called with different parameters and yield different outcomes. Therefore the fixture has to be evaluated for each parameter separately - you can think of this as a separate fixture for each parameter instead of a single fixture.The same is true if a fixture (as
some_fixture
in your example) is "derived" from a parametrized fixture - it will also be parametrized, as a separate outcome is calculated for each parameter. To illustrate this, you can add the parameter to the fixture in the output. Here is a slightly changed example to demonstrate this:I have removed the async part, as it is not relevant for the question, added the parameter to the fixture output and added a second test in the class (also adapted the test names to be recognized by pytest).
The output for this is:
Note that the fixture is called only once for each parameter, even if it is used multiple times (in this case twice in the 2 tests). As you can see, it indeed behaves like a class fixture, if fixtures with different parameters are seen as different fixtures (as they should).