自学考试网站建设与管理,网站需要多大宽带,欧模网室内设计网官网,wordpress多设备网页生成简介
unittest 和 pytest参数化对比#xff1a; pytest与unittest的一个重要区别就是参数化#xff0c;unittest框架使用的第三方库ddt来参数化的
而pytest框架#xff1a;
前置/后置处理函数fixture#xff0c;它有个参数params专门与request结合使用来传递参数#x…简介
unittest 和 pytest参数化对比 pytest与unittest的一个重要区别就是参数化unittest框架使用的第三方库ddt来参数化的
而pytest框架
前置/后置处理函数fixture它有个参数params专门与request结合使用来传递参数也可以用parametrize结合request来传参针对测试方法参数化就直接使用装饰器pytest.mark.parametrize来对测试用例进行传参
参数化目的
参数化就是把测试过程中的数据提取出来通过参数传递不同的数据来驱动用例运行。其实也就是数据驱动的概念当测试用例只有测试数据和期望结果不一样但操作步骤是一样的时可以用参数化提高代码复用性减少代码冗余
参数化实际应用举例
Web UI自动化中的开发场景比如是一个登录框
1、需要测试账号空、密码空、账号密码都为空、账号不存在、密码错误、账号密码正确等情况 2、这些用例的区别就在于输入的测试数据和对应的交互结果 3、所以我们可以只写一条登录测试用例然后把多组测试数据和期望结果参数化节省很多代码量
Pytest参数化
语法
pytest.mark.parametrize(args_name,args_values,indirectFalse, idsNone,scopeNone)
参数列表
args_name参数名称用于参数值传递给函数args_values参数值列表和列表字典元组和字典元组有n个值那么用例执行n次。indirect默认为False,代表传入的是参数。如果设置成True则把传进来的参数当函数执行而不是一个参数。ids自定义测试id字符串列表ids的长度需要与测试数据列表的长度一致标识每一个测试用例自定义测试数据结果的显示为了增加可读性scope如果指定则表示参数的范围。 范围用于按参数实例对测试进行分组。 它还将覆盖任何夹具功能定义的范围允许使用测试上下文或配置设置动态范围。
使用方法
1、单个参数
pytest.mark.parametrize() 装饰器接收两个参数一个参数是以字符串的形式标识用例函数的参数第二个参数以列表或元组的形式传递测试数据
import pytest
#待测试数据
def add(a,b):return ab# 单个参数的情况
pytest.mark.parametrize(a,[1,2,3,4])
def test_add(a): # 作为用例参数接收装饰器传入的数据print( a的值,a)assert add(a,1) a1执行结果
2、多个参数
多个参数pytest.mark.parametrize()第一个参数依然是字符串 对应用例的多个参数用逗号分隔实际是一个解包的过程。
import pytestdef add(a,b):return abpytest.mark.parametrize(a,b,c,[(1,2,3),(4,5,9),(1,2,12)])
def test_add(a,b,c):print(f\n a,b,c的值{a},{b},{c})assert add(a,b)c执行结果
3、整个测试类参数化
测试类的参数化其实际上也是对类中的测试方法进行参数化。 当装饰器 pytest.mark.parametrize 装饰测试类时会将数据集合传递给类的所有测试用例方法
import pytestdata [(1,2,3),(4,5,9)]pytest.mark.parametrize(a,b,c,data)
class TestStudy:def test_parametrize_one(self,a,b,c):print(f\n 测试函数111 测试数据为 {a}-{b})assert ab cdef test_parametrize_two(self, a, b, c):print(\n 测试函数222 测试数据为 {}-{}.format(a,b))assert a b c执行结果
4、多个参数叠加相乘
多个参数组合时使用的是笛卡尔积。 笛卡尔积
一个函数或一个类可以装饰多个 pytest.mark.parametrize这种方式最终生成的用例数是nm比如上面的代码就是参数a的数据有3个参数b的数据有2个所以最终的用例数有326条当参数化装饰器有很多个的时候用例数都等于n * n * n* n *…
# 笛卡尔积组合数据
data_1[1,2,3]
data_2[a,b]pytest.mark.parametrize(a,data_1)
pytest.mark.parametrize(b,data_2)
def test_parametrize_one(a,b):print(f笛卡尔积 测试数据为{a}{b})执行结果 参数化传入字典
# 字典
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(fuser:{dic[user]},pwd:{dic[pwd]})执行结果 参数化标记数据
# 标记参数化
pytest.mark.parametrize(test_input,expected,[(35,8),(24,6),pytest.param(6 * 9,42,markspytest.mark.xfail),pytest.param(6 * 6,42,markspytest.mark.skip)
])
def test_parametrize_mark(test_input,expected):assert eval(test_input) expected执行结果
5、ids 自定义测试id pytest.mark.parametrize() 提供了 ids 参数来自定义显示结果主要是为了更加清晰看到用例的含义 ids的长度需要与测试数据列表的长度一致与fixture的ids参数是一样的可参考fixture的ids。
# 增加可读性
data_1[(1,2,3),(4,5,9)]ids [a:{} b:{} expect:{}.format(a,b,expect) for a,b,expect in data_1]pytest.mark.parametrize(a,b,expect,data_1,idsids)
class TestParametrize(object):def test_parametrize_1(self,a,b,expect):print(f测试函数1测试数据为 {a}--{b})assert a b expectdef test_parametrize_2(self,a,b,expect):print(测试函数2测试数据为 {}--{}.format(a,b))assert a b expect执行结果
request 与parametrize 结合使用给 Fixture传参 fixture自身的params参数可以结合request来传参详见fixture的其他参数介绍章节当然也可以用parametrize来参数化代替params indirectTrue参数目的是把传入的data当做函数去执行而不是参数 如果测试方法写在类中则 pytest.mark.parametrize 的参数名称要与 pytest.fixture 函数名称保持一致
应用场景
为了提高复用性我们在写测试用例的时候会用到不同的fixture比如最常见的登录操作大部分的用- 例的前置条件都是登录假设不同的用例想登录不同的测试账号那么登录fixture就不能把账号写死需要通过传参的方式来完成登录操作
1、单个参数
pytest.fixture()
def test_demo(request):name request.paramyield nameprint(f测试数据是{name})data[ceshi,qianduan]
ids[ftest_name is:{name} for name in data]pytest.mark.parametrize(test_demo,data,idsids,indirectTrue)
def test_name(test_demo):print(f测试用例的数据是{test_demo})执行结果 知识点
添加 indirectTrue 参数是为了把 test_demo 当成一个函数去执行而不是一个参数并且将data当做参数传入函数def test_name(test_demo) 这里的 test_demo 是获取fixture返回的值
2、多个参数
pytest.fixture()
def logins(request):param request.paramyield paramprint(f账号是{param[username]},密码是{param[pwd]})data [{username:张三,pwd:123456},{username:李四,pwd:12345}
]pytest.mark.parametrize(logins,data,indirectTrue)
def test_name_pwd(logins):print(f账号是{logins[username]},密码是{logins[pwd]})执行结果 如果需要传多个参数需要通过字典去传
3、多个fixture(只加一个装饰器)和多个parametrize(叠加装饰器)
# 多个fixture
pytest.fixture()
def login_user(request):user request.paramyield userprint(账号%s % user)pytest.fixture()
def login_pwd(request):pwd request.paramyield pwdprint(密码%s % pwd)data [{username:张三,pwd:123456},{username:李四,pwd:12345}
]pytest.mark.parametrize(login_user,login_pwd,data,indirectTrue)
def test_more_fixture(login_user,login_pwd):print(fixture返回的内容,login_user,login_pwd)执行结果
pytest.fixture(scopefunction)
def login_user(request):user request.paramyield userprint(账号%s % user)pytest.fixture(scopefunction)
def login_pwd(request):pwd request.paramyield pwdprint(密码%s % pwd)name [张三,李四]
pwd [123456,12345]pytest.mark.parametrize(login_user,name,indirectTrue)
pytest.mark.parametrize(login_pwd,pwd,indirectTrue)
def test_more_fixture(login_user,login_pwd):print(fixture返回的内容,login_user,login_pwd)执行结果
[参考文章] 小菠萝测试笔记