源码分析

class _ParametrizeMarkDecorator(MarkDecorator):
    def __call__(  # type: ignore[override]
            self,
            argnames: Union[str, List[str], Tuple[str, ...]],
            argvalues: Iterable[Union[ParameterSet, Sequence[object], object]],
            *,
            indirect: Union[bool, Sequence[str]] = ...,
            ids: Optional[
                Union[
                    Iterable[Union[None, str, float, int, bool]],
                    Callable[[Any], Optional[object]],
                ]
            ] = ...,
            scope: Optional[_Scope] = ...,
        ) -> MarkDecorator:
            ...

argnames

源码解析:

含义:参数名字

格式:字符串"arg1,arg2,arg3"【需要用逗号分隔】

备注:argnames: Union[str, List[str], Tuple[str, ...]],

示例

@pytest.mark.parametrize(["name", "pwd"], [("yy1", "123"), ("yy2", "123")])  
@pytest.mark.parametrize(("name", "pwd"), [("yy1", "123"), ("yy2", "123")])  
@pytest.mark.parametrize("name,pwd", [("yy1", "123"), ("yy2", "123")])

argvalues

源码解析:

含义:参数值列表

格式:必须是列表,如:[ val1,val2,val3 ]

如果只有一个参数,里面则是值的列表如:@pytest.mark.parametrize("username", ["yy", "yy2", "yy3"])

如果有多个参数例,则需要用元组来存放值,一个元组对应一组参数的值,如:@pytest.mark.parametrize("name,pwd", [("yy1", "123"), ("yy2", "123"), ("yy3", "123")])

备注: argvalues: Iterable[Union[ParameterSet, Sequence[object], object]],

ids

含义:用例的ID

格式:传一个字符串列表

作用:可以标识每一个测试用例,自定义测试数据结果的显示,为了增加可读性

强调:ids的长度需要与测试数据列表的长度一致。多少组数据,就要有多少个id,然后组成一个id的列表

indirect

作用:如果设置成True,则把传进来的参数当函数执行,而不是一个参数

实际场景

讲完源码,对方法有更深入的了解了,我们就讲讲常用的场景

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time    : 2022/1/15 17:02
# @Author  : shisuiyi
# @File    : parm.py
# @Software: win10 Tensorflow1.13.1 python3.9
import pytest

ids = ['case1', 'case2', 'case3']


@pytest.mark.parametrize('a,b,result', [[1, 2, 3], [2, 4, 6], [11, 2, 13]], ids=ids)
class TestParametrize(object):
    def test_add1(self, a, b, result):
        print('测试函数1 '+'{}+{} = {}'.format(a, b, result))
        assert a + b == result

    def test_add2(self, a, b, result):
        print('测试函数2 '+'{}+{} = {}'.format(a, b, result))
        assert a + b == result


if __name__ == '__main__':
    pytest.main('parm.py')

输出:

parm.py::TestParametrize::test_add1[case1] 
parm.py::TestParametrize::test_add1[case2] 
parm.py::TestParametrize::test_add1[case3] 
parm.py::TestParametrize::test_add2[case1] 
parm.py::TestParametrize::test_add2[case2] 
parm.py::TestParametrize::test_add2[case3] 

============================== 6 passed in 0.04s ==============================

Process finished with exit code 0
PASSED                        [ 16%]测试函数1 1+2 = 3
PASSED                        [ 33%]测试函数1 2+4 = 6
PASSED                        [ 50%]测试函数1 11+2 = 13
PASSED                        [ 66%]测试函数2 1+2 = 3
PASSED                        [ 83%]测试函数2 2+4 = 6
PASSED                        [100%]测试函数2 11+2 = 13

重点

当装饰器 @pytest.mark.parametrize 装饰测试类时,会将数据集合传递给类的所有测试用例方法