Pytest——Fixture夹具的使用

一、什么是Fixture

在测试开展的过程中,会需要考虑到测试前的准备工作,以及测试后的释放操作行为。这些在Pytest中,会通过Fixture的方式来实现。如果说在运行pytest的测试用例的时候,需要调用一些数据来实现测试行为,这些数据可以通过Fixture来生成。Fixture也叫夹具


二、Fixture的基本应用 

2.1单个Fixture的使用

1. Fixture在pytest之中都是基于装饰器的形态来实现的。@pytest.fixture

2. fixture是对函数进行定义的操作。使用fixture非常简单,只需要将fixture当做参数传入函数即可

3. 在pytest中,调用Fixture直接通过函数的名称即可。

4. 一个pytest中可以定义非常多个fixture,来满足到不同的用例的需要。

首先定义一个构造函数,定义一个fixture,返回human对象。调用fixture生成数据内容,可以生成一个man. 

class Human:#定义一个构造函数def __init__(self,name):self.name = name#定义一个fixture,返回一个human对象,名字叫做man
@pytest.fixture
def man():return Human('man')
#调用fixture生成的数据内容
def test_function(man):print(man.name)if __name__ == '__main__':pytest.main(['-s'])

 查看结果:

  


2.2多个Fixture的使用 

在unitTest中,一般只有一个前置条件,但是在pytest可以有多个夹具,也就是fixture

class Human:#定义一个构造函数def __init__(self,name):self.name = name#定义一个fixture,返回一个human对象,名字叫做man
@pytest.fixture
def man():return Human('man')@pytest.fixture
def woman():return Human('woman')# 定义一个调用fixture的fixture
@pytest.fixture
def people(man, woman):return [man, woman]#调用fixture生成的数据内容
def test_function_01(man):print(man.name)def test_function_02(woman):print(woman.name)

不同函数可以引用不同夹具,所以这里可以打印出man和woman的名字


2.3Fixture中引用Fixture的使用 

在pytest中甚至可以在夹具中引用夹具 ,通过一个统一的类,来管理夹具。并且来满足不同测试用例的需求。

class Human:#定义一个构造函数def __init__(self,name):self.name = name#定义类的比较规则def __eq__(self, other):return self.name == other.name#定义一个fixture,返回一个human对象,名字叫做man
@pytest.fixture
def man():return Human('man')@pytest.fixture
def woman():return Human('woman')# 定义一个调用fixture的fixture
@pytest.fixture
def people(man, woman):return [man, woman]def test_function_03(people):for p in people:print(p.name)

 依然能打印出man和woman:


 三、Fixture的运行机制

1. fixture缓存机制,在用例之中,fixture可以被多次请求,在pytest之中,fixture第一次被请求后, 如果有返回值,则后续继续调用该fixture的时候,会调用第一次生成的值,而不会再重新运行。

2. autouse可以实现让定义了autouse的fixture在每一个测试用例执行前都调用此fixture,就不需要在 每一个测试用例之中都传入该fixture作为参数,减少了不必要的操作行为

3. 报错机制:fixture本身是属于我们自定义的函数,所以在运行过程中也会存在有出现报错的风险。

在实际 运行过程中,很有可能因为关联的fixture导致了一系列不可预见的问题产生。

在pytest之中,如果说与用例相关联的fixture出现了报错,pytest会将当前用例停止执行,并标记为 错误状态。要记得,错误状态不是failed状态,所以并不能表示用例是不通过的。只能够说明是用例关联 的fixture出现了问题,用例本身没有发现任何错误。 所以要明白,在fixture的设计的时候,需要尽可能减少fixture之间的依赖关系,避免因为一个fixture 出现问题导致大批fixture失效。

 3.1Fixture缓存机制

fixture缓存机制,在用例之中,fixture可以被多次请求,在pytest之中,fixture第一次被请求后, 如果有返回值,则后续继续调用该fixture的时候,会调用第一次生成的值,而不会再重新运行。

import pytest@pytest.fixture
def first():return 'a'
@pytest.fixture
def second():return []
@pytest.fixture
def third(first,second):return second.append(first)def test_function(first,second,third):print(first)print(second)if __name__ == '__main__':pytest.main(['-s'])

这里first夹具,是返回'a'的操作,second夹具是返回空[]的操作,third夹具是将'a'放入空[]的操作。

打印first和second中按理说应该打印'a'和[],但是打印出了['a']。主要是由于test_function()测试用例

中,传入了third夹具,已经存在['a']的缓存。所以在打印second的时候,可以直接打印出['a']。


 3.2autouse参数的使用

在unitTest中,如果每个测试用例都会用到某些前置条件或者后置条件,可以通过setUp或者tearDown实现。pytest中也可以通过fixture来实现一些前置和后置条件的处理。但是在每个测试用例都传入fixture不方便,可以使用autouse来解决这个问题。

autouse可以实现让定义了autouse的fixture在每一个测试用例执行前都调用此fixture,就不需要在 每一个测试用例之中都传入该fixture作为参数,减少了不必要的操作行为


import pytest@pytest.fixture
def first():return 'a'
@pytest.fixture
def second():return []
@pytest.fixture(autouse=True)
def third(first,second):return second.append(first)def test_function(first,second):print(first)print(second)if __name__ == '__main__':pytest.main(['-s'])

在third夹具中定义了autouse参数,设置为True。在测试用例test_function中并没有调用third 夹具,理论上打印second是不会打印出['a']的。但是由于antouse,autouse的fixture在每一个测试用例执行前都调用此fixture,所以third夹具运行之后,second就变成了['a'],所以打印结果是['a']。


3.3Fixture报错机制

报错机制:fixture本身是属于我们自定义的函数,所以在运行过程中也会存在有出现报错的风险。在实际 运行过程中,很有可能因为关联的fixture导致了一系列不可预见的问题产生。 

 在pytest之中,如果说与用例相关联的fixture出现了报错,pytest会将当前用例停止执行,并标记为 错误状态。

 错误状态不是failed状态,所以并不能表示用例是不通过的。只能够说明是用例关联 的fixture出现了问题,用例本身没有发现任何错误。

@pytest.fixture
def first():return 1/0
#这是一个会报错的fixture
def test_function(first):print('这是test_function')
#这是一个会报错的测试用例
def test_function_01():1/0if __name__ == '__main__':pytest.main()

 两个测试用例,一个是调用了会报错的fixture,一个是会报错的测试用例。调用了会报错的fixture运行结果是error,会报错的测试用例运行结果是error。


3.4Fixture的setup操作

 这是fixture的setup操作:
        pytest启动运行会生成对应的session对象,本次执行的所有内容都会存放到session当中。
        所以setup分级:
            session -> module -> class -> function
        所有的setup定级需要在fixture之中传入一个参数,叫做scope,默认为function
        session级别的setup需要在conftest.py文件中进行定义。 

#定义函数级别的setup
import pytest# 定义函数级别的setup
@pytest.fixture(scope='function')
def function():print('this is function level')
# 定义class级别的setup
@pytest.fixture(scope='class')
def class_():print('this is class level')
# 定义py文件级别的setup
@pytest.fixture(scope='module')
def module():print('this is module level')def test_function(function):print('这是test_function')
if __name__ == '__main__':pytest.main(['-sv'])

 通过不同的参数,就可以实现不同级别的setup的实现。


3.5Fixture的teardown操作

3.5.1实现方法一 :关键字yield

 可以通过Fixture来实现teardown的操作。通过调用关键字yield实现teardown的操作需要 函数中有return的关键字。通过调用return,结束函数的运行,并返回一个对象。 函数中的yield是迭代器,在函数运行的时候,如果需要返回一个对象,但同时又需要函数能够继续运行 yield实现的teardown只能满足基本的需求,如果说Fixture在运行的时候报错了,yield就相对不会友好了。

import pytest@pytest.fixture(scope='function')
def first():print('this is setup')yieldprint('this is teardown')def test_function(first):print('this is a test_case')

 基于以上描述,可以知道应该先执行yield的代码,再执行测试用例,然后再执行yield后面的代码,观察运行结果,符合推理。

 teardown只能满足基本的需求,如果说Fixture在运行的时候报错了,yield就相对不会友好了。


3.5.2实现方法二  :定义requests.addfinalizer

通过在Fixture中定义requests.addfinalizer来实现。 此方法是通过在Fixture中进行注册的行为,来让程序运行结束时调用,实现teardown的相关操作。为了 避免因为Fixture报错,导致的代码无法正常运行,所以建议teardown的内容写在函数的最开始的位置。 

# 基于request.addfinalizer实现的teardown:request是固定写法,名称不能改变
@pytest.fixture
def second(request):#实现teardown的内容def second_finalizer():print('this is a finalizer')#注册teardown函数,实现fixture的teardown操作request.addfinalizer(second_finalizer)#正常定义setup行为print('this is a setup')
def test_function(second):print('this is a test_case')

将teardown内容定义成一个类似装饰器的函数,通过在Fixture中定义requests.addfinalizer将函数注册来实现。查看结果:


3.6 fixture参数的传入

fixture在特定场景下需要进行参数的传入。来实现Fixture代码的正常运行。
通过装饰器parametrize实现。

通过request参数来接收fixture中可能传入的参数内容,定义参数,传入到fixture之中,一定要记得添加indirect参数为True,意思就是将参数名称识别为fixture

# 定义参数,传入到fixture之中,一定要记得添加indirect参数为True,意思就是将参数名称识别为fixture
@pytest.mark.parametrize('login', [{'by': 'id', 'value': 'kw', 'txt': 'hcc'}], indirect=True)
@pytest.mark.parametrize('data', 'a')
def test_function(login, data):# login.find_element('id', 'su').click()# 通过request参数来接收fixture中可能传入的参数内容
# request可以接收任何格式的参数,不管是常用数据类型还是通过文件传入
@pytest.fixture
def login(request):print(data)

 

3.7 conftest——fixture统一管理

conftest.py文件的文件名是固定的,不能够修改。否则pytest会找不到,他相当于是一个Fixture的仓库,专门存放工程中的Fixture内容。便于在测试过程中
进行有效的统一管理和维护。
1. conftest.py文件的作用范围是文件所在的当前文件夹以及子文件夹。如果想要在整个工程都生效,则需要放到工程的根路径下。
2. conftest.py本身是pytest已定义好的,所以修改名称之后,pytest无法再找到你所设定文件,从而读取文件内容会失败。conftest.py是专门用来管理Fixture的文件。可以在conftest.py文件中将需要的Fixture全部定义好,在测试用例文件中,直接通过Fixture的名字来实现对它内容的调用。
3. 在conftest.py中定义的Fixture内容,可以在有效范围内被其他的测试用例所直接调用。不需要再进行额外的定义了。
4. conftest.py文件本身属于hook函数类型,我们也可以在这个文件中编写其他的hook函数。实现对pytest已有功能的增强。
5. session级别的Fixture必须要在conftest.py文件中定义。

3.8 ini文件 

文件是专门用来配置pytest的使用,如果要定义pytest相关的全局配置,都会使用这个文件来实现。
该文件推荐放在工程的根路径下。
pytest.ini的名称是固定写法,无法被更改。如果输入的指令在pytest.ini文件中已经定义了。
则新的指令会覆盖旧的指令。配置文件都是key:value形式。
[pytest]
# 定义mark标签
markers =hcc: 这是hcc的标签xzl: 这是xzl的标签
#将所有xfail装饰器的strict参数修改为指定的默认值。
xfail_strict = True
# 设置用例读取路径以及文件以及文件名称等相关的读取配置
testpaths = ./
python_files = test_*.py
python_classes = test_*
python_functions = test_*# 执行指令
addopts = -s -v -m xzl# 日志:在pytest之中,本身有定义日志记录的功能,我们可以在每次执行测试用例的时候,添加日志的记录。
#   在pytest中日志只能覆盖,不能追加
log_cli = True
log_cli_level = DEBUG
log_cli_date_format = %Y-%m-%d-%H:%M:%S
log_cli_format = %(levelname)s-%(asctime)s-%(filename)s-%(module)s-%(funcName)s-%(lineno)s:%(message)s
log_file = test.log
涉及到全局的变量,只要在ini文件中进行更改即可。

 

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

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

相关文章

kubectl常用命令(主题篇)

上一篇是按照操作把全局性的命令给整理出来,但是在实际的使用中,经常需要对某一个主题进行操作,因此这一篇按照对应的主题进行一系列操作。 集群 查看集群基本信息 kubectl cluster-info namespace 命名空间 查看 kubectl get namespace k…

web3d-three.js场景设计器-TransformControls模型控制器

场景设计器-TransformControls 控制器 该控制器可以指定模型进入可控制模式-如图有三种控制方式 translate --移动模式 rotate -- 旋转模式 scale -- 缩放模式 方便布局过程中快捷对模型进行摆放操作。 引入方式 import { TransformControls } from three/examples/jsm/…

C# visual studio COM创建及调用

1.visual studuio操作 1.1visual Studio创建类库项目ClassLibrary1。 1.1.1ClassLibrary1项目Class1.cs内容如下: using System; using System.Collections.Generic; using System.Linq; using System.Runtime.InteropServices; using System.Text; using System.T…

torch.where用法介绍

torch.where用法1介绍 torch.where(condition, x, y) → Tensor这个用法介绍直接搜就可以,不做介绍 torch.where用法2介绍(在yolov8中计算TP中出现) torch.where(condition) → Tensor返回的condition中为True的索引 直接举一个例子吧 condition torch.tensor(…

50N65-ASEMI高压N沟道MOS管50N65

编辑:ll 50N65-ASEMI高压N沟道MOS管50N65 型号:50N65 品牌:ASEMI 封装:TO-247 连续漏极电流(Id):50A 漏源电压(Vdss):650V 功率(Pd):388W 芯片个数:2 引脚数量:…

项目知识—SSM及之后02

1、resultMap写的Base内容必须保证select都使用上 2、VALUE单个 ,VALUES多个

Nginx部署笔记

记录Nginx部署Vue项目的流程,以及部署后前端出现问题的解决方案。 目录 一、安装nginx 二、部署流程 三、解决前端路由history模式刷新页面404的问题 四、Nginx解决前端项目打包缓存问题 五、后话 一、安装nginx http://nginx.org/ ,找到页面右下角的d…

leetcode2975. 移除栅栏得到的正方形田地的最大面积

题目 有一个大型的 (m - 1) x (n - 1) 矩形田地,其两个对角分别是 (1, 1) 和 (m, n) ,田地内部有一些水平栅栏和垂直栅栏,分别由数组 hFences 和 vFences 给出。 水平栅栏为坐标 (hFences[i], 1) 到 (hFences[i], n),垂直栅栏为…

企业微信 get请求 设置可信域名

import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController;RestController public class ValidController {GetMapping("/xxxxx.txt")public String getText() {//返回下载的txt里的内容return &…

React 实现 Step组件

简介 本文将会实现步骤条组件功能。步骤条在以下几个方面改进。 1、将url与Step组件绑定,做到浏览器刷新,不会重定向到Step 1 2、通过LocalStorage 存储之前的Step,做到不丢失数据。 实现 Step.jsx (组件) import {useEffect, useState} fro…

Java并行流parallelStream()下InheritableThreadLocal引起的问题

Java并行流parallelStream()下InheritableThreadLocal引起的问题 引起问题的代码。 List orgs00 Arrays.asList(new Org("aaa"),new Org("bbb"),new Org("aa0"));List orgs orgs00.parallelStream() .map(org -> {// 模拟从数据库中获取 …

如何用致远OA连接电商、CRM实现高效营销

连接电商与CRM:高效营销的关键 在竞争激烈的商业环境中,电商企业迫切需要将其营销活动提升到更高的水平。利用致远OA连接电商平台与CRM系统,可以打造一个无缝的信息流,从而实现高效的营销策略。通过自动化的数据同步,…

车流量识别摄像机

车流量识别摄像机是一种利用先进的图像识别技术和智能算法来监测道路上车辆数量和流量的设备。通过安装在道路或交通路口的摄像头,可以实时准确地统计车辆的通过情况,进而为交通管理、道路规划以及交通安全提供重要数据支持。 车流量识别摄像机主要通过计…

机器学习的三个方面

1 机器学习的三个方面 1.1 数据 包括数据采集、增强和质量管理,相当于给人工智能模型学习什么样的知识 第一、什么专业的知识; 第二、知识是否有体系,也就是说样本之间是否存在某种关联、差异等,这个涉及到样本选择等问题&#x…

SqlServer内存使用情况

-- 查询执行中sql语句 SELECT TOP 500 [session_id], [request_id], [start_time] AS 开始时间, getdate() as 当前时间, [status] AS 状态, [command] AS 命令, dest.[text] AS sql语句, DB_NAME([database_id]) AS 数据库名, [blocking_session_id] AS 正在阻塞其他会话的会话…

Docker资源配额

Docker资源配额指的是对Docker容器或服务在系统资源使用方面的限制。 通过资源配额,可以控制和限制Docker容器可以使用的CPU、内存、磁盘空间和网络带宽等资源。 根据应用程序的需求和系统环境来设置适当的资源配额:过于严格的配额可能导致应用程序性能下…

码云Gitee复制 GitHub 项目

码云提供了直接复制 GitHub 项目的功能,方便我们做项目的迁移和下载。 1.新建仓库 2.导入仓库 3.强制同步 如果 GitHub 项目更新了以后,在码云项目端可以手动重新同步,进行更新!

CSS新增文本描边-text-stroke属性

-webkit-text-stroke属性 概念:-webkit-text-stroke属性为文本添加描边效果。所谓的描边效果,指的是给文字添加边框 语法: -webkit-text-stroke:width color;Chrome和Firefox这两个浏览器都只能识别带有-webkit前缀的text-stroke属性 -web…

金和OA C6 UploadFileEditorSave.aspx 任意文件上传漏洞

产品介绍 金和网络是专业信息化服务商,为城市监管部门提供了互联网监管解决方案,为企事业单位提供组织协同OA系统开发平台,电子政务一体化平台,智慧电商平台等服务。 漏洞概述 金和 OA C6 uploadfileeditorsave接口处存在任意文件上传漏洞,攻击者可以通过构造特殊…

洛谷——P1983 [NOIP2013 普及组] 车站分级(拓扑排序、c++)

文章目录 一、题目[NOIP2013 普及组] 车站分级题目背景题目描述输入格式输出格式样例 #1样例输入 #1样例输出 #1 样例 #2样例输入 #2样例输出 #2 提示 二、题解基本思路:代码 一、题目 [NOIP2013 普及组] 车站分级 题目背景 NOIP2013 普及组 T4 题目描述 一条单…