首页 > 其他分享 >Pytest框架中fixture功能详解

Pytest框架中fixture功能详解

时间:2024-06-16 16:28:01浏览次数:12  
标签:fixture pytest print Pytest 参数 def test 详解

文章目录

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 。

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

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

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

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

标签:fixture,pytest,print,Pytest,参数,def,test,详解
From: https://blog.csdn.net/kymppcds/article/details/139721854

相关文章

  • Redis分布式锁详解及电商秒杀功能示例
    Redis分布式锁是一种在分布式系统中,利用Redis的原子操作特性实现的锁机制,用于保护共享资源的并发访问。原理原子性与互斥性Redis分布式锁的核心原理在于利用Redis的某些原子操作(如`SETNX`、`GETSET`、`SET`带特定选项等)来确保锁的获取与释放操作是原子性的,从而保证了锁的......
  • Unreal RecastNavigation 开源项目详解
    0前言Recastnavigation是一个游戏AI导航库,像Unity,UE引擎中都集成了这个开源项目,HALO中使用的也是这个开源库。导航最重要的就是为NPC寻路,以及其他的寻路需求。需要注明的是,这个寻路库虽然厉害。但是他的核心是平面寻路。也就是重力方向一直朝着-Y方向。如果是星球地形,既重......
  • PHP框架详解 - Symfony框架
    PHP框架详解-Symfony框架引言在当今快速发展的Web开发领域,PHP作为一种流行的服务器端脚本语言,一直以其简洁性和高效性受到开发者的青睐。随着Web应用的复杂性不断增加,PHP框架应运而生,为开发者提供了一套更加结构化和模块化的开发方式。在众多PHP框架中,Symfony以其强大的......
  • 【Linux】fork()函数详解|多进程
    ......
  • Redisson详解
    目录第1章:Redisson简介第2章:Redisson的架构与原理第3章:Redisson的基本使用连接Redis基本操作高级数据结构操作分布式锁的使用第4章:Redisson的高级特性分布式数据结构发布/订阅模型延迟队列与阻塞队列第5章:Redisson的分布式服务分布式锁的实现与应用分布式集合......
  • 【DevOps】Logstash详解:高效日志管理与分析工具
    在现代软件开发和运维过程中,日志管理与分析是至关重要的环节。日志可以帮助我们追踪系统行为、诊断问题、优化性能以及确保安全合规。Logstash,作为ELKStack(Elasticsearch、Logstash、Kibana)的核心组件之一,是一个功能强大、灵活易用的日志收集、处理和转发工具。本文将详细介绍......
  • Python自动化测试框架-pytest
    源码:https://github.com/pytest-dev/pytest文档:https://docs.pytest.org/en/8.2.x/安装:pipinstallpytest简单样例#contentoftest_sample.pydefinc(x):returnx+1deftest_answer():assertinc(3)==5命令行执行python可以看到执行结果命名规范......
  • 机器视觉入门学习:YOLOV5自定义数据集部署、网络详解、损失函数(学习笔记)
     前言源码学习资源:YOLOV5预处理和后处理,源码详细分析-CSDN博客网络学习资源:YOLOv5网络详解_yolov5网络结构详解-CSDN博客YOLOv5-v6.0学习笔记_yolov5的置信度损失公式-CSDN博客 本文为个人学习,整合各路大佬的资料进行V5-6.0版本的网络分析,在开始学习之前最好先去学习YOL......
  • 数组(举例详解)
    1.一维数组的创建和初始化有了变量就可以存放数值了存放几个数值可以但是存放一百个呢?这时候就出现了数组1.1数组的创建数组是一组相同类型元素的集合。数组的创建方式:type_t   arr_name   [const_n]type_t  是指数组的元素类型arr_name  是指......
  • goaccess分析nginx日志详解
    goaccess version:1.9安装方式:源文件makemakeinstall 执行环境:cli完整access.log:192.168.1.3:16423|240e:42c:1b30:111:b4c1:49ff:fe49:392c,113.96.59.2114/Jun/2024:00:01:15+0800HTTP/1.0GEThttp://www.baidu.com/yl/ysj/dsj/folder1088/?imageView/......