一、参数化作用
- 实现 数据 和 脚本分离
- 便于 用例重复生成与执行
- 减少 测试方法个数,便于后期维护
二、参数化基本思路
相同步骤不同测试数据对应的测试方法可以合并为一个方法,并通过参数化提供不同的测试数据
-
参数化前
-
参数化后
对比上述两图可知,参数化后代码量明显减少,且便于后期维护,一旦用例更新,只需更新参数列表中数据,无需涉及多个测试方法。
三、参数化实现方式
1、参数化基本使用
通过 @pytest.mark.parametrize() 装饰器进行参数化设置
# 参数化
import pytest
# 计算x的阶乘(为便于演示测试过程,此处专门植入了一些缺陷)
def jiecheng(x):
if(x>=0):
if x==0:
return 0
else:
return x*jiecheng(x-1)
else:
return "error"
# 使用参数化,对阶乘函数进行测试
# tlf-特别注意:测试方法的参数是由参数化装饰器的第一个参数的字段信息传入的,因此要求“一对一”
@pytest.mark.parametrize("x,expected",[[2,2],[5,120],[0,1],[-2,"error"]])
def test_jiecheng(x,expected):
result = jiecheng(x)
assert expected == result
运行效果为:
从测试结果可以看出,被测函数存在多个缺陷
2、为测试用例重命名 及 中文乱码处理方法
运行测试后,测试结果区域显示所有测试用例对应的测试结果,此时,测试用例命名方式为该测试用例所有测试数据连接起来的效果,例如:当测试数据为2、2时,测试用例名称显示为2-2,但可读性不高。因此,建议对测试用例重命名。
通过装饰器的第三个参数 ids=[item1,item2,…] 对测试用例进行重命名。
- 测试代码
# 参数化
import pytest
# 计算x的阶乘(有缺陷,便于演示测试过程)
def jiecheng(x):
if(x>=0):
if x==0:
return 0
else:
return x*jiecheng(x-1)
else:
return "error"
# 使用参数化,对阶乘函数进行测试
# @pytest.mark.parametrize()通过装饰器进行参数化
# 装饰器第一个参数为 测试用例的输入数据和预期结果
# 装饰器第二个参数为 列表形式,其每个元素为 每条测试用例对应的测试数据和预期结果
# 装饰器第三个参数为 ids=[item1,item2,...],其每个元素为 每条测试用例的名称
# 若测试用例名称为中文,需要特殊处理一下
# 处理方式为:在项目目录下新建conftest.py文件,并实现pytest_collection_modifyitems()方法,详见conftest.py文件
@pytest.mark.parametrize("x,expected",[[2,2],[5,120],[0,1],[-2,"error"]],ids=["2的阶乘","3的阶乘","0的阶乘","-2的阶乘"])
def test_jiecheng(x,expected):
result = jiecheng(x)
assert expected == result
- conftest.py文件(用于识别中文,否则中文显示为乱码)
# 创建 conftest.py 文件,将下面的代码添加进去,随后再运行测试脚本即可(就可以识别中文了)
def pytest_collection_modifyitems(items):
# 测试用例收集完成时,将收集到的用例名和用例标识中的中文信息都显示在控制台上
for i in items:
i.name = i.name.encode("utf-8").decode("unicode_escape")
i._nodeid = i.nodeid.encode("utf-8").decode("unicode_escape")
- 运行效果
3、参数笛卡尔积
当测试数据为多个,每个参数有多种取值,且需要测试每个参数的每种取值的组合情况,此时,借助笛卡尔积的形式设置测试数据,更简便。
需求:输入数据为 a、b、c,其中,a 的取值为 1,2,b 的取值为 3,4,c 的取值为5,6,测试时要对a、b、c进行组合测试
# 使用笛卡尔积设置参数时,对于每个参数都要单独进行参数化设置
# 运行测试时,由近及远 进行取值,即先取与测试方法最近的测试数据的取值
@pytest.mark.parametrize("a",[1,2])
@pytest.mark.parametrize("b",[3,4])
@pytest.mark.parametrize("c",[5,6])
def test_dikaerji(a,b,c):
return print(f"a={a},b={b}")
运行效果为: