Pytest系列-数据驱动@pytest.mark.parametrize(7)

简介

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,indirect=False, ids=None,scope=None)

参数列表

  • args_name:参数名称,用于参数值传递给函数
  • args_values:参数值:(列表和列表字典,元组和字典元组),有n个值那么用例执行n次。
  • indirect:默认为False,代表传入的是参数。如果设置成True,则把传进来的参数当函数执行,而不是一个参数。
  • ids:自定义测试id,字符串列表,ids的长度需要与测试数据列表的长度一致,标识每一个测试用例,自定义测试数据结果的显示,为了增加可读性
  • scope:如果指定,则表示参数的范围。
    范围用于按参数实例对测试进行分组。
    它还将覆盖任何夹具功能定义的范围,允许使用测试上下文或配置设置动态范围。

使用方法

1、单个参数

​​@pytest.mark.parametrize()​​ 装饰器接收两个参数,一个参数是以字符串的形式标识用例函数的参数,第二个参数以列表或元组的形式传递测试数据

import pytest
#待测试数据
def add(a,b):return a+b# 单个参数的情况
@pytest.mark.parametrize("a",[1,2,3,4])
def test_add(a):  # 作为用例参数,接收装饰器传入的数据print(" a的值:",a)assert add(a,1) == a+1

执行结果
在这里插入图片描述

2、多个参数

多个参数,​​@pytest.mark.parametrize()​​第一个参数依然是字符串, 对应用例的多个参数,用逗号分隔,实际是一个解包的过程。

import pytestdef add(a,b):return a+b@pytest.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 a+b ==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个,所以最终的用例数有32=6条
  • 当参数化装饰器有很多个的时候,用例数都等于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(f"user:{dic['user']},pwd:{dic['pwd']}")

执行结果
在这里插入图片描述
参数化,标记数据

# 标记参数化
@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_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,ids=ids)
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

  • indirect=True参数,目的是把传入的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=[f"test_name is:{name}" for name in data]@pytest.mark.parametrize("test_demo",data,ids=ids,indirect=True)
def test_name(test_demo):print(f"测试用例的数据是:{test_demo}")

执行结果
在这里插入图片描述
知识点:

  • 添加 indirect=True 参数是为了把 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,indirect=True)
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,indirect=True)
def test_more_fixture(login_user,login_pwd):print("fixture返回的内容:",login_user,login_pwd)

执行结果
在这里插入图片描述

@pytest.fixture(scope="function")
def login_user(request):user = request.paramyield userprint("账号:%s" % user)@pytest.fixture(scope="function")
def login_pwd(request):pwd = request.paramyield pwdprint("密码:%s" % pwd)name= ["张三","李四"]
pwd = ["123456","12345"]@pytest.mark.parametrize("login_user",name,indirect=True)
@pytest.mark.parametrize("login_pwd",pwd,indirect=True)
def test_more_fixture(login_user,login_pwd):print("fixture返回的内容:",login_user,login_pwd)

执行结果
在这里插入图片描述

[参考文章] 小菠萝测试笔记

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/80682.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

CLIP 基础模型:从自然语言监督中学习可转移的视觉模型

一、说明 在本文中,我们将介绍CLIP背后的论文(Contrastive Language-I mage Pre-Training)。我们将提取关键概念并分解它们以使其易于理解。此外,还对图像和数据图表进行了注释以澄清疑问。 图片来源: 论文&#xff1a…

Layui + Flask | 实现注册、登录功能(案例篇)(08)

此案例内容比较多,建议滑到最后点击阅读原文,阅读体验更佳。后续也会录制案例视频,将在本周内上传到同名的 b 站账号。 已经看了 layui 表单相关的知识,接下来就可以实现注册功能,功能逻辑如下: 项目创建 新建 flask 项目下载 layui 文件,解压之后复制到指定文件编写前…

前缀和实例4(和可被k整除的子数组)

题目: 给定一个整数数组 nums 和一个整数 k ,返回其中元素之和可被 k 整除的(连续、非空) 子数组 的数目。 子数组 是数组的 连续 部分。 示例 1: 输入:nums [4,5,0,-2,-3,1], k 5 输出:7 …

系统性能调优:提升服务器响应速度

🌷🍁 博主猫头虎(🐅🐾)带您 Go to New World✨🍁 🦄 博客首页——🐅🐾猫头虎的博客🎐 🐳 《面试题大全专栏》 🦕 文章图文…

95.qt qml-诺谦通用可扩展多功能QML界面

支持如下所示: 1.可扩展多功能交互,用户可以根据自己喜欢使用常用功能,针对多功能项目非常有用!2.登录用户信息显示,历史消息显示,皮肤黑白风格切换 如下图所示: 自带一个功能界面,可以通过功能界面添加不…

第十三章总结

一.泛型 1.定义泛型类 泛型机制语法&#xff1a; 类名<T> 其中&#xff0c;T是泛型的名称&#xff0c;代表某一种类型。 【例13.6】创建带泛型的图书类 代码&#xff1a; 结果&#xff1a; 2.泛型的常规用法 (1)定义泛型类时声明多个变量 class MyCla…

算法通过村第八关-树(深度优先)青铜笔记|经典算法题目

文章目录 前言1. 二叉树里面的双指针1.1 判断两棵树是否相同1.2 对称二叉树1.3 合并二叉树 2. 路径专题2.1 二叉树的所有路径2.2 路径总和 3. 翻转的妙用总结 前言 提示&#xff1a;人类的底里是悲伤&#xff0c;我们都在用厚重的颜料&#xff0c;覆盖那些粗糙的线稿。--张皓宸…

ros2学习笔记:shell环境变量脚本setup.bash[-z][-n][-f]参数作用

-n作用 [ -n 字符串 ] or [ 字符串 ] 字符串的长度为非零&#xff08;有内容&#xff09;则为真。加-n与不加-n结果相同。 -z作用 [ -z 字符串 ] 字符串的长度为零则为真。 字符串为空即NULL时为真&#xff0c;与上面的-n相反。 -f作用 [ -f FILE ] 如果 FILE 存在且是一…

【C语言】指针和数组笔试题解析(2)

【C语言】指针和数组笔试题解析&#xff08;1&#xff09;&#xff0c; 这是第一篇关于sizeof与strlen在指针中的应用&#xff0c;而这一篇主要讲解在各种情形下的灵活运用&#xff0c;也是大厂中经典的面试题 第一题&#xff1a; int main() {int a[5] { 1, 2, 3, 4, 5 };in…

uniapp 触底加载

方式一 onReachBottomDistance 缺点&#xff1a;需要整个页面滑动&#xff0c;局部滑动触发不了 { // pages.json // 路由下增加 onReachBottomDistance "path": "detailed/detailed","style": {"navigationBarTitleText": "收…

【无公网IP内网穿透】Windows搭建Web站点

什么是cpolar&#xff1f; cpolar是一个非常强大的内网穿透工具&#xff0c;开发调试的必备利器。 它可以将本地内网服务器的HTTP、HTTPS、TCP协议端口映射为公网地址端口&#xff0c;使得公网用户可以轻松访问您的内网服务器&#xff0c;无需部署至公网服务器。支持永久免费使…

idea 无法识别vue3语法

问题描述&#xff1a; 整合了vue3.js插件能够识别到vue标准语法和html语法第三方库的语法不支持 原因 因为没配置项目根路径&#xff0c;导致无法识别配置文件 而配置文件是识别第三方库语法所必须的。 我用vite操作的&#xff0c;需要这么几个包&#xff1a; 当识别到这…

22.(地图工具篇)geoserver点服务图层SLD样式效果1

地图之家总目录(订阅之前必须详细了解该博客) 效果如下: SLD样式 <?xml version="1.0" encoding="GBK"?> <StyledLayerDescriptor version="1.0.0" xsi:schemaLocation

【Linux网络编程】Socket-UDP实例

这份代码利用下面所有知识编写了一个简易聊天室&#xff08;基于Linux操作系统&#xff09;。虽然字数挺多其实并不复杂&#xff0c;这里如果能够看完或许会对你的知识进行一下串联&#xff0c;这篇文章比较杂并且网络编程这块知识需要用到系统编程的知识&#xff0c;希望能帮助…

Spring Boot集成EasyExcel实现数据导出

在本文中&#xff0c;我们将探讨如何使用Spring Boot集成EasyExcel库来实现数据导出功能。我们将学习如何通过EasyExcel库生成Excel文件&#xff0c;并实现一些高级功能&#xff0c;如支持列下拉和自定义单元格样式&#xff0c;自适应列宽、行高&#xff0c;动态表头 &#xff…

Open3D 点云配准——可视化匹配点对之间的连线

点云配准 一、算法原理1、概述2、主要函数二、代码实现三、结果展示四、测试数据本文由CSDN点云侠原创,原文链接。如果你不是在点云侠的博客中看到该文章,那么此处便是不要脸的爬虫。 一、算法原理 1、概述 可视化源点云和目标点云中匹配点对之间的连线,这对于点云配准,尤…

【AI语言大模型】星火使用介绍

一、前言 现在AI语言大模型是百花齐放,挺好!有竞争,有发展,才能推出更好的产品。现在,科大讯飞就推出了大语言模型——星火!能够学习和理解人类的语言,进行多轮对话,回答问题,高效便捷地帮助人们获取信息、知识和灵感。星火在对话栏设置了三个插件:文档回答、PPT生成…

unity 使用声网(Agora)实现语音通话

第一步、先申请一个声网账号 [Agora官网链接]&#xff08;https://console.shengwang.cn/&#xff09; 第二步在官网创建项目 &#xff0c;选择无证书模式&#xff0c;证书模式需要tokenh和Appld才能通话 第三步 官网下载SDK 然后导入到unity&#xff0c;也可以直接在unity商店…

Linux界的老古董

Slackware 是由 Patrick Volkerding 制作的 Linux 发行版&#xff0c;从 1993 年发布至今也一直在 Patrick 带领下进行维护。7 月 17 日&#xff0c;Slackware 才刚刚过完它 24 岁的生日&#xff0c;看似年纪轻轻的它&#xff0c;已然是 Linux 最古老的发行版。 Slackware 的发…

第 363 场 LeetCode 周赛题解

A 计算 K 置位下标对应元素的和 模拟 class Solution { public:int pop_cnt(int x) {//求x的二进制表示中的1的位数int res 0;for (; x; x >> 1)if (x & 1)res;return res;}int sumIndicesWithKSetBits(vector<int> &nums, int k) {int res 0;for (int i…