自定义pytest参数化测试名称

问题描述 投票:0回答:3

我进行了以下测试:

@pytest.mark.parametrize(
    "nums",
    [[3, 1, 5, 4, 2], [2, 6, 4, 3, 1, 5], [1, 5, 6, 4, 3, 2]]
)
def test_cyclic_sort(nums):
    pass


@pytest.mark.parametrize(
    "nums, missing",
    [([4, 0, 3, 1], 2)]
)
def test_find_missing_number(nums, missing):
    pass

我想自定义测试名称以包含输入数组。我已经阅读了pytest文档这个问题这个问题,但没有人回答以下问题:

  1. 传递给 id 函数的是什么?在我上面的代码中,第一个测试采用一个参数,第二个测试采用两个参数。
  2. pytest 文档使用 id 的顶级函数,而我想将我的测试放在一个类中并使用
    @staticmethod
    。尝试从
    TestClass.static_method
    内部使用
    TestClass
    引用静态方法会在 PyCharm 中出现错误;执行此操作的正确语法是什么?

编辑: 创建https://github.com/pytest-dev/pytest/issues/8448

python python-3.x pytest parameterized-unit-test
3个回答
4
投票

当对

ids
关键字使用可调用函数时,它将使用单个参数进行调用:被参数化的测试参数的值。可调用的
ids
返回一个字符串,该字符串将在方括号中用作测试名称后缀。

如果测试对多个值进行参数化,则仍将使用单个参数调用该函数,但每个测试将多次调用该函数。生成的名称将用破折号连接,类似于

"-".join([idfunc(val) for val in parameters])

例如:

test_something[val1-val2-val3]

这是pytest源码中的连接

要使用静态方法,此语法有效:

class TestExample:

    @staticmethod
    def idfunc(val):
        return f"foo{val}"

    @pytest.mark.parametrize(
        "x, y",
        [
            [1, 2],
            ["a", "b"],
        ],
        ids=idfunc.__func__,
    )
    def test_vals(self, x, y):
        assert x
        assert y

这将生成两个测试,如上所述调用

idfunc
四次。

TestExample::test_vals[foo1-foo2]
TestExample::test_vals[fooa-foob]

2
投票

我喜欢wims的回答,这是对他的回答的评论(我没有时间发表评论)。这对我来说似乎更Pythonic。它还有助于避免使用静态方法。

class TestExample:
    @pytest.mark.parametrize(
        "x, y",
        [
            [1, 2],
            ["a", "b"],
        ],
        ids= lamba val : f"foo{val}"
    )
    def test_vals(self, x, y):
        assert x
        assert y

这将具有相同的输出:

TestExample::test_vals[foo1-foo2]
TestExample::test_vals[fooa-foob]

0
投票

我一直在这里结束,所以为了后代,我想注意你也可以使用

pytest.param
对象(https://docs.pytest.org/en/7.1.x/reference/reference.html#pytest- param)直接将 id 与测试用例关联起来。

例如

cases = [
    pytest.param(1, 1, id="first"),
    pytest.param(2, 4, id="second"),
    pytest.param(3, 9, id="third"),
]

@pytest.mark.parametrize("x, expected", cases)
def test_mytest(x, expected):
    assert x**2 == expected

输出:

test_mytest[first] PASSED           [ 33%]
test_mytest[second] PASSED          [ 66%]
test_mytest[third] PASSED           [100%]

您还可以通过这种方式向测试用例添加标记,例如,如果某些用例“慢”,您可以将

marks=slow
添加到那些
params
对象中。

© www.soinside.com 2019 - 2024. All rights reserved.