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/0

if __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')
    yield
    print('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文件中进行更改即可。
 

 

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

thingsboard规则节点功能记录(自用)

本文是对【ThingsBoard源码级分析规则节点使用第一季】 https://www.bilibili.com/video/BV1CT411e7vt/?p4&share_sourcecopy_web&vd_source9a5ca7ed3cff97385fdab4b6188e485c 学习的一些记录,加深自己的理解,在此声明。 asset profile switch…

五、HTML 标题

在 HTML 文档中&#xff0c;标题很重要。 一、HTML 标题 标题&#xff08;Heading&#xff09;是通过 <h1> - <h6> 标签进行定义的。<h1> 定义最大的标题。 <h6> 定义最小的标题。 <h1>这是一个标题。</h1> <h2>这是一个标题。&l…

微型导轨在设备中起什么作用

微型导轨精度高&#xff0c;摩擦系数小&#xff0c;自重轻&#xff0c;结构紧凑&#xff0c;可以用于电子制造设备、半导体制造设备、医疗设备、光学设备和机器人等各种工业机械设备中&#xff0c;那么微型导轨在设备中起什么作用呢&#xff1f; 1、导向与定位&#xff1a;为机…

Flume基础知识(九):Flume 企业开发案例之复制和多路复用

1&#xff09;案例需求 使用 Flume-1 监控文件变动&#xff0c;Flume-1 将变动内容传递给 Flume-2&#xff0c;Flume-2 负责存储 到 HDFS。同时 Flume-1 将变动内容传递给 Flume-3&#xff0c;Flume-3 负责输出到 Local FileSystem。 2&#xff09;需求分析&#xff1a; 3&…

【论文解读】基于神经辐射场NeRF的像素级交互式编辑(Seal-3D)

来源&#xff1a;投稿 作者&#xff1a;橡皮 编辑&#xff1a;学姐 论文链接&#xff1a;https://arxiv.org/pdf/2307.15131 项目主页&#xff1a;https://windingwind.github.io/seal-3d/ 摘要&#xff1a; 随着隐式神经表征或神经辐射场&#xff08;NeRF&#xff09;的普及…

推荐几个免费的HTTP接口Mock网站和工具

在前后端分离开发架构下&#xff0c;经常遇到调用后端数据API接口进行测试、集成、联调等需求&#xff0c;比如&#xff1a; &#xff08;1&#xff09;前端开发人员很快开发完成了UI界面&#xff0c;但后端开发人员的API接口还没有完成&#xff0c;不能进行前后端数据接口对接…

嵌入式开发——电源管理单元PMU

学习目标 了解什么是电池管理单元PMU了解ARM32中的电源域了解几种省电模式学习内容 PMU PMU全称Power Management Unit,电源管理单元。 电源域 总共有三大电源域,包括VDD / VDDA域,1.2V域和备份域。 VDD/VDDA域 VDD/VDDA域如下图: 提供PMU 常规电源供应以下模块的供电…

C# 反射的乌云,MethodInfo的Json序列化参数入参问题

文章目录 前言直接运行MethodInfo运行结果 Json解决ParamterInfo实例化运行结果无法实例化问题部分参数的问题 Json反序列化 经过长达一天的研究&#xff0c;我终于完全的解决的了实战思路方法测试用例运行测试运行结果 代码总结总结 前言 我上篇文章已经基本解决了反射的基本…

【SpringCloud】之远程消费(进阶使用)

&#x1f389;&#x1f389;欢迎来到我的CSDN主页&#xff01;&#x1f389;&#x1f389; &#x1f3c5;我是君易--鑨&#xff0c;一个在CSDN分享笔记的博主。&#x1f4da;&#x1f4da; &#x1f31f;推荐给大家我的博客专栏《SpringCloud开发之远程消费》。&#x1f3af;&a…

python画图工具总结

一、python工具 python运行工具&#xff1a;Anaconda3 Anaconda3运行模式&#xff1a;jupyter notebook 操作系统&#xff1a;window11 二、折线图 from matplotlib import pyplot import matplotlib.pyplot as plt from math import sqrt import pandas as pd from matplot…

ffmpeg.c(4.3.1)源码剖析

文章目录 前言一、FFmpeg 源码结构图二、ffmpeg.h 头文件详解三、main 函数主要流程分析四、ffmpeg_parse_options1、命令行例子①、解析命令行 split_commandline()②、parse_optgroup()③、MATCH_PER_XXX_OPT() 2、vf 选项解析①、filters②、vf 术语③、avfilter_graph_pars…

【LeetCode每日一题】2807. 在链表中插入最大公约数(模拟+求最大公约数的6中写法)

2024-1-6 文章目录 [2807. 在链表中插入最大公约数](https://leetcode.cn/problems/insert-greatest-common-divisors-in-linked-list/)思路&#xff1a;模拟求最大公约数的几种方法&#xff1a; 1.暴力枚举法2.辗转相除法3.辗转相除法 ---递归调用4.辗转相除法 ---递归调用---…

微服务注册中的负载均衡

背景 随着互联网行业的发展&#xff0c;对服务的要求也越来越高&#xff0c;服务架构也从单体架构逐渐演变为现在流行的微服务架构。这些架构之间有怎样的差别呢&#xff1f; 单体架构&#xff1a;简单方便&#xff0c;高度耦合&#xff0c;扩展性差&#xff0c;适合小型项目。…

【计算机毕业设计】SSM在线化妆品网站

项目介绍 本项目为前后台项目&#xff0c;前台为普通用户登录&#xff0c;后台为管理员登录&#xff1b; 管理员角色包含以下功能&#xff1a; 管理员登录,分类管理,产品管理,用户管理,订单管理等功能。 用户角色包含以下功能&#xff1a; 提交订单,用户登录,用户首页,查看…

MySQL数据库期末知识点总结(复习版)

一、数据库基本知识 数据库中的数据有什么特点 1、数据是按某种结构组织的 2、数据有整体性、共享性和较高的独立性 数据管理技术经历了哪三个阶段 1、手工管理 2、文件管理 3、数据库管理 数据库管理系统的主要功能有哪些 数据库管理系统的主要功能包括数据定义、数据…

欧科云链研究院:奔赴2024,Web3与AI共振引爆数字时代潘多拉魔盒

出品&#xff5c;欧科云链研究院 2024年&#xff0c;Web3与AI两个数字科技的巅峰碰撞&#xff0c;欧科云链研究院探索AI与Web3的技术融合&#xff0c;与澎湃科技联合发布2024年展望&#xff0c;原标题为《2024年展望&#xff1a;Web3与AI共振引爆可信数字社会》&#xff0c;共…

Mybatis-Mapper代理开发

Mapper代理开发 目的使用Mapper代理方式入门1.定义与SQL映射文件同名的Mapper接口&#xff0c;并且将Mapper接口和SQL映射文件放置在同一目录下首先新建一个Mapper接口编译mybatis-demo更改sql映射文件路径 2.设置SQL映射文件的namespace属性为Mapper接口全限定名3.在Mapper 接…

数据在内存中的存储之大小端

今天也是努力学编程&#xff0c;敲代码的一天&#xff01; 1.什么是大小端 其实超过一个字节的数据在内存中存储的时候&#xff0c;就有存储顺序的问题&#xff0c;按照不同的存储顺序&#xff0c;我们分为大端字节序 存储和小端字节序存储&#xff0c;下面是具体的概念: &…

吉时利2601A数字源表Keithley 2601A

吉时利2601A源测量单元&#xff08;SMU&#xff09;&#xff0c;也被称为源表&#xff0c;是一种高性能的仪器&#xff0c;能够提供100毫伏至40伏的电压范围&#xff0c;以及100纳至10安的电流范围。这种仪器能够提供的功率高达40.4瓦&#xff0c;使其在台式I-V表征工具或多通道…

如何充值GPT会员账号?

详情点击链接&#xff1a;如何充值GPT会员账号&#xff1f; 一OpenAI 1.最新大模型GPT-4 Turbo 2.最新发布的高级数据分析&#xff0c;AI画图&#xff0c;图像识别&#xff0c;文档API 3.GPT Store 4.从0到1创建自己的GPT应用 5. 模型Gemini以及大模型Claude2二定制自己的…