【问题标题】:Python Pytest unpack fixturePython Pytest 解压夹具
【发布时间】:2018-05-08 10:39:50
【问题描述】:

我有一个在测试期间创建项目列表的夹具。我想要另一个用第一个生成的值参数化的夹具。

示例代码

import random
import pytest

@pytest.fixture
def values():
    return [random.randint(0, 100) for _ in range(10)]


@pytest.fixture
def value(request):
    return request.param


@pytest.mark.parametrize("value", params=values):
def test_function(value):
    assert value > 0

上面代码的问题是values 是一个函数而不是一个列表。我做了很多挖掘工作,但没有找到任何方法来解压夹具以使用它来参数化另一个夹具。

我知道我可以通过 values 夹具并在测试中对其进行迭代,但这不是一个好的解决方案,因为我想查看哪些值导致测试失败。

我也对替代解决方案持开放态度,例如是否可以从已启动的测试中运行子测试。

【问题讨论】:

  • 不幸的是,不能使用夹具作为参数化源,请参阅this issue。有一个实现此功能的插件:pytest-lazy-fixture,如果您愿意,可以尝试一下。但是,在您的特定示例中,values 夹具没有参数,可以轻松用作普通函数,因此您只需使用 @pytest.mark.parametrize('value', values()) 标记测试。
  • 您能将values 定义为模块级变量吗?它真的需要固定吗?
  • 感谢您的建议。不幸的是,我把例子过于简单化了。在我的情况下,values 夹具使用了上面定义的一些其他夹具。为了使其成为模块级变量,我必须将它所依赖的所有固定装置也制作成变量。至于pytest-lazy-fixture,它允许使用固定装置作为参数,但不能作为参数的来源——你不能这样做parametrize("x", params=lazy_fixture(values))

标签: python testing pytest


【解决方案1】:

这似乎是对夹具概念及其与参数概念的区别的误解。

Pytest 有两个主要阶段:

  • 收集阶段,目标是创建要运行的测试“节点”列表。一个测试“节点”对应一个测试id,每个参数对应一个值。在这个阶段,不执行夹具,只读取装饰器标记(包含参数)。因此,只有在装饰器中声明的参数才能影响这个阶段。

  • 运行每个测试节点的执行阶段。在运行之前,所有尚未设置的所需灯具都已设置好。因此,夹具功能在此阶段执行,并且仅在此阶段执行。 他们的结果不能修改上一阶段已经完成的测试列表。(也就是说,不能通过fixtures动态添加新的测试节点)。

在您的示例中,您希望夹具设置(阶段 B)的结果更改要创建的测试列表(阶段 A):这在设计上是不可能的。您必须在其他地方创建此列表,例如在 conftest.py 中的 pytest init hook 或简单地作为任何测试模块中的共享变量,并在测试或夹具的参数中引用它。

另请参阅这个非常相似的问题:Parametrizing tests depending of also parametrized values in pytest

请注意,作为对hoefling's comment to your question 的补充,您现在可以在参数列表中使用参数化夹具:我已在我的pytest-cases 插件中添加了此功能,用于评估,以便我们最终建议将其合并到 pytest 中(请参阅this discussion,所以请毫不犹豫地提供反馈!)。但不幸的是,由于上述根本原因,这并不能解决您在本文中描述的确切问题。

【讨论】:

  • 为什么你的插件还没有在 pytest 中?这似乎很重要。
  • 感谢@MadPhysicist :) 这些功能需要大量重要的内部引擎更改,因此这需要在 pytest 中进行重大重构。据我了解,pytest 核心团队已经在其他主题(包括清理和错误修复)上花费了大量开发时间,因此现在似乎还不是适合他们的时间。希望很快!
  • 我也希望如此。当我得知测试用例是预先计算的而不是被视为正确的图表时,我有点失望。
  • 你是对的,pytest 中唯一存在的图是夹具的图(虽然已经相当复杂,因为多范围机制)。它们将参数作为预先计算的东西来处理。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-11
  • 1970-01-01
  • 1970-01-01
  • 2019-07-13
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多