Pytest系列(9) - 参数化@pytest.mark.parametrize
如果你还想从头学起Pytest,可以看看这个系列的文章哦!
https://www.cnblogs.com/poloyy/category/1690628.html
前言
pytest允许在多个级别启用测试参数化:
- pytest.fixture() 允许fixture有参数化功能(后面讲解)
- @pytest.mark.parametrize 允许在测试函数或类中定义多组参数和fixtures
- pytest_generate_tests 允许定义自定义参数化方案或扩展(拓展)
参数化场景
只有测试数据和期望结果不一样,但操作步骤是一样的测试用例可以用上参数化;
可以看看下面的栗子
未参数化的代码
- def test_1():
- assert 3 + 5 == 9
- def test_2():
- assert 2 + 4 == 6
- def test_3():
- assert 6 * 9 == 42
可以看到,三个用例都是加法然后断言某个值,重复写三个类似的用例有点冗余
利用参数化优化之后的代码
- @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,可以节省很多代码
实际Web UI自动化中的开发场景,比如是一个登录框
- 你肯定需要测试账号空、密码空、账号密码都为空、账号不存在、密码错误、账号密码正确等情况
- 这些用例的区别就在于输入的测试数据和对应的交互结果
- 所以我们可以只写一条登录测试用例,然后把多组测试数据和期望结果参数化,节省很多代码量
源码分析
def parametrize(self,argnames, argvalues, indirect=False, ids=None, scope=None):
argnames
源码解析:a comma-separated string denoting one or more argument names, or a list/tuple of argument strings.
含义:参数名字
格式:字符串"arg1,arg2,arg3"【需要用逗号分隔】
备注:源码中写了可以是参数字符串的list或者tuple,但博主实操过是不行的,不知道是不是写的有问题,大家可以看看评论下
示例
- @pytest.mark.parametrize(["name", "pwd"], [("yy1", ""), ("yy2", "")]) # 错的
- @pytest.mark.parametrize(("name", "pwd"), [("yy1", ""), ("yy2", "")]) # 错的
- @pytest.mark.parametrize("name,pwd", [("yy1", ""), ("yy2", "")])
argvalues
源码解析:
- The list of argvalues determines how often a test is invoked with different argument values.
- If only one argname was specified argvalues is a list of values.【只有一个参数,则是值列表】
- If N argnames were specified, argvalues must be a list of N-tuples, where each tuple-element specifies a value for its respective argname.【如果有多个参数,则用元组来存每一组值】
含义:参数值列表
格式:必须是列表,如:[ val1,val2,val3 ]
如果只有一个参数,里面则是值的列表如:@pytest.mark.parametrize("username", ["yy", "yy2", "yy3"])
如果有多个参数例,则需要用元组来存放值,一个元组对应一组参数的值,如:@pytest.mark.parametrize("name,pwd", [("yy1", "123"), ("yy2", "123"), ("yy3", "123")])
备注:虽然源码说需要list包含tuple,但我试了下,tuple包含list,list包含list也是可以的........
ids
含义:用例的ID
格式:传一个字符串列表
作用:可以标识每一个测试用例,自定义测试数据结果的显示,为了增加可读性
强调:ids的长度需要与测试数据列表的长度一致
indirect
作用:如果设置成True,则把传进来的参数当函数执行,而不是一个参数(下一篇博文即讲解)
讲完源码,对方法有更深入的了解了,我们就讲讲常用的场景
装饰测试类
- @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
执行结果
重点
当装饰器 @pytest.mark.parametrize 装饰测试类时,会将数据集合传递给类的所有测试用例方法
“笛卡尔积”,多个参数化装饰器
- # 笛卡尔积,组合数据
- 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}')
执行结果
重点知识
- 一个函数或一个类可以装饰多个 @pytest.mark.parametrize
- 这种方式,最终生成的用例数是n*m,比如上面的代码就是:参数a的数据有3个,参数b的数据有2个,所以最终的用例数有3*2=6条
- 当参数化装饰器有很多个的时候,用例数都等于n*n*n*n*....
参数化 ,传入字典数据
- # 字典
- 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"]}')
没啥特别的,只是数据类型是常见的dict而已
执行结果
- 09parametrize.py::test_parametrize_1[dic0] PASSED [ 50%]测试数据为
- {'user': 1, 'pwd': 2}
- user:1,pwd2
- 09parametrize.py::test_parametrize_1[dic1] PASSED [100%]测试数据为
- {'user': 3, 'pwd': 4}
- user:3,pwd4
参数化,标记数据
- # 标记参数化
- @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
执行结果
参数化,增加可读性
- # 增加可读性
- 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
执行结果
知识点
多少组数据,就要有多少个id,然后组成一个id的列表
作用:主要是为了更加清晰看到用例的含义
Pytest系列(9) - 参数化@pytest.mark.parametrize的更多相关文章
- Pytest 系列(28)- 参数化 parametrize + @allure.title() 动态生成标题
如果你还想从头学起Pytest,可以看看这个系列的文章哦! https://www.cnblogs.com/poloyy/category/1690628.html 前言 参数化 @pytest.ma ...
- pytest自动化6:pytest.mark.parametrize装饰器--测试用例参数化
前言:pytest.mark.parametrize装饰器可以实现测试用例参数化. parametrizing 1. 下面是一个简单是实例,检查一定的输入和期望输出测试功能的典型例子 2. 标记单 ...
- pytest.mark.parametrize()参数化应用二,读取json文件
class TestEnorll(): def get_data(self): """ 读取json文件 :return: """ data ...
- pytest.mark.parametrize()参数化的应用一
from page.LoginPage import Loginpage import os, sys, pytest base_dir = os.path.dirname(os.path.dirna ...
- pytest系列(二):筛选用例新姿势,mark 一下,你就知道。
pytest系列(一)中给大家介绍了pytest的特性,以及它的编写用例的简单至极. 那么在实际工作当中呢,我们要写的自动化用例会比较多,不会都放在一个py文件里. 如下图所示,我们编写的用例存放在不 ...
- 5.@pytest.mark.parametrize()数据驱动
简介: pytest.mark.parametrize 是 pytest 的内置装饰器,它允许你在 function 或者 class 上定义多组参数和 fixture 来实现数据驱动. @pytes ...
- pytest文档9-参数化parametrize
前言 pytest.mark.parametrize装饰器可以实现测试用例参数化. parametrizing 1.这里是一个实现检查一定的输入和期望输出测试功能的典型例子 # content of ...
- Pytest进阶之参数化
前言 unittest单元测试框架使用DDT进行数据驱动测试,那么身为功能更加强大且更加灵活的Pytest框架怎么可能没有数据驱动的概念呢?其实Pytest是使用@pytest.mark.parame ...
- 11、pytest -- 测试的参数化
目录 1. @pytest.mark.parametrize标记 1.1. empty_parameter_set_mark选项 1.2. 多个标记组合 1.3. 标记测试模块 2. pytest_g ...
随机推荐
- python爬虫的数据库连接问题
1.需要导的包 import pymysql 2.# mysql连接信息(字典形式) db_config ={ 'host': '127.0.0.1',#连接的主机id(107.0.0.1是本机id) ...
- 网络编程---socket模块
内容中代码都是先写 server端, 再写 client端 1 TCP和UDP对比 TCP(Transmission Control Protocol)可靠的.面向连接的协议(eg:打电话).传输效 ...
- JAVAEE学习day02
1.数据类型的转换 1>自动转换(隐式) // 将取值范围小的数据类型自动提升为取值范围大的类型 // 定义byte类型数据 byte b = 10; // 定义short类型数据 short ...
- Scrapy同时启动多个爬虫
1. 在项目文件夹中新建一个commands文件夹 2. 在command的文件夹中新建一个文件 crawlall.py 3.在crawlall.py 中写一个command类,该类继承 scrapy ...
- el-dialog对话弹框中根据后台数据无限制添加el-select标签,并进行展示,搜索,删除
前几天遇到一个题,el-dialog对话弹框中根据后台数据无限制添加el-select标签,并进行展示,搜索,删除,在这上面用到了递归算法,废话不多说,直接上代码 <template> & ...
- C#winform如何主窗口最大化最小化默认大小
this.WindowState = FormWindowState.Minimized; bool b = true; private void button2_Click(object sende ...
- 三万字、91道MySQL面试题。 附PDF
文末领取面试题 高清PDF 数据库基础知识 1. 为什么要使用数据库 数据保存在内存 优点:存取速度快 缺点:数据不能永久保存 数据保存在文件 优点:数据永久保存 缺点:1)速度比内存操作慢,频繁的I ...
- Linux下反弹shell笔记
0x00 NC命令详解 在介绍如何反弹shell之前,先了解相关知识要点. nc全称为netcat,所做的就是在两台电脑之间建立链接,并返回两个数据流 可运行在TCP或者UDP模式,添加参数 —u 则 ...
- Happens-before先行发生原则
简介 从JDK1.5,java使用新的JSR-133内存模型:JSR-133使用happens-before的概念来阐述操作之间的内存可见性:在JMM中,如果一个操作执行的结果需要对另一个操作可见,那 ...
- identityserver4源码解析_3_认证接口
目录 identityserver4源码解析_1_项目结构 identityserver4源码解析_2_元数据接口 identityserver4源码解析_3_认证接口 identityserver4 ...