Pytest框架中fixture功能详解

news2024/11/24 22:36:22

文章目录

1 定义 Fixture函数

2 Fixture 的函数参数

2.1 传入其他fixture函数作为参数

2.2 传入request对象参数

示例1:访问fixture的调用者

示例2:使用fixture的参数

3 Fixture 的作用域参数scope

3.1 scope=class场景

3.2 scope=session场景

4 Fixture 的自动使用参数autouse=True

5 Fixture 的参数化params和ids

6 fixture函数传入的request到底是啥?

pytest 的 fixture 是一个非常强大的功能,它允许你在测试函数或测试类之间共享设置和清理代码。fixture可以被看作是测试中的“依赖注入”机制,它允许你以函数的形式定义这些依赖,并在需要时将其注入到测试函数中。

pytest官方文档是这样解释的:
https://docs.pytest.org/en/latest/how-to/fixtures.html#how-to-fixtures

由于英语不好,只能百度翻译如下:

在测试中,fixtures(夹具)为测试提供了一个定义明确、可靠且一致的上下文。这个上下文可以包括环境(例如配置有已知参数的数据库)或内容(如数据集)。

Fixtures 定义了测试的 "arrange"(安排)阶段所需的步骤和数据。在 pytest 中,fixtures 是你定义的函数,用于这个目的。它们也可以用于定义测试的 "act"(行动)阶段,这是设计更复杂测试的一个强大技巧。

由 fixtures 设置的服务、状态或其他操作环境通过参数被测试函数访问。对于测试函数使用的每个 fixture,通常在测试函数的定义中有一个以 fixture 命名的参数。

我们可以通过 @pytest.fixture 装饰器来告诉 pytest 某个函数是一个 fixture。

我们举个简单的例子理解下:

定义一个用 @pytest.fixture 装饰的函数fixture_steup_exec,

并将函数fixture_steup_exec作为参数传入测试用例test_1中。

@pytest.fixture
def fixture_steup_exec():
  print('\n执行测试用例前,先执行我这个fixture函数')

def test_1(fixture_steup_exec):
  assert 1==1
  print('\n用例test_1执行成功'

当我们执行测试用例test_1时,程序发现参数fixture_steup_exec正是被 @pytest.fixture装饰的函数,那么先执行被装饰函数中的代码,然后才执行测试用例的代码。

test_1的执行结果如下:

1 定义 Fixture

使用 @pytest.fixture 装饰器来定义一个 fixture。

主要有几个参数fixture_function,scope,params,autouse,ids等,下面几个章节会详细介绍。

被@pytest.fixture 装饰的函数会在测试函数或测试方法之前运行,并返回一个值,该值可以作为参数传递给测试函数或测试方法。

举例:定义my_fixture函数返回data,将该函数传入测试用例test_example。

@pytest.fixture
def my_fixture():
  #这里是设置代码 
  data = "Hello, pytest!"
  return data
def test_example(my_fixture):
  assert my_fixture=="Hello, pytest!"
  print(f"\nmy_fixture 返回的值: {my_fixture}")

用例执行结果:

2 Fixture 的fixture_function参数

1)Fixture 函数可以接受其他 fixture 作为参数。换句话说定义的fixture 可以依赖于其他 fixture 来执行设置和清理工作。

2)Fixture 函数还可以接受 request 对象作为参数,这个对象提供了关于当前请求的额外信息,如 fixture 的名称、参数等。

2.1 传入其他fixture函数作为参数

一个 fixture 可以依赖于另一个 fixture,只需将依赖的 fixture 作为参数传递给 fixture 函数即可。

举例:定义fixture_a,同时定义fixture_b,参数传入fixture_a。

@pytest.fixture
def fixture_a():
  return "a"

@pytest.fixture
def fixture_b(fixture_a): # 依赖于 fixture_a
  return fixture_a + "b"

def test_both_fixtures(fixture_b):
  assert fixture_b == "ab"
  print('\n调用了fixture_b 和 fixture_a')

将fixture_b作为参数传入测试用例test_both_fixtures,执行成功。

2.2 传入request对象参数

request是pytest中fixture函数的一个特殊参数,它提供了许多有关当前测试请求的信息。request对象主要有以下功能:

1)访问fixture的调用者:我们可以知道是哪个测试或fixture调用了当前的fixture。

2)获取fixture的参数:如果fixture有参数可以使用request.param来访问这些参数。

3)访问fixture的上下文:request对象还提供了许多其他方法和属性,允许你更深入地了解当前测试请求的上下文。

以下是一些使用request的示例:

示例1:访问fixture的调用者

通过在fixture函数传入request,通过request.node.name获取测试用例名称。

@pytest.fixture
def my_parametrized_fixture(request):
  print(f'是那个测试用例调用了我: {request.node.name}')

def test_case1(my_parametrized_fixture):
  print(f"Running testcase1")

示例2:使用fixture的参数

举例:传入两个参数value1和value2,并打印下测试用例获取的fixture的参数值。

@pytest.fixture(params=["value1", "value2"])
def example_fixture(request):
  return request.param

def test_example(example_fixture):
  print(f"Using value: {example_fixture}")

用例执行结果:

3 Fixture 的作用域参数scope

默认情况下,fixture 的作用域是函数级,可通过 scope 参数来改变 fixture 的作用域。可用的作用域有:["session", "package", "module", "class", "function"]

scope 参数解释:

  • function(默认)

每个测试函数都会执行一次 fixture。

适用于每个测试用例都需要独立设置和清理资源的场景。

  • class

每个测试类都会执行一次 fixture。

在类中定义的第一个测试方法执行前执行 fixture,在类中的所有测试方法执行后执行 teardown(如果使用了 yield)。

适用于类中的多个测试方法共享相同设置和清理资源的场景。

  • module

一个 Python 模块(一个 .py 文件)只会执行一次 fixture。

在模块中的第一个测试函数或方法执行前执行 fixture,在模块中的所有测试函数或方法执行后执行 teardown(如果使用了 yield)。

适用于整个模块内的多个测试函数或方法共享相同设置和清理资源的场景。

  • session

整个测试会话期间只执行一次 fixture。

在 pytest 会话开始时执行 fixture,在所有测试文件执行完毕后执行 teardown(如果使用了 yield)。

适用于整个测试套件需要共享的设置和清理资源的场景,如数据库连接、浏览器驱动等。

当 fixture 设置为 autouse=True 时,结合 scope 参数,fixture 将在指定的作用域内自动生效,无需在每个测试函数或类中显式引用。

3.1 scope=class场景

举例:在测试类执行前执行setup和teardown的动作。

定义一个fixture函数,在该函数使用 @pytest.fixture(scope='class') 装饰器(应用于类时scope参数定义为class),并使用yield关键字,yield上面的代码在类中第一个测试用例执行前执行,yield下面的代码在类中最后一条用例执行后执行。我们将这个fixture 作为类中测试方法的参数,以此来实现类中的setup和teardown功能。

@pytest.fixture(scope='class')
def class_setup_teardown():
  print("\nClass setup (equal to setup_class)")
  # 设置代码
  yield
  print("\nClass teardown (equal to teardown_class)")
  # 清理代码
第一种方式:在测试函数中传入定义的fixture函数作为参数
class Testcase:
  def test_one(self, class_setup_teardown): # 直接将fixture作为参数
    print("\nRunning test_one")
    # 测试代码
  def test_two(self, class_setup_teardown): # 同样地,直接作为参数
    print("\nRunning test_two")
    # 测试代码
  • 第二种方式:在测试类中注明使用fixture,测试函数中不传参数
@pytest.mark.usefixtures("class_setup_teardown")
class Testcase: 
  def test_one(self): 
    print("\nRunning test_one")
    # 测试代码
  def test_two(self):
    print("\nRunning test_two")
    # 测试代码

用例执行后结果如下:两种方式都实现了测试类setup和teardown的功能

3.2 scope=session场景

由于 session 级别的 fixture 在整个测试会话中只执行一次,因此它可以跨多个测试文件共享资源(而module级别的只能在单个py文件内适用)。

举例:我们有一个需要连接数据库的 fixture,并且这个连接在整个测试会话期间只需要建立一次。

@pytest.fixture(scope='session')
def db_connection_fixture():
  # 这里是建立数据库连接的代码
  print("Connecting to database...")
  yield # 暂停点,测试函数开始执行
  # 这里是关闭数据库连接的代码
  print("Closing database connection...")
  # 之后的测试函数或类将自动使用这个 fixture,无需显式引用

  def test_database_operation(db_connection_fixture):
    # 在这里执行数据库操作,db_connection fixture 已经在会话开始时自动建立连接
    pass

由于 scope="session" ,db_connection fixture 将在整个测试会话开始时自动建立数据库连接,并在所有测试执行完毕后自动关闭连接。

4 Fixture 的自动使用参数autouse=True

autouse=True 参数使 fixture 在所有测试函数或测试类中自动使用,而无需将其作为参数传递。但这可能会导致代码更难理解和维护。

举例:上面我们创建的scope=class的fixture函数,如果加上参数autouse=True,则不需要在测试类中在使用这个fixture函数。

@pytest.fixture(scope='session', autouse=True)
def class_setup_teardown():
  print("\nClass setup (equal to setup_class)")
  # 设置代码
  yield
  print("\nClass teardown (equal to teardown_class)")
  # 清理代码

#@pytest.mark.usefixtures("class_setup_teardown")
#完全可以注释该fixture函数的使用
class Testcase2:
  def test_one(self):
    print("\nRunning test_one")
    # 测试代码
  def test_two(self):
    print("\nRunning test_two")
    # 测试代码

5 Fixture 的参数化params和ids

允许为fixture指定多个参数值,并为每个参数值运行测试函数。通常params与ids参数结合使用,ids为参数化值提供别名,在后续测试报告中更容易识别每个参数化测试。

举例:给fixture传入三个参数和它们的ids,执行测试用例后,其实会执行3个用例。

@pytest.fixture(params=[1, 2, 3],ids=['id1','id2','id3'])
def my_parametrized_fixture(request):
  return request.param

def test_parametrized_fixture(my_parametrized_fixture):
  print(f"Running test with {my_parametrized_fixture}")

执行后结果如下:

6 fixture函数传入的request到底是啥?

request 参数,对应访问的是特殊的 FixtureRequest 对象,它提供了关于当前请求的上下文信息。

以下是位于pytest.fixture文件中的FixtureRequest 类:

在初始化函数中添加了一行打印,如上图所示。

FixtureRequest 对象包含以下一些有用的属性和方法:

属性

1)fixturename: 当前 fixture 的名称。

2)param: 如果 fixture 被参数化,则这是当前参数的值。

3)scope: fixture 的作用域(例如 "function", "class", "module", "session")。

4) config: pytest 的配置对象。

5) session: pytest 的 session 对象。

6)node: 收集到的节点(通常是测试用例或类)。

7)function: 如果 fixture 被一个测试函数调用,则这是该函数。

8)cls: 如果 fixture 被一个测试类使用,则这是该类。

9)instance: 如果 fixture 被一个测试类的实例方法使用,则这是该实例。

10)module: 如果 fixture 被一个模块中的测试使用,则这是该模块。

11)fspath: 调用 fixture 的文件路径。

方法

1)addfinalizer(finalizer): 添加一个将在测试结束后调用的 finalizer 函数。这可以用于执行清理操作。

2)getfixturevalue(argname): 请求另一个 fixture 的值。

3)getparam(name, default): 检索参数的当前值,如果该参数未定义则返回默认值。

举例:在测试用例中打印下部分request的属性:

@pytest.fixture(params=["value1", "value2"])
def example_fixture(request):
  return request

def test_example(example_fixture):
  print(f"\nrequest.fspath : {example_fixture.fspath}")
  print(f"\nrequest.node : {example_fixture.node}")
  print(f"\nrequest.scope : {example_fixture.scope}")
  print(f"\nrequest.fixturename : {example_fixture.fixturename}")
  print(f"\nrequest.module : {example_fixture.module}")
  print(f"\nrequest.config : {example_fixture.config}")

用例执行后结果:打印了上面自己添加的一行记录,说明调用了FixtureRequest 。

共勉: 东汉·班固《汉书·枚乘传》:“泰山之管穿石,单极之绠断干。水非石之钻,索非木之锯,渐靡使之然也。”

-----指水滴不断地滴,可以滴穿石头;

-----比喻坚持不懈,集细微的力量也能成就难能的功劳。

----感谢读者的阅读和学习,点个赞和关注吧,谢谢大家。

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

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

相关文章

ImageNet-1k 测试集 两大坑

1、官方网站提交test set标签时,千万不能提交zip文件,即便明文说可以 https://image-net.org/challenges/LSVRC/eval_server.php 不然就会浪费一次提交机会,直接提交submission.txt就可以,注意每排5个预测结果,用于计…

Excel报表

(Apache POI) 入门案例 P164 使用POI需要导入下面2个坐标&#xff1a; <dependency><groupId>org.apache.poi</groupId><artifactId>poi</artifactId> </dependency> <dependency><groupId>org.apache.poi</groupId>&…

[个人感悟] 缓存应该考察哪些问题?

前言 缓存, 根据冯诺依曼计算机模型, 无非是为了更高效的交互, 使用内存IO替换本地磁盘IO. 又因为内存的稀缺性, 其必然存储的是热点数据, 且较小的数据. [虽然直至今日, 已有使用缓存作为数据库的使用, 但是与磁盘IO相比, 其价格仍是数倍之多.] 当涉及缓存问题时, 又分为本地…

springboot+vue+mybatis教师工作审核系统+PPT+论文+讲解+售后

随着社会不断进步与发展&#xff0c;生活节奏不断加快&#xff0c;信息已经成为我们生活中不可缺少的一部分&#xff0c;很多学校需要掌握大量的信息来了解特定学生的需求&#xff0c;传统的做法是组织大量的人力物力对学生散发调查表&#xff0c;然后对收集的信息进行统计并得…

【SOEM主站】EtherCAT主站时钟偏移补偿

在进行EtherCAT主从通讯测试时&#xff0c;比较容易在DC配置出现错误&#xff0c;特别是使用到从站DC模式时&#xff0c;有时会报同步错误&#xff0c;有时即使没报错误伺服从站运行过程中也会出现电机轴的抖动。引起同步错误其中一个原因就是主站发送数据帧时间存在较大的抖动…

一文带你精通Android中的Activity

本文将会从活动的生命周期、启动模式、Intent数据传输、最佳实践等多维度来讲解Activity&#xff0c;希望对你有用 生命周期 深入理解活动的生命周期&#xff0c;可以帮助我们更加流畅地编程&#xff0c;并在管理系统资源方面更加游刃有余 活动状态 每个活动在生命周期中最…

《Windows API每日一练》4.4 绘制填充区域

本节讲述如何填充由线条构建的封闭区域。当我们初始化一个窗口类时&#xff0c;往往已经指定了窗口的背景色画刷&#xff08;WHITE_BRUSH&#xff09;&#xff0c;即默认的填充封闭区域背景的画刷。如果我们想更换背景颜色&#xff0c;需要选入其他系统预定义的画刷&#xff08…

助力樱桃智能自动化采摘,基于YOLOv5全系列【n/s/m/l/x】参数模型开发构建果园种植采摘场景下樱桃成熟度智能检测识别系统

随着科技的飞速发展&#xff0c;人工智能&#xff08;AI&#xff09;技术已经渗透到我们生活的方方面面&#xff0c;从智能家居到自动驾驶&#xff0c;再到医疗健康&#xff0c;其影响力无处不在。然而&#xff0c;当我们把目光转向中国的农业领域时&#xff0c;一个令人惊讶的…

几何公差的设计和选用

保证轴承的旋转精度&#xff0c;提出圆柱度&#xff1b; 这里的轴肩部面 为了测量方便&#xff0c;使用圆跳动代替垂直度公差方便一些。

胡说八道(24.6.15)——数字电子技术及Multisim仿真

上回书说到数电中的两种基本存储电路——锁存器和触发器以及时序逻辑电路的设计和分析。今天来看看触发器的几个应用&#xff0c;主要实践实践&#xff0c;不能只说概念。 首先&#xff0c;首当其冲的就是计数器&#xff0c;如果大家看过我之前记的笔记的话&#xff0c;应该不会…

vue3轮播图怎么做

先看效果 实现代码 <n-carouseleffect"card"dot-type"line"draggable:autoplay"!isHovered":current-index"currentIndex"prev-slide-style"transform: translateX(-150%) translateZ(-450px);opacity:1"next-slide-st…

SE语法总结博文(附思维导图)

Java中的规范 注释 //单行注释 /*多行注释 */ /**文档注释 */命名规范 命名时可以包含&#xff1a;字母、数字以及 下划线和 $ 符号等等。 但是不能以数字开头&#xff0c;也不能是关键字&#xff0c;且严格区分大小写。 类名&#xff1a;每个单词的首字母大写(大驼峰)&…

springboot优雅shutdown时异步线程安全优化

前面针对graceful shutdown写了两篇文章 第一篇&#xff1a; https://blog.csdn.net/chenshm/article/details/139640775 只考虑了阻塞线程&#xff0c;没有考虑异步线程 第二篇&#xff1a; https://blog.csdn.net/chenshm/article/details/139702105 第二篇考虑了多线程的安全…

Rewrite the Stars

文章目录 摘要1、引言2、相关工作3、重写星操作3.1、单层中的星操作3.2、扩展到多层3.3、特殊情况3.4、实证研究3.4.1、星操作的实证优越性3.4.2、决策边界对比3.4.3、扩展到无激活函数的网络 3.5、开放讨论与更广泛的影响 4、概念验证&#xff1a;StarNet4.1、StarNet架构4.2、…

HDU - 5651 xiaoxin juju needs help(Java JS Python C C++)

题目来源 Problem - 5651 (hdu.edu.cn) 题目描述 众所周知&#xff0c;小新是一位才华横溢的程序员。当他还是小学六年级的学生时&#xff0c;他就知道回文字符串了。 今年夏天&#xff0c;他在腾讯实习。一天&#xff0c;他的领导来找小新帮忙。他的领导给了他一个字符串&a…

LabVIEW程序的常见加密方式

LabVIEW程序的加密对于保护知识产权和敏感数据至关重要。本文将详细介绍LabVIEW程序常用的加密方式&#xff0c;包括VI加密、代码保护、文件加密和通信加密等&#xff0c;帮助开发者选择合适的加密方法来确保程序的安全性和完整性。 LabVIEW程序的常见加密方式 VI加密&#xf…

Fiddler抓包工具介绍

下载 下载:Web Debugging Proxy and Troubleshooting Tools|Fiddler 进去要填一个表 汉化版 百度网盘 请输入提取码 提取码&#xff1a;xq9t 下载过附件之后分别把两个文件 点开fiddler就ok了 配置https fiddler要想抓到https包(解密的),点击tools->options勾选三个对…

做好程序前设计

不要小看任何一道编程题目&#xff01;一定一定一定要想好之后再动手&#xff01;&#xff01;&#xff01; 带上你的草稿本&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xf…

DP:01背包问题

一、背包问题的概述 背包问题是⼀种组合优化的NP完全问题。 本质上是为了找出“带有限制条件的组合最优解” 1、根据物品的个数&#xff0c;分为如下几类&#xff1a; • 01背包问题&#xff1a;每个物品只有⼀个&#xff08;重点掌握&#xff09;• 完全背包问题&#xff1…

牛客热题:最长上升子序列(一)

&#x1f4df;作者主页&#xff1a;慢热的陕西人 &#x1f334;专栏链接&#xff1a;力扣刷题日记 &#x1f4e3;欢迎各位大佬&#x1f44d;点赞&#x1f525;关注&#x1f693;收藏&#xff0c;&#x1f349;留言 文章目录 牛客热题&#xff1a;最长上升子序列(一)题目链接方法…