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基本知识:我们知道,如果两个引用指向同一个对象,用表示它们是相等的。如果两…...
Golang 面试经典题:map 的 key 可以是什么类型?哪些不可以?
Golang 面试经典题:map 的 key 可以是什么类型?哪些不可以? 在 Golang 的面试中,map 类型的使用是一个常见的考点,其中对 key 类型的合法性 是一道常被提及的基础却很容易被忽视的问题。本文将带你深入理解 Golang 中…...
React---day11
14.4 react-redux第三方库 提供connect、thunk之类的函数 以获取一个banner数据为例子 store: 我们在使用异步的时候理应是要使用中间件的,但是configureStore 已经自动集成了 redux-thunk,注意action里面要返回函数 import { configureS…...
MySQL 部分重点知识篇
一、数据库对象 1. 主键 定义 :主键是用于唯一标识表中每一行记录的字段或字段组合。它具有唯一性和非空性特点。 作用 :确保数据的完整性,便于数据的查询和管理。 示例 :在学生信息表中,学号可以作为主键ÿ…...

给网站添加live2d看板娘
给网站添加live2d看板娘 参考文献: stevenjoezhang/live2d-widget: 把萌萌哒的看板娘抱回家 (ノ≧∇≦)ノ | Live2D widget for web platformEikanya/Live2d-model: Live2d model collectionzenghongtu/live2d-model-assets 前言 网站环境如下,文章也主…...

windows系统MySQL安装文档
概览:本文讨论了MySQL的安装、使用过程中涉及的解压、配置、初始化、注册服务、启动、修改密码、登录、退出以及卸载等相关内容,为学习者提供全面的操作指导。关键要点包括: 解压 :下载完成后解压压缩包,得到MySQL 8.…...

破解路内监管盲区:免布线低位视频桩重塑停车管理新标准
城市路内停车管理常因行道树遮挡、高位设备盲区等问题,导致车牌识别率低、逃费率高,传统模式在复杂路段束手无策。免布线低位视频桩凭借超低视角部署与智能算法,正成为破局关键。该设备安装于车位侧方0.5-0.7米高度,直接规避树枝遮…...

何谓AI编程【02】AI编程官网以优雅草星云智控为例建设实践-完善顶部-建立各项子页-调整排版-优雅草卓伊凡
何谓AI编程【02】AI编程官网以优雅草星云智控为例建设实践-完善顶部-建立各项子页-调整排版-优雅草卓伊凡 背景 我们以建设星云智控官网来做AI编程实践,很多人以为AI已经强大到不需要程序员了,其实不是,AI更加需要程序员,普通人…...
虚幻基础:角色旋转
能帮到你的话,就给个赞吧 😘 文章目录 移动组件使用控制器所需旋转:组件 使用 控制器旋转将旋转朝向运动:组件 使用 移动方向旋转 控制器旋转和移动旋转 缺点移动旋转:必须移动才能旋转,不移动不旋转控制器…...

职坐标物联网全栈开发全流程解析
物联网全栈开发涵盖从物理设备到上层应用的完整技术链路,其核心流程可归纳为四大模块:感知层数据采集、网络层协议交互、平台层资源管理及应用层功能实现。每个模块的技术选型与实现方式直接影响系统性能与扩展性,例如传感器选型需平衡精度与…...

【见合八方平面波导外腔激光器专题系列】用于干涉光纤传感的低噪声平面波导外腔激光器2
----翻译自Mazin Alalus等人的文章 摘要 1550 nm DWDM 平面波导外腔激光器具有低相位/频率噪声、窄线宽和低 RIN 等特点。该腔体包括一个半导体增益芯片和一个带布拉格光栅的平面光波电路波导,采用 14 引脚蝶形封装。这种平面波导外腔激光器设计用于在振动和恶劣的…...