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

news2024/11/30 14:27:28

简介

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 pytest

def 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 pytest

data= [(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 ==c

    def 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 ==expect

    def 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.param
    yield name
    print(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.param
    yield param
    print(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.param
    yield user
    print("账号:%s" % user)

@pytest.fixture()
def login_pwd(request):
    pwd = request.param
    yield pwd
    print("密码:%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.param
    yield user
    print("账号:%s" % user)

@pytest.fixture(scope="function")
def login_pwd(request):
    pwd = request.param
    yield pwd
    print("密码:%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.coloradmin.cn/o/1007746.html

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

相关文章

【javaSE】 枚举与枚举的使用

文章目录 🎄枚举的背景及定义⚾枚举特性总结: 🌲枚举的使用🚩switch语句🚩常用方法📌示例一📌示例二 🎍枚举优点缺点🌴枚举和反射🚩枚举是否可以通过反射&…

【基本数据结构 三】线性数据结构:栈

学习了数组和链表后,再来看看第三种线性表结构,也就是栈,栈和后边讲的队列一样是一种受限的线性表结构,正是因为其使用有限制,所以对于一些特定的需要操作可控的场合,受限的结构就非常有用。 栈的定义 我们平时放盘子的时候,都是从下往上一个一个放;取的时候,我们也…

矩阵系统全方位管理多平台1000多个账号,实现精准化运营获客!

全自动化视频综合处理工具! ​ 普通的剪辑软件是不可能实现自动化,一个人一天制作3000条视频!​必须要借助高效率的工具【呆头鹅批量剪辑软件】探店混剪系统,导入大量的素材,就能自动帮你批量处理,满…

第28章_瑞萨MCU零基础入门系列教程之基于面向对象的工程结构

本教程基于韦东山百问网出的 DShanMCU-RA6M5开发板 进行编写,需要的同学可以在这里获取: https://item.taobao.com/item.htm?id728461040949 配套资料获取:https://renesas-docs.100ask.net 瑞萨MCU零基础入门系列教程汇总: ht…

Django05_反向解析

Django05_反向解析 5.1 反向解析概述 随着功能的不断扩展,路由层的 url 发生变化,就需要去更改对应的视图层和模板层的 url,非常麻烦,不便维护。这个时候我们可以通过反向解析,将 url解析成对应的 试图函数 通过 path…

OSCP系列靶场-Esay-Vegeta1保姆级

OSCP系列靶场-Esay-Vegeta1保姆级 目录 OSCP系列靶场-Esay-Vegeta1保姆级总结准备工作信息收集-端口扫描目标开放端口收集目标端口对应服务探测 信息收集-端口测试22-SSH端口的信息收集22-SSH端口版本信息与MSF利用22-SSH协议支持的登录方式22-SSH手动登录尝试(无)22-SSH弱口令…

魔众携手ModStart上线全新模块市场,支持模板主题

ModStart模板主题 对于很多新手或者是缺乏经验的开发者来说,快速建站具有一定的难度,总是一件让人头疼的问题。 ModStart为开发者提供了一些模板主题供开发者选购使用,模块市场包含了丰富的模块,后台一键快速安装,让开…

Botowski:SEO友好的AI内容生成器

【产品介绍】 名称 Botowski 具体描述 Botowski是一个人工智能内容生成器,可以被撰稿人、企业主和其他人用来创建高质量的内容。 它可以创建各种主题的文章、博客文章,甚至散文。Botowski的设计是用户友好的;你所需要做…

Java笔记042-反射章节练习

反射章节练习 练习1:通过反射修改私有成员变量 定义PrivateTest类,有私有name属性,并且属性值为helloKitty提供getName的公有方法创建PrivateTest的类,利用Class类得到私有的name属性,修改私有的name属性值&#xff…

过拟合、欠拟合、泛化误差、训练误差

模型容量的影响: 泛化误差: 当训练的模型的容量过了最优点时,泛化误差反而升高,这是由于模型过于关注细节导致,模型也同时记住噪声;当拿来一个真的数据时,模型会被一些无关紧要的细节所干扰。 …

Python数据分析 — 数据分析概念、重要性、流程和常用工具

前言:Hello大家好,我是小哥谈。Python数据分析是利用Python编程语言进行数据处理、转换、清洗、可视化和建模的过程。Python在数据科学领域非常流行,有许多强大的库和工具可供使用,例如NumPy、Pandas、Matplotlib和Scikit-learn等…

问道管理:iPhone15系列发布 星闪技术快速商用

9月12日,沪指盘中窄幅震动收拾,创业板指午后下探。到收盘,沪指跌0.18%报3137.06点,深成指微跌0.08%报10373.99点,创业板指跌0.59%报2051.04点;两市算计成交7083亿元,较此前一日削减1329亿元&…

UPS电源UL1778认证,不间断电源系统ul1778认证

UPS电源UL1778认证,不间断电源系统ul1778认证 UL认证-不间断电源系统ul1778认证范围: 不间断电源系统:UPS即不间断电源(Uninterruptible Power Supply),是一种含有储能装置的不间断电源。主要用于给部分对电源稳定性要求较高的设…

JavaScript与jQuery(上篇)

JavaScript与jQuery笔记(上篇) 一、引入JavaScript二、快速入门三、数据类型快速过一遍四、严格检查模式strict五、详解字符串六、数组详解七、对象详解八、流程控制,判断,循环九、Map、Set集合(ES6才出来的&#xff…

FD1257H 带有嵌入式霍尔传感器的智能电机驱动器芯片

FD1257H 带有嵌入式霍尔传感器的智能电机驱动器芯片 特征 电机驱动器与集成霍尔传感器 锁关闭保护和自动重启功能 精确的磁开关阈值 “软开关“相位切换技术,以减少振动和声噪声 热关闭保护 可在SIP-4L包 为12V系统 一般说明 FD1257H是一个嵌入式霍尔传感器的单线圈…

帆软FineReport决策报表Tab实现方案

最近有个需求是要做首页展示,为了减少前端工作量,利用采购的帆软FineReport来实现,记录过程,方便备查。 需求 做个Tab页,实现多个页切换。 方案一、利用帆软自带切换 帆软自带的有Tab控件,可实现切换&a…

多线程案例(1) - 单例模式

目录 单例模式 饿汉模式 懒汉模式 前言 多线程中有许多非常经典的设计模式(这就类似于围棋的棋谱),这是用来解决我们在开发中遇到很多 "经典场景",简单来说,设计模式就是一份模板,可以套用。…

江西服装学院图书馆藏《乡村振兴战略下传统村落文化旅游设计》许少辉八一新著

江西服装学院图书馆藏《乡村振兴战略下传统村落文化旅游设计》许少辉八一新著

浅谈C++|STL之string篇

一.string的基本概念 本质 string是C风格的字符串,而string本质是一个字符串 string和char * 区别 char * 是一个指针string是一个类,类内部封装了char *,管理这个字符串,是一个char * 型容器。 特点 string类内部封装了很多成…

Unity技术手册-UGUI零基础详细教程-Canvas详解

点击跳转专栏>Unity3D特效百例点击跳转专栏>案例项目实战源码点击跳转专栏>游戏脚本-辅助自动化点击跳转专栏>Android控件全解手册点击跳转专栏>Scratch编程案例点击跳转>软考全系列点击跳转>蓝桥系列 👉关于作者 专注于Android/Unity和各种游…