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)
执行结果

[参考文章] 小菠萝测试笔记
相关文章:
Pytest系列-数据驱动@pytest.mark.parametrize(7)
简介 unittest 和 pytest参数化对比: pytest与unittest的一个重要区别就是参数化,unittest框架使用的第三方库ddt来参数化的 而pytest框架: 前置/后置处理函数fixture,它有个参数params专门与request结合使用来传递参数&#x…...
【Qt】QGroundControl入门2:下载、编译、错误处理、运行
1、源码下载 git clone https://github.com/mavlink/qgroundcontrol.git 2、下载依赖库 2.1 查看依赖库的github路径 cat .gitmodules[submodule "src/GPS/Drivers"]path = src/GPS/Driversurl = https://github.com/PX4/GpsDrivers.git [submodule "libs/m…...
【深度学习】Pytorch 系列教程(十):PyTorch数据结构:2、张量操作(Tensor Operations):(4)索引和切片详解
目录 一、前言 二、实验环境 三、PyTorch数据结构 0、分类 1、张量(Tensor) 2、张量操作(Tensor Operations) 1. 数学运算 2. 统计计算 3. 张量变形 4. 索引和切片 使用索引访问单个元素 使用切片访问子集 使用索引和…...
2024字节跳动校招面试真题汇总及其解答(三)
6.jwt与cookie区别 JWT 和 Cookie 都是用于在客户端和服务器之间传输信息的常用方法。但是,它们之间存在一些关键差异。 JWT 是 JSON Web Token 的缩写,它是一种基于 JSON 的加密令牌。JWT 由三部分组成:Header、Payload 和 Signature。Header 包含令牌的类型、加密算法和…...
基于springboot+vue的便利店信息管理系统
博主主页:猫头鹰源码 博主简介:Java领域优质创作者、CSDN博客专家、公司架构师、全网粉丝5万、专注Java技术领域和毕业设计项目实战 主要内容:毕业设计(Javaweb项目|小程序等)、简历模板、学习资料、面试题库、技术咨询 文末联系获取 项目介绍…...
在ubuntu18.04上编译C++版本jsoncpp/opencv/onnxruntime且如何配置CMakelist把他们用起来~
这篇文章背景是笔者在ubuntu上编译C代码,依赖一些包,然后需要编译并配置到CMakelist做的笔记。主要也是一直不太懂CMakellist,做个笔记以防忘记,也给读者提供一站式的参考,可能您需要的不是这几个包,但大同…...
大二上学期学习计划
这个学期主要学习的技术有SpringBoot,Vue,MybatisPlus,redis,还有要坚持刷题,算法不能落下,要坚持一天至少刷2道题目,如果没有布置任务就刷洛谷上面的,有任务的话就尽量完成任务&…...
【python爬虫—星巴克产品】
文章目录 需求爬取星巴克产品以及图片,星巴克菜单 python爬虫爬取结果 需求 爬取星巴克产品以及图片,星巴克菜单 网页分析: 首先,需要分析星巴克官方网站的结构,了解菜单栏的位置、布局以及菜单项的标签或类名等信息…...
shell SQL 变量 Oracle shell调用SQL操作DB
注意 : v\\\$ 用法, “v\\\$session ” ""不能用 sqlplus -S / as sysdba << EOF set pagesize 0 set verify off set feedback off set echo off col coun new_value v_coun select count(*) coun from dual; EOF value"$?"VALUE…...
【校招VIP】java线程池考点之核心线程数
考点介绍: 线程池是这一两年java大厂提问频度飙升的考点,需要从池子的概念理解相关参数和方法 java线程池考点之核心线程数-相关题目及解析内容可点击文章末尾链接查看! 一、考点试题 1、请列举一下启动线程有哪几种方式,之后再…...
[每周一更]-(第61期):Rust入门策略(持续更新)
一门语言的学习,就要从最基本的语法开始认识,再分析不同语言的区别,再加上实战,才能更快的学会,领悟到作者的设计思想; 介绍 Rust编程练习 开发工具VSCode及插件 社区驱动的 rust-analyzerEven Better T…...
线程安全问题的原因及解决方案
要想知道线程安全问题的原因及解决方案,首先得知道什么是线程安全,想给出一个线程安全的确切定义是复杂的,但我们可以这样认为:如果多线程环境下代码运行的结果是符合我们预期的,即在单线程环境应该的结果,…...
基于matlab中点放炮各类地震波时距曲线程序
完整程序: clear all dx50;x-500:dx:500;%炮检距 h100;V11500; theta25*pi/180; V2V1/sin(theta); t1sqrt(x.*x4*h*h)/V1;%反射波时距曲线 t2abs(x)./V1;%直达波时距曲线 %折射波时距曲线 xm2*h*tan(theta);%求盲区 k1; for i1:length(x) if x(i)<-xm …...
vue中el-dialog 中的内容没有预先加载,因此无法获得内部元素的ref 的解决方案 使用强制提前加载dialog方法
问题描述 在没有进行任何操作的时候,使用 this.$refs.xxxx 无法获取el-dialog中的内部元素,这个问题会导致很多bug,其中目前网络上也有许多关于这个问题的解决方案,但是大多数是使用el-dialog中的open在dialog打开的时候使用thi…...
vue-h5移动Web的rem配置
H5移动的适配方案 rem rem适配方案是兼容性比较好的移动端适配方案,rem支持大部分的移动端系统和机型。 rem是相对于根元素的字体大小的单位。本质上就是一个相对单位,和em的区别是:em是依赖父元素的字体来计算,rem是依赖根元素…...
企业级数据仓库-数仓实战
数仓实战 安装包大小 安装清单 环境搭建 一、环境搭建01(机器准备) 准备好三台虚拟机,并进行修改hostname、在hosts文件增加ip地址和主机名映射 。 1、设置每个虚拟机的hostname vi /etc/sysconfig/network 修改HOSTNAMEnode02修改hostna…...
Spring Boot 下载文件(word/excel等)文件名中文乱码问题|构建打包不存在模版文件(templates等)
Spring Boot 下载文件(word/excel等)文件名中文乱码问题|构建打包不存在模版文件(templates等) 准备文件,这里我放在resource下的templates路径 在pom中配置构建打包的资源,更新maven 如果使用了assembly打包插件这样配置可能仍不生效&#…...
Ansible数组同步至Shell脚本数组中
1、ansible中定义数组,我以 ccaPojectList 数组为例子,如下图数组内容 2、需要写一个j2模板的Shell脚本,在j2模板的Shell脚本中引用ansible的 ccaPojectList 数组,大致如下图: {% for item in ccaPojectList %} "{{ item }…...
私域流量的优势
私域流量是指由自身品牌或个人拥有并具备完全掌控权的流量资源。它相比于传统的广告推广,拥有独特的优势。 首先,私域流量能够更加精准地定位目标用户,实现精准传播。不再盲目投放广告,而是通过建立自身社群、粉丝群,获…...
Java 中“1000==1000”为false,而”100==100“为true?
如果你运行下面的代码: Integer a 1000, b 1000; System.out.println(a b);//1Integer c 100, d 100; System.out.println(c d);//2你会得到: false true基本知识:我们知道,如果两个引用指向同一个对象,用表示它们是相等的。如果两…...
智慧医疗能源事业线深度画像分析(上)
引言 医疗行业作为现代社会的关键基础设施,其能源消耗与环境影响正日益受到关注。随着全球"双碳"目标的推进和可持续发展理念的深入,智慧医疗能源事业线应运而生,致力于通过创新技术与管理方案,重构医疗领域的能源使用模式。这一事业线融合了能源管理、可持续发…...
【机器视觉】单目测距——运动结构恢复
ps:图是随便找的,为了凑个封面 前言 在前面对光流法进行进一步改进,希望将2D光流推广至3D场景流时,发现2D转3D过程中存在尺度歧义问题,需要补全摄像头拍摄图像中缺失的深度信息,否则解空间不收敛…...
跨链模式:多链互操作架构与性能扩展方案
跨链模式:多链互操作架构与性能扩展方案 ——构建下一代区块链互联网的技术基石 一、跨链架构的核心范式演进 1. 分层协议栈:模块化解耦设计 现代跨链系统采用分层协议栈实现灵活扩展(H2Cross架构): 适配层…...
spring:实例工厂方法获取bean
spring处理使用静态工厂方法获取bean实例,也可以通过实例工厂方法获取bean实例。 实例工厂方法步骤如下: 定义实例工厂类(Java代码),定义实例工厂(xml),定义调用实例工厂ÿ…...
【学习笔记】深入理解Java虚拟机学习笔记——第4章 虚拟机性能监控,故障处理工具
第2章 虚拟机性能监控,故障处理工具 4.1 概述 略 4.2 基础故障处理工具 4.2.1 jps:虚拟机进程状况工具 命令:jps [options] [hostid] 功能:本地虚拟机进程显示进程ID(与ps相同),可同时显示主类&#x…...
RSS 2025|从说明书学习复杂机器人操作任务:NUS邵林团队提出全新机器人装配技能学习框架Manual2Skill
视觉语言模型(Vision-Language Models, VLMs),为真实环境中的机器人操作任务提供了极具潜力的解决方案。 尽管 VLMs 取得了显著进展,机器人仍难以胜任复杂的长时程任务(如家具装配),主要受限于人…...
Sklearn 机器学习 缺失值处理 获取填充失值的统计值
💖亲爱的技术爱好者们,热烈欢迎来到 Kant2048 的博客!我是 Thomas Kant,很开心能在CSDN上与你们相遇~💖 本博客的精华专栏: 【自动化测试】 【测试经验】 【人工智能】 【Python】 使用 Scikit-learn 处理缺失值并提取填充统计信息的完整指南 在机器学习项目中,数据清…...
在RK3588上搭建ROS1环境:创建节点与数据可视化实战指南
在RK3588上搭建ROS1环境:创建节点与数据可视化实战指南 背景介绍完整操作步骤1. 创建Docker容器环境2. 验证GUI显示功能3. 安装ROS Noetic4. 配置环境变量5. 创建ROS节点(小球运动模拟)6. 配置RVIZ默认视图7. 创建启动脚本8. 运行可视化系统效果展示与交互技术解析ROS节点通…...
五、jmeter脚本参数化
目录 1、脚本参数化 1.1 用户定义的变量 1.1.1 添加及引用方式 1.1.2 测试得出用户定义变量的特点 1.2 用户参数 1.2.1 概念 1.2.2 位置不同效果不同 1.2.3、用户参数的勾选框 - 每次迭代更新一次 总结用户定义的变量、用户参数 1.3 csv数据文件参数化 1、脚本参数化 …...
接口 RESTful 中的超媒体:REST 架构的灵魂驱动
在 RESTful 架构中,** 超媒体(Hypermedia)** 是一个核心概念,它体现了 REST 的 “表述性状态转移(Representational State Transfer)” 的本质,也是区分 “真 RESTful API” 与 “伪 RESTful AP…...
