当前位置: 首页 > news >正文

pytest之fixture中yield详解

1. fixture——yield介绍

fixture的teardown操作并不是独立的函数,用yield关键字呼唤teardown操作。前面通过fixture实现了在每个用例之前执行初始化操作,那么用例执行完之后,如需要清除数据(或还原)操作,可以使用yield来实现。

yield是一个关键字,它不是单独存在的,要写在fixture标记的固件中。我们在声明的固件fixture中加入yield关键字,在它下面写测试用例执行后想要运行的代码;其他有关于固件的使用没有任何差别。需要说明的一点是我们在pytest主函数中增加一个参数-setup-show,它会显示出固件的执行情况。

自动执行清理逻辑:无论测试是否通过、是否抛出异常,yield后的代码始终会被执行。这确保资源(如文件、网络连接)被正确释放。但是如果固件中的yield之前的代码也是相当于setup部分的代码,出现错误或断言失败,那么yield后的代码将不会再执行,当然测试用例中的代码也不会执行。

2. 基本原理:通过 yield 分割执行阶段

在 fixture 函数中,yield语句将代码分为两部分:

  • 前置操作yield之前的代码在测试执行前运行(类似于 setup)。
  • 返回值yield后的值作为 fixture 的返回值传递给测试函数。
  • 后置操作yield之后的代码在测试执行后运行(类似于 teardown),无论测试是否通过。

用法示例

#!/usr/bin/env python
# encoding: utf-8
'''
@Author  : 草木零
@Software: PyCharm
@File    : test_yield.py
@Time    : 2023/8/23 0:50
@desc   : fixture装饰的函数里,yield的代码,是pytest用例执行完后再执行的
'''
import pytest@pytest.fixture
def fix1():print('\nfix1,用例前置')yieldprint('\nfix1,用例执行完成,收尾')# 测试用例
def test_yield(fix1):print('fixture + yield的测试用例')if __name__ == '__main__':pytest.main(['-s', 'test_yield.py'])

控制台:
在这里插入图片描述

3. 处理异常的清理

yield前的代码抛出异常,yield后的清理代码不会执行。需使用try/finally包裹:

@pytest.fixture
def safe_setup():resource = Nonetry:resource = acquire_resource()  # 可能抛出异常yield resourcefinally:if resource:resource.release()  # 确保资源被释放

4. yield详解

在 Python 中,yield是创建生成器(Generator)的核心关键字。生成器是一种特殊的迭代器,它允许你在迭代过程中动态生成值,而不是一次性生成所有值。这种特性让生成器在处理大数据、优化内存和实现异步编程时非常有用。

yield: return 
yield: return + generator 的一部分
PS:带yield的函数才是完整的generator 

(1) 生成器的本质:按需生成的迭代器

生成器是 Python 中实现惰性计算的主要方式,它有两种形式:

a. 生成器函数(Generator Function)
使用yield关键字的函数,调用时返回一个生成器对象:

def count_up_to(n):i = 0while i <= n:yield i  # 暂停执行并返回当前值i += 1# 创建生成器对象(不会立即执行函数体)
gen = count_up_to(3)# 通过迭代获取值
print(next(gen))  # 输出: 0
print(next(gen))  # 输出: 1
print(next(gen))  # 输出: 2
print(next(gen))  # 输出: 3
print(next(gen))  # 抛出 StopIteration 异常

b. 生成器表达式(Generator Expression)
类似列表推导式,但使用圆括号:

gen = (x**2 for x in range(3))  # 创建生成器print(next(gen))  # 输出: 0
print(next(gen))  # 输出: 1
print(next(gen))  # 输出: 4

(2) yield 的核心作用:暂停与恢复执行

当生成器函数被调用时,函数体不会立即执行,而是返回一个生成器对象。每次调用next()时:

  • 生成器从上次暂停的位置继续执行(或从函数起始处开始)。
  • 执行到yield语句时,生成一个值并暂停执行。
  • 下一次调用next()时,继续执行yield之后的代码。

总结:yield和return的关系和区别

yield的函数是一个生成器,而不是一个函数了。这个生成器有一个函数就是next函数,next就相当于“下一步”生成哪个数,这一次的next开始的地方是接着上一次的next停止的地方执行的。所以调用next的时候,生成器并不会从yield_demo函数的开始执行,而是接着上一步开始,然后遇到yield后,return出要生成的数,此步就结束。

#!/usr/bin/env python
# encoding: utf-8
'''
@Author  : 草木零
@Software: PyCharm
@File    : yield.py
@Time    : 2023/8/23 17:28
@desc   : yield详解
1.程序开始执行以后,因为yield_demo函数终有yield关键字,
所以test函数并不会真正的执行,而是先得到一个生成器y
2.直到调用next方法,yield_demo函数正式开始执行,先执行yield_demo函数中的print方法,然后进入while循环
3.程序遇到yield关键字,然后把yield想成是return,return了一个8之后,程序停止,
并没有执行赋值给a操作,此时next(y)语句执行完成,所以输出前面两行(第一行是while上面的print的结果,第二行是return出来的结果)
4.程序执行print("**********************")
5.又开始执行下面的print(next(y)),这个时候是从刚才next程序停止的地方开始执行,
也就是要执行a的赋值操作,这个时候因为赋值操作的右边是没有值的,已经被return出去了
这个时候a的值是none,所以接下来的输出是a:none
6.程序会继续在whili里执行,又一次碰到yield,这个时候同样return出8,然后程序停止。
print函数输出的8就是这次return出的8
'''def yield_demo():print('begin================')while True:a = yield 8print('a', a)y = yield_demo() # 这句不会打印出东西,因为test函数终有yield关键字,所以yield_demo函数并不会真正的执行,而是先得到一个生成器y
print(next(y))
print('*******************************')
print(next(y))
print('*******************************')

控制器:
在这里插入图片描述

http://www.lryc.cn/news/579017.html

相关文章:

  • 文心快码答用户问|Comate AI IDE专场
  • UniApp完美对接RuoYi框架开发企业级应用
  • Droplets:趣味AI课程,开启语言学习新旅程
  • 【趣谈】Android多用户导致的UserID、UID、shareUserId、UserHandle术语混乱讨论
  • AJAX 安装使用教程
  • 从零用java实现 小红书 springboot vue uniapp (12)实现分类筛选与视频笔记功能
  • 网站面临爬虫攻击waf能防护住吗
  • mars3d (基于 Cesium 的轻量化三维地图库)
  • javaWeb02-Tomcat
  • 面试150 矩阵置0
  • SPI、I2C和UART三种串行通信协议的--------简单总结
  • 飞算 JavaAI 智控引擎:全链路开发自动化新图景
  • 分布式定时任务:xxl-job
  • 滤波电路Multisim电路仿真实验汇总——硬件工程师笔记
  • 【网工|知识升华版|实验】2 ACL原理及应用
  • 力扣 hot100 Day32
  • Spring AI 源码
  • 用自定义注解解决excel动态表头导出的问题
  • 【全网唯一】自动化编辑器 Windows版纯本地离线文字识别插件
  • 少样本学习在计算机视觉中的应用:原理、挑战与最新突破
  • 分布式事务理论基础及常见解决方案
  • 【科研绘图系列】基于R语言的种质资源评分可视化教程:条形图与地理分布图
  • Redis搭建集群模式
  • 桥岛隧大型工程 3D 可视化监测平台
  • Objective-C 路由表原理详解
  • Git 怎么判断是否冲突?
  • 开源 Python 库---Diffusers 库的安装及运用(自留)
  • Python学习之——单例模式
  • 智慧赋能高压并网:分布式光伏监控系统在5.88MW物流园项目的实践解析
  • PHP Yii2 安装SQL Server扩展-MAC M4 Pro芯片