一前言

1.Pytest允许在多个级别启用测试参数化
 1.1.pytest.fixture()允许fixture有参数化功能(后面讲解)
 
 1.2.@pytest.mark.parametrize允许在"测试函数或类"中定义多组参数和fixtures
 
 1.3.pytest_generate_tests允许定义"自定义参数化"方案或扩展(拓展)

二.@pytest.mark.parametrize参数化场景

1.只有"测试数据和期望结果"不一样,但操作步骤是一样的"测试用例可以用上参数化"
2."未参数化"实例
2.1.test_009.py
def test_1():
    assert 3 + 5 == 9

def test_2():
    assert 2 + 4 == 6

def test_3():
    assert 6 * 9 == 42
2.2.可以看到,三个用例都是加法然后断言某个值,重复写三个类似的用例有点冗余
3."利用参数化"实例
3.1.test_009.py
import pytest

@pytest.mark.parametrize("test_input,expected", [("3+5", 8), ("2+4", 6), ("6*9", 42)])
def test_eval(test_input, expected):
    print(f"测试数据{test_input},期望结果{expected}")
    assert eval(test_input) == expected
3.2.可以看到,只有一条用例,但是利用"参数化输入三组不同的测试数据和期望结果",最终执行的测试用例数=3,可以节省很多代码

在这里插入图片描述

三.实际Web UI自动化中的开发场(比如:一个登录框)

1."登录"需要测试账号空、密码空、账号密码都为空、账号不存在、密码错误、账号密码正确等情况

2.这些用例的"区别"就在于"输入的测试数据和对应的交互结果"不同

3.所以可以只写一条登录测试用例,然后把"多组测试数据和期望结果参数化",节省很多代码量

四.@pytest.mark.parametrize源码分析

def parametrize(self,argnames, argvalues, indirect=False, ids=None, scope=None): 
1.argnames"参数名字"
1.1.argnames含义:"参数"名字

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

1.4.备注:源码中写了可以是参数字符串的list或者tuple,但实操过是不行的,不知道是不是写的有问题
@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")])
2.argvalues"参数值列表"
2.1.argvalues含义:"参数值列表"

2.3.argvalues格式:"必须是列表",如:[ val1,val2,val3 ]
2.3.1.如果"只有一个参数,里面则是值的列表"
如:@pytest.mark.parametrize("username", ["yy", "yy2", "yy3"])

2.3.2.如果"有多个参数例,则需要用元组来存放值,一个元组对应一组参数的值"
如:@pytest.mark.parametrize("name,pwd", [("yy1", "123"), ("yy2", "123"), ("yy3", "123")])
2.4.备注:虽然源码说需要list包含tuple,但试了下tuple包含list,list包含list也是可以的
3.ids"用例的ID"
3.1.ids含义:"用例的ID"

3.2.ids格式:传一个"字符串列表"

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

3.4."强调":ids的长度需要与测试数据列表的长度一致
4.indirect
4.1.indirect作用:"如果设置成True,则把传进来的参数当函数执行,而不是一个参数"(下一篇博文即讲解)

五.@pytest.mark.parametrize装饰测试类

1.test_010.py
import pytest


# 参数化数据:(a, b, expect)
data_1 = [
    (1, 2, 3),
    (4, 5, 9),
]


@pytest.mark.parametrize('a, b, expect', data_1)
class TestParametrize:

    def test_parametrize_1(self, a, b, expect):
        print('\n测试函数11111 测试数据为\n{}-{}'.format(a, b))
        assert a + b == expect

    def test_parametrize_2(self, a, b, expect):
        print('\n测试函数22222 测试数据为\n{}-{}'.format(a, b))
        assert a + b == expect
2.重点:当装饰器"@pytest.mark.parametrize装饰测试类"时,会将"数据集合传递给类的所有测试用例方法"

在这里插入图片描述

六.“笛卡尔积”,多个参数化装饰器@pytest.mark.parametrize

1.test_011.py
import pytest

# 笛卡尔积,组合数据
data_1 = [1, 2, 3]
data_2 = ['a', 'b']

@pytest.mark.parametrize('a', data_1)
@pytest.mark.parametrize('b', data_2)
def test_parametrize_1(a, b):
    print(f'笛卡尔积 测试数据为 : {a},{b}')

在这里插入图片描述

2.【重点知识】
2.1."一个函数或一个类可以装饰多个@pytest.mark.parametrize"

2.2.这种方式,最终生成的用例数是n*m
比如:上面参数a的数据有3个,参数b的数据有2个,所以最终的用例数有3*2=6条

2.3.当参数化装饰器有很多个的时候,用例数都等于n*n*n*n*....

七.@pytest.mark.parametrize参数化 ,传入字典数据

1.test_012.py
import pytest

# 字典
data_1 = (
    {
        'user': 1,
        'pwd': 2
    },
    {
        'user': 3,
        'pwd': 4
    }
)

@pytest.mark.parametrize('dic', data_1)
def test_parametrize_1(dic):
    print(f'测试数据为\n{dic}')
    print(f'user:{dic["user"]},pwd:{dic["pwd"]}')
1.1.数据类型是常见的dict而已(字典)

在这里插入图片描述

八.@pytest.mark.parametrize参数化,标记(标签)数据

1.test_013.py
import pytest


# 标记参数化
@pytest.mark.parametrize("test_input,expected", [
    ("3+5", 8),
    ("2+4", 6),
    pytest.param("6 * 9", 42, marks=pytest.mark.xfail),
    pytest.param("6*6", 42, marks=pytest.mark.skip)
])
def test_mark(test_input, expected):
    assert eval(test_input) == expected

在这里插入图片描述

九.@pytest.mark.parametrize参数化,增加可读性

1.test_014.py
import pytest


# 增加可读性
data_1 = [
    (1, 2, 3),
    (4, 5, 9)
]

# ids
ids = ["a:{} + b:{} = expect:{}".format(a, b, expect) for a, b, expect in data_1]

@pytest.mark.parametrize('a, b, expect', data_1, ids=ids)
class TestParametrize(object):

    def test_parametrize_1(self, a, b, expect):
        print('测试函数1测试数据为{}-{}'.format(a, b))
        assert a + b == expect

    def test_parametrize_2(self, a, b, expect):
        print('测试函数2数据为{}-{}'.format(a, b))
        assert a + b == expect

在这里插入图片描述

2.说明
2.1.多少组数据,就要有多少个id,然后组成一个id的列表

2.2.作用:主要是为了更加清晰看到用例的含义

更多推荐