1、fixture简绍

官方解释如下

Decorator to mark a fixture factory function.
This decorator can be used, with or without parameters, to define a fixture function.
The name of the fixture function can later be referenced to cause its invocation ahead of running tests: test modules or classes can use the pytest.mark.usefixtures(fixturename) marker.
Test functions can directly use fixture names as input arguments in which case the fixture instance returned from the fixture function will be injected.
Fixtures can provide their values to test functions using return or yield statements. When using yield the code block after the yield statement is executed as teardown code regardless of the test outcome, and must yield exactly once.

https://docs.pytest.org/en/7.1.x/reference/reference.html#pytest.fixture
fixture属于pytest中的一个方法。fixture可以用作测试用例的前置和后置操作,其中fixture命令规范没有像setup和teardown固定格式。可以随意命名。控制fixture的前置和后置操作是通过yield关键字进行来区分的,代码在yield前面的属于前置操作,代码在yield后面的属于后置操作。并且fixture也没有强烈的要求必须要前后置同时存在,可以只存在前置也可以只存在后置。
fixture如果有后置内容,无论遇到什么问题,都会进行执行后置的代码。

2、fixture基本用法

import pytest# 定义的夹具函数,使用装饰器pytest.fixture
@pytest.fixture
def login():print("login:用户执行登录操作")# 使用夹具函数的测试用例
def test_01(login):print("test_01")# 使用夹具函数的测试用例
def test_02(login):print("test_02")# 不使用夹具函数的测试用例
def test_03():print("test_03")if __name__ == '__main__':pytest.main(['MyPytest.py', '-s'])

执行结果:

collected 3 itemsMyPytest.py login:用户执行登录操作
test_01
.login:用户执行登录操作
test_02
.test_03
.
============================== 3 passed in 0.07s ==============================

fixture通过@pytest.fixture()装饰器装饰login()函数,那么这个函数就是一个fixture。
上述代码中,声明的测试夹具函数login,作为参数传入其他函数(不需要带括号哦),即可完成调用。可以传多个fixture,按先后顺序执行。

3、调用fixture的方式

a、Fixture名字作为测试用例的参数

即上述案例中的调用方式,将定义的fixture作为测试用例的参数传递进去:

import pytest# 定义的夹具函数,使用装饰器pytest.fixture
@pytest.fixture
def login():print("login:用户执行登录操作")# 使用夹具函数的测试用例
def test_01(login):print("test_01")if __name__ == '__main__':pytest.main(['MyPytest.py', '-s'])

b、使用@pytest.mark.usefixtures(‘fixture’)装饰器

使用@pytest.mark.usefixtures('fixture')的方式调用,效果同上:

import pytest# 定义的夹具函数,使用装饰器pytest.fixture
@pytest.fixture
def login():print("login:用户执行登录操作")# 使用夹具函数的测试用例
@pytest.mark.usefixtures('login')
def test_01():print("test_01")if __name__ == '__main__':pytest.main(['MyPytest.py', '-s'])

c、使用autouse参数

@pytest.fixture()的参数中的字段autouse = True的情况下,默认会在模块内的每条用例调用时候自动用到:

import pytest# 定义的夹具函数,使用装饰器pytest.fixture
@pytest.fixture(autouse=True)
def login():print("login:用户执行登录操作")# 自动使用夹具函数的测试用例
def test_01():print("test_01")if __name__ == '__main__':pytest.main(['MyPytest.py', '-s'])

4、fixture函数参数

![image.png](https://img-blog.csdnimg.cn/img_convert/bd9f4733e197a0674d82010189f1e792.png#clientId=u72bc370c-d735-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=412&id=u77733fa1&margin=[object Object]&name=image.png&originHeight=497&originWidth=944&originalType=binary&ratio=1&rotation=0&showTitle=false&size=77248&status=done&style=none&taskId=u5c1cbd35-b30f-421a-9e87-3efdc20372b&title=&width=782)

@pytest.fixture(scope = “function”,params=None,autouse=False,ids=None,name=None)

scope

控制fixture的作用范围,也就是哪些用例需要调用这个fixture。有点类似之前讲过的setup_module 、setup_class等等。

取值 作用
function 函数级 每一个函数或方法都会调用
class 函数级 模块级 每一个.py文件调用一次
module 模块级 每一个.py文件调用一次
session 会话级 每次会话只需要运行一次,会话内所有方法及类,模块都共享这个方法

session的讲解,我后面在conftest.py的用法时候讲解。
举个例子说明:

import pytest# 定义的夹具函数,使用装饰器pytest.fixture
@pytest.fixture(scope="class")
def login():print("login:用户执行登录操作")# 当fixtrue的scope="class",则只在该类中执行一次
class Test_Fixture():def test_02(self, login):print("test_02")def test_03(self, login):print("test_03")if __name__ == '__main__':pytest.main(['MyPytest.py', '-s'])
collected 2 itemsMyPytest.py login:用户执行登录操作
test_02
.test_03
.============================== 2 passed in 0.07s ==============================***Repl Closed***

params

Fixture的可选形参列表,支持列表传入,默认None,每个param的值,fixture都会去调用执行一次,类似for循环,可与参数ids一起使用,作为每个参数的标识,详见ids。被Fixture装饰的函数要调用是采用:request.param(固定写法)

import pytest# 定义的夹具函数,使用装饰器pytest.fixture
@pytest.fixture(params=["胡八万","胡三条","胡七筒"])
def login(request):temp = request.paramprint(f"login:用户{temp}执行登录操作")return temp#当fixture 的params参数 会被循环执行
def test_01(login):print(f"{login}已经登录成功~")if __name__ == '__main__':pytest.main(['MyPytest.py', '-s'])
collected 3 itemsMyPytest.py login:用户胡八万执行登录操作
胡八万已经登录成功~
.login:用户胡三条执行登录操作
胡三条已经登录成功~
.login:用户胡七筒执行登录操作
胡七筒已经登录成功~
.============================== 3 passed in 0.07s ==============================***Repl Closed***

ids

用例标识ID,与params配合使用,一对一关系

import pytest# 定义的夹具函数,使用装饰器pytest.fixture
@pytest.fixture(params=["胡八万", "胡三条", "胡七筒"],ids=['用例A','用例B','用例C'])
def login(request):temp = request.paramprint(f"login:用户{temp}执行登录操作")return temp# 当fixture 的params参数 会被循环执行
def test_01(login):print(f"{login}已经登录成功~")if __name__ == '__main__':pytest.main(['MyPytest.py', '-s'])

有的编辑器执行无效果,但是使用pycharm等就可以看出用例的编号

autouse

默认False,若为True,刚每个测试函数都会自动调用该fixture,无需传入fixture函数名。参考之前的代码案例。

import pytest# 定义的夹具函数,使用装饰器pytest.fixture
@pytest.fixture(autouse=True)
def login():print("login:用户执行登录操作")# 自动使用夹具函数的测试用例
def test_01():print("test_01")if __name__ == '__main__':pytest.main(['MyPytest.py', '-s'])

name

fixture的重命名。重新把他命名一下,之前的函数名将不生效

import pytest# 定义的夹具函数,使用装饰器pytest.fixture
@pytest.fixture(name='new_login')
def login(request):print(f"login:用户执行登录操作")def test_01(new_login):print("test_01已经登录成功~")def test_02(login):print("test_02已经登录成功~")if __name__ == '__main__':pytest.main(['MyPytest.py', '-s'])

执行上述代码将报错,提示fixture 'login' not found

5、fixture对比setup、teardown

  • 全局共享conftest.py,可以统一管理、多处调用和自动调用
  • 命名方式灵活,不局限于setup和teardown这个几个命名
  • fixture出现重名,就近原则
  • conftest.py为fixture而生的,可以方便管理、修改和查看fixture函数
  • 自动引入不需要导入

6、fixture配合yield 实现teardown

关于yield可以看我之前写的一篇专门介绍它基本用法的文章。这里不再赘述
yeild也是一种函数的返回值类型,是函数上下文管理器,使用yield被调fixture函数执行遇到yield会停止执行,接着执行调用的函数,调用的函数执行完后会继续执行fixture函数yield关键后面的代码。因此利用fixture函数,我们可以说pytest集合了setup、teardown,既做了初始化,又做了后置的清理工作。

import pytest# 定义的夹具函数,使用装饰器pytest.fixture
@pytest.fixture()
def login(request):print("login:用户执行登录操作")yieldprint("退出登录~")def test_01(login):print("test_01已经登录成功~")def test_02(login):print("test_02已经登录成功~")if __name__ == '__main__':pytest.main(['MyPytest.py', '-s'])

执行结果:

collected 2 itemsMyPytest.py login:用户执行登录操作
test_01已经登录成功~
.退出登录~
login:用户执行登录操作
test_02已经登录成功~
.退出登录~============================== 2 passed in 0.07s ==============================***Repl Closed***

7、addfinalizer 终结函数

addfinalizer,终结函数。效果上是大致相同的,但是在用法上,addfinalizer跟yield是不同的,需要注册作为终结器使用的函数。

import pytest# 定义的夹具函数,使用装饰器pytest.fixture
@pytest.fixture()
def login(request):print("login:用户执行登录操作")def logout():print("退出登录~")# 注册logout为终结函数request.addfinalizer(logout)def test_01(login):print("test_01已经登录成功~")def test_02(login):print("test_02已经登录成功~")if __name__ == '__main__':pytest.main(['MyPytest.py', '-s'])

执行结果:

collected 2 itemsMyPytest.py login:用户执行登录操作
test_01已经登录成功~
.退出登录~
login:用户执行登录操作
test_02已经登录成功~
.退出登录~============================== 2 passed in 0.07s ==============================***Repl Closed***

addfinalizer可以定义多个终结函数,但是执行顺序是定义时候顺序的倒叙:

import pytest# 定义的夹具函数,使用装饰器pytest.fixture
@pytest.fixture()
def login(request):print("login:用户执行登录操作")def logout01():print("退出登录01~")def logout02():print("退出登录02~")def logout03():print("退出登录03~")# 注册logout为终结函数request.addfinalizer(logout01)request.addfinalizer(logout02)request.addfinalizer(logout03)def test_01(login):print("test_01已经登录成功~")def test_02(login):print("test_02已经登录成功~")if __name__ == '__main__':pytest.main(['MyPytest.py', '-s'])

运行结果:

collected 2 itemsMyPytest.py login:用户执行登录操作
test_01已经登录成功~
.退出登录03~
退出登录02~
退出登录01~
login:用户执行登录操作
test_02已经登录成功~
.退出登录03~
退出登录02~
退出登录01~============================== 2 passed in 0.07s ==============================***Repl Closed***

好了,今天的内容比较多,因为pytest的精髓也在fixture。所以希望本文的案例大家跟着大家敲一遍,纸上得来终觉浅~

对你有用的话点个赞吧!

pytest系列教程——4、fixture详解相关推荐

  1. h2 不能访问localhost_SpringBoot2.x系列教程44--H2数据库详解及搭建Web控制台

    SpringBoot2.x系列教程44--H2数据库详解及搭建Web控制台 作者:一一哥 我在上一章节中讲解了Spring Boot中整合Mybatis,接下来我给大家介绍一款内存数据库--H2. H ...

  2. Redis系列教程(二):详解Redis的存储类型、集群架构、以及应用场景

    高并发架构系列 高并发架构系列:数据库主从同步的3种一致性方案实现,及优劣比较 高并发架构系列:Spring Cloud的核心成员.以及架构实现详细介绍 高并发架构系列:服务注册与发现的实现原理.及实 ...

  3. Cobaltstrike系列教程(三)beacon详解

    0x000–前文 有技术交流或渗透测试培训需求的朋友欢迎联系QQ/VX-547006660 2000人网络安全交流群,欢迎大佬们来玩 群号820783253 0x001-Beacon详解 1.Beac ...

  4. 一步一步使用ABP框架搭建正式项目系列教程之本地化详解

    返回总目录<一步一步使用ABP框架搭建正式项目系列教程> 本篇目录 扯扯本地化 ABP中的本地化 小结 扯扯本地化 本节来说说本地化,也有叫国际化.全球化的,不管怎么个叫法,反正道理都是一 ...

  5. python fixture_python pytest进阶之xunit fixture详解

    前言 今天我们再说一下pytest框架和unittest框架相同的fixture的使用, 了解unittest的同学应该知道我们在初始化环境和销毁工作时,unittest使用的是setUp,tearD ...

  6. junit5 入门系列教程-02-junit5 注解详解

    目录 目录 Junit5 注解 @Test @ParameterizedTest @RepeatedTest @TestFactory @TestInstance @TestTemplate @Dis ...

  7. 『SQLServer系列教程』——事务详解

  8. RxJS 系列之二 - Observable 详解

    查看新版教程,请访问前端修仙之路 RxJS 系列目录 RxJS 系列之一 - Functional Programming 简介 RxJS 系列之二 - Observable 详解 (本文) RxJS ...

  9. jquery系列教程3-DOM操作全解

    全栈工程师开发手册 (作者:栾鹏) 快捷链接: jquery系列教程1-选择器全解 jquery系列教程2-style样式操作全解 jquery系列教程3-DOM操作全解 jquery系列教程4-事件 ...

  10. python语言入门详解-python初级教程:入门详解

    python初级教程:入门详解 Crifan Li 目录 前言 .................................................................... ...

最新文章

  1. hibernate 和 mybatis 的区别
  2. 解决vue移动端适配问题
  3. asp服务器推送消息,asp.net实时向客户端推送消息(SignalRWeb)
  4. 在C盘和D盘执行php 结果不同,window_双系统电脑给C盘扩容后导致D盘Win10引导项丢失该怎么办?,为了写个经验,特意把C盘用无 - phpStudy...
  5. C:\Users\22981\Desktop (拒绝访问。)
  6. 数据库系列之mysql 自定义函数function,函数和存储过程的区别
  7. 【转】为什么螺丝都是六角的?
  8. surface pro 5 加AD域后,人脸识别选项是灰色按钮,无法使用
  9. c++ 写x64汇编 5参数_自己动手写操作系统 8086sos
  10. EditPlus 3编译运行设置
  11. android fragment 设置透明,DialogFragment背景透明设置
  12. CSS基础教程 -- 媒体查询屏幕适配
  13. 2011-11-27神马浮云的一天
  14. Qt自定义进度条示例
  15. python实现决策树 西瓜书_朴素贝叶斯python代码实现(西瓜书)
  16. Cutting Bamboos【主席树+二分】
  17. [人脸活体检测] 论文: Learning Deep Models for Face Anti-Spoofing: Binary or Auxiliary Supervision
  18. js统计字符串中大写字母与小写字母的总个数
  19. iPhone/iPad应用使用麦克风的开启和关闭
  20. 前端应届生如何做一个职业规划?已拿offer附真题解析

热门文章

  1. 为什么我们要用密码生成器?
  2. 双指缩放canvas图片_JS实现移动端双指缩放和旋转方法
  3. FFmpeg获取视频正确的宽高比
  4. PHP中的日期相减函数,在php中有没有日期相减的函数
  5. 8年Android开发教你如何写简历,详细的Android学习指南
  6. Chrome:下载Chrome网上应用店扩展程序crx
  7. 计算机桌面运维问题分类,桌面运维工程师常见面试问题汇总
  8. echarts横向柱状图
  9. Taxi Cab Scheme 【HDU - 1350】【匈牙利算法解决最小链覆盖】
  10. 界面原形设计/UI原型设计