Pytest进阶之fixture的使用(超详细)
目录
Fixture定义
Fixture使用方式
作为参数使用
Fixture间相互调用(作为参数调用)
作为conftest.py文件传入
Fixture作用范围Scope
function
class
module
session
Fixture中params和ids
Fixture中autouse
Fixture中Name
总结
pytest fixture 是一种用来管理测试依赖和资源的机制。
简单来说,就是做初始化准备,比如一些测试用例需要打开浏览器或者链接数据库才能进行测试,因此我们需要在有需要的测试用例面前加上fixture进行测试前的资源准备。
Fixture定义
通过在函数前面加上
@pytest.fixture()装饰器来装饰一个函数,那么被装饰的这个函数就是一个fixture
先来简单的用一下:
我们在一个普通函数前面加上@pytest.fixture()
@pytest.fixture()
def fixtureFunc():return "I am Fixture"
这样这个函数就是一个fixture了,然后我们在用例中使用这个fixture
class TestDemo:def test_case1(self,fixtureFunc):print(fixtureFunc)assert fixtureFunc == "I am Fixture"
这个方式是作为参数传入,后面还有其它的传入方式,我们等下再说
运行后我们发现已经成功输出了fixture函数中的值,而且用例也passed了
Fixture使用方式
Fixture共三种使用方式:
1.作为参数传入
2.fixture相互调用(也相当于作为参数传入)
3.作为conftest.py文件传入
我接下来会分别讲这三种使用方式
作为参数使用
我创建2个fixture函数,分别为login和logout,login如果被调用输出“登录”,并返回“Account”;logout如果被调用,则输出“退出”,并返回“Exit”
然后我在测试类中创建3个测试方法:
第一个case 我在参数中传入login,并输出
第二个case 不传入任何参数
第三个case 两个fixture(login,logout)全部传入,也输出
如下:
import pytest@pytest.fixture()
def login():print("登录")return "Account"@pytest.fixture()
def logout():print("退出")return "Exit"class TestDemo:def test_case1(self,login):print("我传入了Login Fixture")assert login == "Account"def test_case2(self):print("我没传入任何 Fixture")def test_case3(self,login,logout):print("我传入了两个Fixture")assert login == "Account"assert logout == "Exit"if __name__ == '__main__':pytest.main(['-s','test_2.py'])
预期结果:
case1:首先在参数中调用了login,则会自动寻找login的fixture,找到后输出
“登录”和“我传入了Login Fixture”
case2:由于没有传入任何Fixture,所以只会输出“我没传入任何 Fixture”
case3:两个fixture都传入了,那么输出“登录”和“退出”,以及测试方法本身的“我传入了两个Fixture”
我们运行验证一下结果:
可以看到谁出结果符合我们的预期,这便是作为参数的一种使用方法
Fixture间相互调用(作为参数调用)
该方法其实是属于作为参数调用的一种特殊情况,只不过是是某个Fixture方法又调用了其他Fixture方法,而不是测试用例调用Fixture方法
现在有一个login和account的fixture,login参数中调用了account。
在测试用例中,有一个用例调用了login,另一个用例调用了account,先看代码:
import pytest@pytest.fixture()
def account():print("Account")return "Ret-Account"#调用上面的account fixture
@pytest.fixture()
def login(account):print("Login")class TestDemo:def test_case1(self,login):print("调用了login,返回值为{}".format(login))def test_case2(self,account):print("调用了account,返回值为{}".format(account))
我们注意,login是没有返回值的,而account有一个返回值
那我们执行用例,结果是什么呢?
在命令行或终端输入 pytest -s .\test_2.py,,文件名和路径改成自己的就可以
可以看到。test_case1调用login后,login的参数中有account fixture,因此先调用了account,然后再执行login自己内部的逻辑,因此输出了Login,最后执行了test_case1中的逻辑
但是返回值是None,这是因为返回值永远是上一次调用的函数返回的值,虽然login调用了account,account给login返回了一个值,但是login没用这个值,也没有返回任何值给test_case1,所以这个测试用例是没有返回值的
作为对照,test_case2直接调用了account,然后返回了Ret-Account,也是符合我们预期的
做一下总结及补充:
- 1.Fixture之间支持相互调用,但普通函数直接调用fixture是不生效的,必须在测试函数中调用才会生效
- 2.多层fixture调用时,会最先执行最后一层fixture,然后再依次向前执行。类似于C语言中的压栈。例如这个例子调用顺序是test_case1->login->account,那么他就会先执行account,再执行login,最后执行test_case1
- 3.不会自动return 上一层函数返回的值。例如login 接收到了上一层account的返回值,但是它并没有返回account返回的这个值,而是None,取决login本身return 的值
作为conftest.py文件传入
如果我们想在多个测试文件中,使用同一个fixture,那么我们可以单独将这个fixture拿出来,放到conftest.py文件中。
下面是使用conftest.py文件的规则:
- 1.conftest.py文件名是固定的,不可以修改
- 2.conftest.py与运行用例在同一个包下,并且该包中有__init__.py文件
- 3.运行其他测试文件时会自动寻找conftest.py文件,而不需要手动导入
我们首先创建一个名为conftest.py文件,然后再新建两个.py文件,分别使用conftest.py文件中的fixture
conftest.py:
@pytest.fixture()def login():print("Login")return "Ret-Login"
test_1.py
import pytestdef test_case1(login):print(login)assert login == "Ret-Login"
test_2.py
import pytestdef test_case2(login):assert login != "Ret-Login"
然后我们在命令行执行这两个文件:
pytest -s .\test_1.py .\test_2.py
可以看到case1确实如预期结果所示,调用了conftest.py中的fixture,正确输出而且断言正确
case2也调用了fixture,断言错误,和预期一样
Fixture作用范围scope
Fixture的参数如下:
@pytest.fixture(scope = "function",params=None,autouse=False,ids=None,name=None)
fixture的作用范围(scope)共有4种:function,class,module,session
范围依次递增的:即function < class < module < session
我依次来讲解这些作用范围
function
其实我们刚才使用的是例子scope一直是function,它也是默认值
当scope=“function”时,只要有测试函数显示调用fixture时,都会执行一次fixture。但是如果测试函数没有调用fixture,那么就不会执行fixture
如下:
import pytest@pytest.fixture()
def login():print("Login")return "Ret-Login"class TestDemo:#调用login,则会调用一次fixturedef test_case1(self,login):print("case1")#不调用login,则不会调用fixturedef test_case2(self):print("case2")#调用login,则第二次调用fixture,加上case1,一共调用了两次def test_case3(self,login):print("case3")assert login == "Ret-Login"
我们看运行结果:
可以看到第一次和第三次都调用了Login,一共调用了2次,第二次没调用
所以总结是:只要有测试方法调用了fixture,那么fixture都会被执行一次
class
当scope=“class”时,有两种场景:
- 1.测试类下所有的测试方法都调用了fixture,那么fixture只执行一次,时机为测试类中 所有测试方执行前。
- 2.测试类下只有部分测试方法调用了fixture,那么fixture只执行一次,时机为在测试类中 第一个调用fixture的测试方法前执行
不理解可以看下面的例子:
对于1:测试类下所有的测试方法都调用了fixture
import pytest@pytest.fixture(scope="class")
def login():print("Scope='class'")return "Ret-Login"class TestDemo:def test_case1(self,login):print("case1")assert login == "Ret-Login"def test_case2(self,login):print("case2")def test_case3(self,login):print("case3")assert login != "Ret-Login"
测试结果:
可以看到虽然类中有3个测试函数都调用了fixture,但是由于scope=“class”,所以最终fixture在所有测试方法执行前 只调用了一次
对于2:测试类下只有部分测试方法调用了fixture
import pytest@pytest.fixture(scope="class")
def login():print("Scope='class'")return "Ret-Login"class TestDemo:def test_case1(self):print("case1")def test_case2(self,login):print("case2")def test_case3(self,login):print("case3")assert login == "Ret-Login"
我们预期的是,先执行完case1,然后case2中由于是第一个调用login fixture,所以此时调用一次login,然后case3就不再调用login了,因为scope=“class”,所以只从第一个调用处调用一次、
结果如下:
可以看到确实结果如我们所预料的,而且case3正常通过,说明login已经能正常使用了
module
当scope=“module”时,则范围会对当前整个.py文件生效
与class相同,会在第一个调用fixture的测试方法前调用一次然后生效,后面即使再有 其他测试方法调用fixture,也不会再调用
import pytest@pytest.fixture(scope="module")
def login():print("Scope='module'")return "Ret-Login"def test_case(login):print("test_case")class TestDemo:def test_case1(self,login):print("case1")def test_case2(self,login):print("case2")def test_case3(self,login):print("case3")assert login == "Ret-Login"
从上向下执行,会先执行test_case,然后调用一次login fixture对后面其他调用的也就生效了,后面即使TestDemo中所有的测试方法都调用了login,也不会在调用了
可以看到也就在test_case第一次调用前 调用了一次fixture,后面都没有再调用了
session
当scope=“session”时,则范围会对所有的.py文件生效
还记得我们刚才说的conftest.py文件吗?其实该范围主要是应用在这里
这里有两个.py文件,test_1.py,test_2.py.
如果conftest.py文件中的fixture的scope=“module”
那么当test_1.py文件第一次测试方法调用fixture后,test_1.py文件里后面其它的测试方法便不再调用,但是如果test_1.py文件执行完后,此时test_2.py也有测试方法调用fixture,那么测试还会再调用一次,这样相当于调用了2次
先看代码,看着代码理解会容易一些:
conftest.py:
import pytest@pytest.fixture(scope="module")
def login():print("Scope='module'")return "Ret-Login"
test_1.py:
import pytestdef test_case1(login):print("case1")assert login == "Ret-Login"def test_case2(login):print("case2")def test_case3(login):print("case3")
test_2.py:
import pytestdef test_case(login):print("test_case")class TestDemo:def test_case1(self,login):print("case1")def test_case2(self,login):print("case2")def test_case3(self,login):print("case3")assert login == "Ret-Login"
可以看到此时scope是“module”,我们运行:
可以看到此时确实一个文件都执行了一次
此时我把conftest.py文件中的scope换成“session”:
import pytest@pytest.fixture(scope="session")
def login():print("Scope='session'")return "Ret-Login"
运行:
可以看到此时虽然有多个测试文件,但fixture只被调用了一次 ,这便是session的作用了
Fixture中参数列表params和ids
params是fixture的第二个参数,它是Fixture的可选形参列表,支持列表传入
默认不写为None;
如果传入列表,对于传入的列表的每个值(参数),fixture都会执行一次。可以与第三个参数ids搭配使用,ids是每个参数的标识。类似for循环
在pytest中有一个内建的fixture叫做request,request.param
是 pytest 提供的一种机制,用于访问 fixture 参数化过程中每个参数值。
调用每一个参数,固定写法:
request.param
比如我想写一个带参数列表的fixture,然后每次都返回这几个参数,写法如下(这里我搭配了ids):
@pytest.fixture(params=[1, 2, 3], ids=["param1", "param2", "param3"])
def some_fixture(request):return request.param
然后我们使用一个测试用例来调用这个fixture
import pytest@pytest.fixture(params=[1, 2, 3], ids=["param1", "param2", "param3"])
def some_fixture(request):return request.paramdef test_fixture(some_fixture):print(f"Running test with param: {some_fixture}")assert some_fixture > 0
可以看到三个值都已经被输出出来了,说明那3个参数全部被传入fixture了
如果我再加一个测试用例:
可以看到1,2,3又被执行了一次
说明对于每个测试用例,fixture都会将参数列表的值传入执行。
比如fixture参数列表有3个,有两个测试用例
那么fixture一共会被执行2*3=6次
Fixture中autouse
autouse默认为Fasle
pytest 中的 fixture 只有在被显式地调用或作为测试函数的参数传递时才会执行。但是,如果你希望某个 fixture 在所有测试函数执行之前或之后自动执行,可以使用 autouse=True
来实现这一点。
即不需要再测试方法前面加上fixture调用,不需要加任何东西,他就会自动调用。
哪怕你没有使用该fixture,也会调用一次
我举个例子
@pytest.fixture(autouse=False)
def testAutouse():print("autouse is called")def test_case1(login):print("case1")def test_case2():print("case2")
可以看到只有显式调用fixture,才被执行了
但是当我们把autouse=True
可以看到即使case2没有调用testautouse,它也被调用了一次,这便是autouse的作用
Fixture中Name
pytest 中,fixture 可以通过参数传递一个可选的 name
参数,这个参数的作用是为 fixture 显式命名,使得在测试报告中能够更清晰地识别和显示这个 fixture 的名称。
如果使用了name,那么后面传参只能使用这个name进行传参,而原本的fixture的名字会失效,
import pytest
#指定old_Fixture新名字为new_Fixture
@pytest.fixture(name="new_Fixture")
def old_Fixture():print("hello, Fixture")def test_case1(new_Fixture):print("case1")
def test_case2(old_Fixture):print("case2")
此时我们再运行:
可以看到报错,说old_Fixture未找到 ,就印证了刚才我们所说的
总结
在 pytest 中,fixture 是一种用于管理测试依赖和资源的强大机制。它可以在测试函数之前设置(setup)需要的环境,并在测试函数执行后进行清理(teardown)。以下是 fixture 的关键用法和参数总结:
定义 fixture:
- 1.使用 @pytest.fixture 装饰器定义 fixture 函数。
- 2.Fixture 函数可以接受测试函数传入的参数,这些参数可以是其他 fixture 或者测试函数的参数。
- 3.可以设置不同作用域来控制 fixture 的生命周期,如 scope="function"、scope="module"、scope="class" 和 scope="session"。
参数化 fixture:
- 1.使用 params 参数为 fixture 提供多个参数化实例。
- 2.可以使用 ids 参数为每个参数化实例指定可读的标识符。
- 3.request.param 用于在 fixture 函数中访问当前的参数化实例。
自动使用 fixture:
- 使用 autouse=True 参数使得 fixture 在每个测试函数执行之前自动调用,无需在测试函数中显式引用。
显式命名 fixture:
- 使用 name 参数为 fixture 显式设置一个名称,以便在测试报告中显示更有意义的名称。
通过合理使用 fixture,可以使得测试代码更清晰、模块化,并且能够提高测试的可维护性和可靠性。
到这里关于Pytest中的fixture机制就讲完了,如果感觉有疑问或者不懂,欢迎提问~
感谢你的阅读
相关文章:

Pytest进阶之fixture的使用(超详细)
目录 Fixture定义 Fixture使用方式 作为参数使用 Fixture间相互调用(作为参数调用) 作为conftest.py文件传入 Fixture作用范围Scope function class module session Fixture中params和ids Fixture中autouse Fixture中Name 总结 pytest fixture 是一种用来管理测试…...

GitHub 详解教程
1. 引言 GitHub 是一个用于版本控制和协作的代码托管平台,基于 Git 构建。它提供了强大的功能,使开发者可以轻松管理代码、追踪问题、进行代码审查和协作开发。 2. Git 与 GitHub 的区别 Git 是一个分布式版本控制系统,用于跟踪文件的更改…...

边界网关IPSEC VPN实验
拓扑: 实验要求:通过IPSEC VPN能够使PC2通过网络访问PC3 将整个路线分为三段 IPSEC配置在FW1和FW2上,在FW1与FW2之间建立隧道,能够传递IKE(UDP500)和ESP数据包,然后在FW1与PC2之间能够流通数据…...

力扣高频SQL 50题(基础版)第六题
文章目录 1378. 使用唯一标识码替换员工ID题目说明思路分析实现过程结果截图总结 1378. 使用唯一标识码替换员工ID 题目说明 Employees 表: ---------------------- | Column Name | Type | ---------------------- | id | int | | name | varchar | ------…...

在一个事物方法中开启新事物,完成对数据库的修改
在Java中,使用Transactional注解来管理事务非常常见。但是,在一个已经标记为Transactional的方法内部调用另一个也标记了Transactional的方法时,如果不正确处理,可能会导致一些意料之外的行为。这是因为默认情况下,Spr…...

ffmpeg的vignetting filter
vignetting filter是暗角过滤器 vignetting filter在官网是vignette。但是我查了一下,vignetting应该是正确的表达,vignette是什么鬼? 官网参数 官书参数 参数解释 angle,x0,y0可以使用表达式。 angle:不知道什么意思…...

商场导航系统:从电子地图到AR导航,提升顾客体验与运营效率的智能解决方案
商场是集娱乐、休闲、社交于一体的综合性消费空间,随着商场规模的不断扩大和布局的日益复杂,顾客在享受丰富选择的同时,也面临着寻路难、店铺曝光率低以及商场管理效率低下等挑战。商场导航系统作为提升购物体验的关键因素,其重要…...

vue3中父子组件的双向绑定defineModel详细使用方法
文章目录 一、defineProps() 和 defineEmits()二、defineModel() 的双向绑定2.1、基础示例2.2、定义类型2.3、声明prop名称2.4、其他声明2.5、绑定多个值2.6、修饰符和转换器2.7、修饰符串联 一、defineProps() 和 defineEmits() 组件之间通讯,通过 props 和 emits…...

耳机、音响UWB传输数据模组,飞睿智能低延迟、高速率超宽带uwb模块技术音频应用
在数字化浪潮席卷全球的今天,无线通信技术日新月异,其中超宽带(Ultra-Wideband,简称UWB)技术以其独特的优势,正逐步成为无线传输领域的新星。本文将深入探讨飞睿智能UWB传输数据模组在音频应用中的创新应用…...

webpack配置报错:Invalid options object.
前言: 今天在使用webpack进行项目配置的时候,运行之后终端报错:Invalid options object. Dev Server has been initialized using an options object that does not match the API schema. - options has an unknown property inline. Thes…...

Java 并发编程:一文了解 Java 内存模型(处理器优化、指令重排序与内存屏障的深层解析)
大家好,我是栗筝i,这篇文章是我的 “栗筝i 的 Java 技术栈” 专栏的第 022 篇文章,在 “栗筝i 的 Java 技术栈” 这个专栏中我会持续为大家更新 Java 技术相关全套技术栈内容。专栏的主要目标是已经有一定 Java 开发经验,并希望进…...

谷粒商城实战笔记-64-商品服务-API-品牌管理-OSS前后联调测试上传
文章目录 1,拷贝文件到前端工程2,局部修改3,在品牌编辑界面使用上传组件4,OSS配置允许跨域5,测试multiUpload.vue完整代码singleUpload.vue完整代码policy.js代码 在Web应用开发中,文件上传是一项非常常见的…...

Springboot 开发之 RestTemplate 简介
一、什么是RestTemplate RestTemplate 是Spring框架提供的一个用于应用中调用REST服务的类。它简化了与HTTP服务的通信,统一了RESTFul的标准,并封装了HTTP连接,我们只需要传入URL及其返回值类型即可。RestTemplate的设计原则与许多其他Sprin…...

Django transaction.atomic()事务处理
在Django中,transaction.atomic()是一个上下文管理器,它会自动开始一个事务,并在代码块执行完毕后提交事务。如果在代码块中抛出异常,事务将被自动回滚,确保数据库的一致性和完整性。 在实际应用中,你可能需…...

2024.07-电视版免费影视App推荐和猫影视catvod、TVBox源(最新接口地址)
文章目录 电视版免费影视App推荐精选列表(2024.07可用筛选列表):2024.07可用筛选列表,盲盒资源打包合集下载安装说明真的是盲盒? 猫影视catvod、TVBoxTVBox源推荐可用列表目前不可用列表(前缀为错误状态码&…...

【Python】 基于Q-learning 强化学习的贪吃蛇游戏(源码+论文)【独一无二】
👉博__主👈:米码收割机 👉技__能👈:C/Python语言 👉公众号👈:测试开发自动化【获取源码商业合作】 👉荣__誉👈:阿里云博客专家博主、5…...

谷粒商城实战笔记-44-前端基础-Vue-整合ElementUI快速开发/设置模板代码
文章目录 一,安装导入ElementUI1,安装 element-ui2,导入 element-ui 二,ElementUI 实战1,将 App.vue 改为 element-ui 中的后台布局2,开发导航栏2.1 开发MyTable组件2.2 注册路由2.3 改造App.vue2.4 新增左…...
Android adb shell ps进程查找以及kill
Android adb shell ps进程查找以及kill 列出当前Android手机上运行的所有进程信息如PID等: adb shell ps 但是这样会列出一大堆进程信息,不便于定向查阅,可以使用关键词查找: adb shell "ps | grep 关键词" 关键词查…...

[OJ]水位线问题,1.采用回溯法(深度优先遍历求解)2.采用广度优先遍历求解
1.深度优先遍历 使用回溯法,深度优先遍历利用栈先进后出的特点,在加水控制水量失败时, 回到最近一次可对水进行加水与否的位置1.对于给定水量k,是否在[l,r]之间, 是:是否加水(加水y,用掉x,是否在[l,r]之间)(不加水y,用掉x,是否在[l,r]之间)先尝试加水,如…...

《华为数据之道》读书笔记六---面向自助消费的数据服务建设
七、从结果管理到过程管理, 从能“看”到能“管” 1、数据赋能业务运营 数字化运营旨在利用数字化技术获取、管理和分析数据,从而为企业的战略决策与业务运营提供可量化的、科学的支撑。 数字化运营归根结底是运营,旨在推动运营效率与能力的…...

go语言day18 reflect反射
Golang-100-Days/Day16-20(Go语言基础进阶)/day19_Go语言反射.md at master rubyhan1314/Golang-100-Days (github.com) 7-19 接口:底层实现_哔哩哔哩_bilibili 一、interface接口 接口类型内部存储了一对pair(value,Type) type interface { type *Type // 类型信…...

理解 Objective-C 中 `+load` 方法的执行顺序
理解 Objective-C 中 load 方法的执行顺序 在 Objective-C 中,load 方法是在类或分类被加载到内存时调用的。它在程序启动过程中非常早的阶段执行,用于在类或分类被加载时进行一些初始化工作。理解 load 方法的执行顺序对于编写可靠的 Objective-C 代码…...

C++:类和对象2
1.类的默认成员函数 默认成员函数就是用户没有显示实现编译器会自动生成的成员函数称为默认成员函数。一个类,我们在不写的情况下编译器会默认生成6个默认成员函数,分别是构造函数,析构函数,拷贝构造函数,拷贝赋值运算…...

Docker安装kkFileView实现在线文件预览
kkFileView为文件文档在线预览解决方案,该项目使用流行的spring boot搭建,易上手和部署,基本支持主流办公文档的在线预览,如doc,docx,xls,xlsx,ppt,pptx,pdf,txt,zip,rar,图片,视频,音频等等 官方文档地址:https://kkview.cn/zh-cn/docs/production.html 一、拉取镜像 do…...

ElasticSearch(四)— 数据检索与查询
一、基本查询语法 所有的 REST 搜索请求使用_search 接口,既可以是 GET 请求,也可以是 POST请求,也可以通过在搜索 URL 中指定索引来限制范围。 _search 接口有两种请求方法,一种是基于 URI 的请求方式,另一种是基于…...

Pytest之parametrize()实现数据驱动
一、Pytest之parametrize()实现数据驱动 方法: pytest.mark-parametrize(argsname,args_value) args_name:参数名称,用于将参数值传递给函数 args value:参数值:(列表和字典列表,元组和字典元组),有n个值那么用例执行n次 第一种用法…...

关于鸿蒙系统前景
鸿蒙系统的前景看起来非常乐观。 鸿蒙系统以其全新的分布式架构和快速运行速度,展现了其独特的优势。它没有历史包袱,可以轻量前进,这一点在开发适配上具有明显优势。此外,鸿蒙系统的最大优势在于其“万物互联”的…...

针对datax-web 中Swagger UI接口未授权访问
application.yml 添加以下配置 实现访问doc.html 以及/v2/api-docs 接口时需要进行简单的校验 swagger:basic:enable: trueusername: adminpassword: 12345 配置重启后再进行相关访问则需要输入用户名和密码...

生成式AI如何帮助小型企业高效运营?
即使只有几家或几十家店的小规模生意,也可以利用AI技术来提升效率。不管企业组织规模如何,未来可能会有新的工作流程需要适应。就像计算机编程一样,我们需要将业务逻辑拆解成多个可管理的小任务,并设计它们之间的协同关系。这样&a…...

2024最新网络安全自学路线,内容涵盖3-5年技能提升
01 什么是网络安全 网络安全可以基于攻击和防御视角来分类,我们经常听到的 “红队”、“渗透测试” 等就是研究攻击技术,而“蓝队”、“安全运营”、“安全运维”则研究防御技术。 无论网络、Web、移动、桌面、云等哪个领域,都有攻与防两面…...