带参数的pytest夹具

pytest fixture with argument

似乎可以将参数传递给固定装置:

Pass a parameter to a fixture function

然而,在实现这个最小示例时,我收到了一个错误。

import pytest

@pytest.fixture
def my_fixture(v):
    print("fixture in")
    yield v+1
    print("fixture out")

@pytest.mark.parametrize("my_fixture",[1], indirect=True)
def test_myfixture(my_fixture):
    print(my_fixture)

@pytest.fixture def my_fixture(v): E fixture 'v' not found

上面的代码有什么问题吗?

(python 3.8.10, pytest-6.2.5)

没有错。夹具用于固定常量,以便在多个测试中以相同方式重用它们。他们不接受任何争论。顺便说一句,你可以创建一个 pytest.fixture 是一个“常量”函数:

@pytest.fixture
def my_fixture():
    return lambda x: x+1

并避免在夹具中使用 print(至少在最终版本中)。

这个有效:

@pytest.fixture
def my_fixture(request):
    print("fixture in")
    yield request.param+1 # difference here !
    print("fixture out")

@pytest.mark.parametrize("my_fixture",[1], indirect=True)
def test_myfixture(my_fixture):
    print(my_fixture)


简要说明 Vince 的回答:一般来说,fixture 函数的参数被解释为要在定义的 fixture 之前加载的其他 fixture 的名称。这就是您收到错误消息 fixture 'v' not found 的原因:pytest 认为您希望 my_fixture 依赖于另一个名为 v 的不存在的装置。

request 参数是这个一般规则的一个例外。它不涉及另一个固定装置。相反,它指示 pytest 授予夹具访问 request 对象的权限,该对象包含有关当前 运行 测试的信息,例如正在测试哪些参数(通过request.param),测试有哪些标记(通过request.node.get_closest_marker())等

因此,要使用间接参数化,您的灯具需要 (i) 接受 request 参数和 (ii) 使用 request.param 做一些事情。有关详细信息,请参阅文档中的相关页面: