如何向 pytest fixture 传递参数?

5
我希望能够向pytest fixture传递参数,这样当fixture的90%相同时,就不需要创建10个不同的fixture了。
我想要实现的最简单的例子:
@pytest.mark.parametrize('foo', [a=1])
def test_args(tmp_path, foo):
    assert foo == 3

@pytest.fixture
def foo(tmp_path, a, b=2):
    return a + b

有没有一种方法可以将a和b标记为参数而不是其他fixture? 或者也许最好的方法是通过定义函数而不是fixture来做到这一点?
我加入了tmp_path fixture,以确保参数化是显式的,并允许使用多个fixture。
值得指出的是:
@pytest.fixture
def foo(request):
    return request.param[0] + request.param[1]


@pytest.mark.parametrize('foo', [(1, 2)], indirect=True)
def test_args(tmp_path, foo):
    assert foo == 3

这种方法(在文档中有定义)是可行的,但不符合我的需求。我想知道是否有更类似于我提供的代码的解决方案。我想通过参数名称传递参数、指定参数的默认值等。

我看到了这个类似的stackoverflow问题,似乎表明pytest支持这个特性(?),但它的答案似乎只会让人更加困惑,并且它们都不适用于我提出的情况。


我认为你在示例中展示的间接参数化是 pytest 目前最接近这种情况的方法 - 虽然我很希望我是错的。 - MrBean Bremen
[a=1] 应该是什么意思?这不是有效的 Python 语法。_有没有一种方法可以将 a 和 b 标记为参数而不是其他固定装置?_实际上没有,因为 fixture args 受到特殊处理。pytest 将所有位置参数、未被 functools.partial 绑定或被 unittest.mock 替换的参数视为其他 fixture 的占位符。在您的示例中,a 应该是一个 fixture,否则 pytest 将失败。 - hoefling
@hoefling那个代码例子本来就不应该工作。我只是想通过这个例子来表达我的问题,即我想按名称指定参数。 - Jacob Pavlock
1个回答

9

通过使用fixture工厂,我成功实现了所需功能。

@pytest.fixture
def foo(tmp_path):
    def _foo(a: int, b: int = 2):
        return a + b

    return _foo

def test_args(tmp_path, foo):
    bar = foo(a=1)
    assert bar == 3

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接