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机制就讲完了,如果感觉有疑问或者不懂,欢迎提问~

感谢你的阅读

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

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

相关文章

回溯算法(相关解题):

求子集序列&#xff1a; 解题思路&#xff1a; 已知原集合的数据位数为N&#xff0c;则可以通过二进制比对原来集合&#xff0c;二进制位为1则输出集合上的该位数据&#xff0c;为0则空&#xff0c;二进制的01排序规律与子集的输出一致由集合的位数可以判断出二进制的范围 0 ~…

Direct3D 9的介绍以及Demo演示

文章目录 1、d3d9的介绍1. 概述2. 核心概念3. 初始化和渲染流程4. 常见用法5. 先进特性6. 总结 2、d3d9demo详解1.头文件和全局变量2.IGW 相关全局变量3.函数&#xff1a;CloseIGW4.函数&#xff1a;OpenIGW5.UI 控件和日志处理6.登录和登出相关函数7.登录回调函数8.DXUT 相关回…

P3-AI产品经理-九五小庞

AI产品的数据流向 美团外卖&#xff0c;实时只能调度 美团28分钟送达需求的分析 AI产品常用的算法 常用算法 常见的AI算法解析 自然语言生成NLG语音识别&#xff1a;科大讯飞&#xff0c;通义千问 虚拟现实机器学习平台 决策管理系统生物特征识别技术 RPA(机器人流程自动…

探索 GPT-4o Mini:开发者的新利器

文章目录 探索 GPT-4o Mini&#xff1a;开发者的新利器1. 引言2. GPT-4o Mini 的核心特点3. 使用 GPT-4o Mini 的实际案例3.1 客户支持自动化3.2 内容生成与创作3.3 代码生成与优化 4. 使用体验分享5. 未来展望6. 结论 探索 GPT-4o Mini&#xff1a;开发者的新利器 OpenAI 最新…

UE4-光照重建

当我们拉入新的光源和模型到我们的场景中后&#xff0c;会产生这样的情况&#xff1a; Preview:预览 表示此时由于光照物体所产生的阴影都是预览级别的并不是真正的效果。 方法一&#xff1a; 或者也可以在世界大纲中选中我们的光源&#xff0c;然后将我们的光源改变为可以…

JAVA基本概念(垃圾回收、API)- 10

一、垃圾分代回收机制 1. 垃圾回收针对的是堆内存 2. 对象在堆内存中存储,对象在使用完成之后会在不定的某个时刻被垃圾回收器(GC - Garbage Collector)解析 掉。现阶段回收过程无法手动控制。当调用构造方法的时候,创建好一个对象,因为Java中对每种数据类型都明确 给…

Jdk22新特性

JDK 22 引入了多项新特性,旨在提升 Java 语言的性能、简化开发过程以及增强代码的可读性和可维护性。以下是对 JDK 22 新特性的详细归纳: 核心Java库 外部函数和内存 API (JEP 454):提供了一个纯 Java 应用程序接口,用于替代 JNI(Java Native Interface),以支持直接调…

前端切片下载

要在Vue3前端实现文件切片下载&#xff0c;可以参考以下步骤&#xff1a; 分片函数&#xff1a;将文件分成多个小片段。 生成Blob对象&#xff1a;将片段转换为Blob对象。 创建下载链接&#xff1a;通过Blob对象创建下载链接。 合并下载的片段&#xff1a;下载完成后&#x…

判断字符串,数组方法

判断字符串方法 在JavaScript中&#xff0c;可以使用typeof操作符来判断一个变量是否为字符串。 function isString(value) {return typeof value string; } 判断数组 在JavaScript中&#xff0c;typeof操作符并不足以准确判断一个变量是否为数组&#xff0c;因为typeof会…

深入理解Python中的Pandas库

目录 Pandas简介安装PandasPandas的核心数据结构 SeriesDataFrame 数据加载与存储 从CSV文件读取数据从Excel文件读取数据从SQL数据库读取数据数据存储 数据操作 数据选择数据过滤数据排序数据分组与聚合数据透视表 数据清洗与处理 处理缺失值数据转换数据合并 数据可视化实战…

KingBase 下的 sys_hba.conf 详解

客户端访问KingbaseES数据库,需要建立身份的认证,sys_hba.conf相当于认证的黑白名单,可以通过配置sys_hba.conf允许或拒绝客户端对数据库服务器的访问。 sys_hba.conf原理: 客户端认证是由一个配置文件(通常名为sys_hba.conf并被存放在数据库集簇目录中)控制(HBA表示基…

《昇思25天学习打卡营第25天|第27天》

今天是学习的第二十七天&#xff0c;今天学习的是应用实践篇中计算机视觉中ShuffleNet图像分类。 从对ShuffleNet网络介绍开始学习&#xff0c;模型架构&#xff08;Pointwise Group Convolution&#xff0c;Channel Shuffle&#xff0c;ShuffleNet模块&#xff0c;构建Shuffl…

knowLedge-工具函数返回kb数值转换为KB,MB,GB等单位保留两位小数

1.场景 实现一个工具函数&#xff0c;将后端返回的单位为KB&#xff08;但实际上是kb&#xff0c;即千字节&#xff0c;注意大小写通常表示不同&#xff0c;这里我们按照常见需求处理为KB&#xff09;的数字转换成KB、MB、GB等形式&#xff0c;你可以按照以下步骤进行。这个函数…

【Mybatis整合Oracle】在 xml 文件中 WITH 子句的简单使用

在 Oracle SQL 中&#xff0c;WITH 子句用于定义一个或多个公共表表达式&#xff08;CTE, Common Table Expression&#xff09;&#xff0c;然后可以在主查询中引用这些表达式。WITH 子句通常用于简化复杂查询的结构&#xff0c;增强可读性&#xff0c;并避免重复编写相同的子…

# Redis 入门到精通(九)-- 主从复制(1)

Redis 入门到精通&#xff08;九&#xff09;-- 主从复制&#xff08;1&#xff09; 一、redis 主从复制 – 主从复制简介 1、互联网“三高”架构 高并发高性能高可用 2、你的“Redis”是否高可用&#xff1f; 1&#xff09;单机 redis 的风险与问题 问题1.机器故障  现…

C++ 鼠标轨迹API【神诺科技SDK】

一.鼠标轨迹模拟简介 传统的鼠标轨迹模拟依赖于简单的数学模型&#xff0c;如直线或曲线路径。然而&#xff0c;这种方法难以捕捉到人类操作的复杂性和多样性。AI大模型的出现&#xff0c;使得神诺科技 能够通过深度学习技术&#xff0c;学习并模拟更自然的鼠标移动行为。 二.…

java之对称字符串以及如何优化(链式编程)

import java.util.Scanner;public class ScannerDemo12 {public static void main(String[] args) {Scanner sc new Scanner(System.in);System.out.println("请输入一个字符串");String str sc.next();//链式编程StringBuilder sbnew StringBuilder();sb.append(s…

国内大陆地区huggingface连接不上的解决方案

简介 本文主要介绍国内大陆地区huggingface连接不上的解决方案,希望能对学习大模型的同学们有所帮助。 1. 背景 最近有不少同学反应无法正常下载huggingface的模型文件,亲自尝试使用git clone下载huggingface上的大模型文件时,也同样无法正常下载,以Meta-Llama-3-8B为例…

全国区块链职业技能大赛第九套区块链产品需求分析与方案设计

任务1-1:区块链产品需求分析与方案设计 房屋租赁平台中涉及到租客、房东、区块链租房平台、房屋等参与方,他们需要在区块链租房平台中完成账户注册、身份上链、出租房屋、生成合同等多种业务活动。通过对业务活动的功能分析,可以更好的服务系统的开发流程。基于房屋租赁平台…

数据结构之判断完全二叉树详解与示例(C,C++)

文章目录 一、判断完全二叉树的思路二、C语言实现三、C语言实现四、总结 完全二叉树是一种特殊的二叉树&#xff0c;它满足以下两个条件&#xff1a; 每一层&#xff08;除了最后一层&#xff09;都被严格地填充了节点。 最后一层的节点都尽可能地靠左对齐。 本文将详细介绍如…