覆盖 pytest 参数化函数的名称

37

我的参数决定了我的参数化pytest的名称。我将为这些测试使用一些随机参数。为了避免我的junit报告名称混乱,我想为每个参数化测试创建一个静态名称。

是否可能?

JUnit似乎有一个参数:更改参数化测试的名称

class TestMe:
    @pytest.mark.parametrize(
        ("testname", "op", "value"),
        [
            ("testA", "plus", "3"),
            ("testB", "minus", "1"),
        ]
    )
    def test_ops(self, testname, op, value):

我尝试覆盖request.node.name,但我只能在测试执行期间重命名它。

我几乎可以确定我需要编写一个插件或一个fixture。你认为最好的方法是什么?

3个回答

66
你正在寻找 pytest.mark.parametrizeids 参数:

字符串 ID 列表或可调用对象。如果是字符串,每个字符串对应于 argvalues 的一部分,以便它们成为测试 ID 的一部分。如果是可调用对象,则它应该接受一个参数(单个 argvalue),并返回一个字符串或返回 None

你的代码应该像这样:

@pytest.mark.parametrize(
    ("testname", "op", "value"),
    [
        ("testA", "plus", "3"),
        ("testB", "minus", "1"),
    ],
    ids=['testA id', 'testB id']
)
def test_industry(self, testname, op, value):

我该如何解决单独测试用例的问题,pytest -k test_industry[testA id] 无法正常工作... - orange
1
请使用lambda函数生成一些ID: ids=lambda t: str(t).lstrip()[0:8], - Jos Verlinde
1
文档示例使用 ids (pytest.mark.parametrize) 和 id (pytest.param) 参数 -- https://docs.pytest.org/en/latest/example/parametrize.html#different-options-for-test-ids - Ian Thompson

10

您还可以使用来自https://github.com/singular-labs/parametrization或pypi的pytest parametrize包装器。

pip install pytest-parametrization

你的代码应该长这样:
from parametrization import Parametrization

class TestMe:
    @Parametrization.autodetect_parameters()
    @Parametrization.case(name="testA", op='plus', value=3)
    @Parametrization.case(name="testB", op='minus', value=1)
    def test_ops(self, op, value):
        ...

这相当于:

class TestMe:
    @pytest.mark.parametrize(
        ("op", "value"),
        [
            ("plus", "3"),
            ("minus", "1"),
        ],
        ids=['testA', 'testB']
    )
    def test_ops(self, op, value):
        ...

0
如果您使用自己的自定义类进行参数化,我发现继承“str”类非常有用。这样,您可以在类中控制“ID”,而无需每次都重复“ids=str”。
class TestMode(str):
    __test__ = False
    def __new__(cls, name: str, op: str, value: int):
        obj = super().__new__(cls, name)
        obj.name = name
        obj.op = op
        obj.value = value
        ...
        return obj
M1 = TestMode("M1", "plus", 3)
M2 = TestMode("M1", "minus", 1)

@pytest.mark.parametrize("mode", (M1, M2))
def test_good_exbytes_fail_over(mode: TestMode):
    pass

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