Pytest中fixture的scope详解

news2024/10/17 11:31:32

pytest作为Python技术栈下最主流的测试框架,功能极为强大和灵活。其中Fixture夹具是它的核心。而且pytest中对Fixture的作用范围也做了不同区分,能为我们利用fixture带来很好地灵活性。

下面我们就来了解下这里不同scope的作用

fixture的scope定义

首先根据官网的说明,Pytest中fixture的作用范围支持5种设定,分别是function(默认值), classs, module, package, session

作用范围说明
function默认值,对每个测试方法(函数)生效,生命周期在测试方法级别
class对测试类生效,生命周期在测试类级别
module对测试模块生效,生命周期在模块(文件)级别
package对测试包生效,生命周期在测试包(目录)级别
session对测试会话生效,生命周期在会话(一次pytest运行)级别

下面结合代码来说明,假设目前有这样的代码结构

在这里插入图片描述

run_params是被测方法

def deal_params(p):  
    print(f"input :{p}")  
    if type(p) is int:  
        return p*10  
    if type(p) is str:  
        return p*3  
    if type(p) in (tuple, list):  
        return "_".join(p)  
    else:  
        raise TypeError

test_ch_param, test_fixture_scope中分别定义了参数化和在测试类中的不同测试方法

import pytest

@pytest.mark.parametrize("param",[10, "城下秋草", "软件测试", ("示例", "代码")])  
def test_params_mark(param):  
    print(deal_params(param))
import pytest  
 
class TestFixtureScope1:  
    def test_int(self):  
        assert deal_params(2) == 20  
  
    def test_str(self):  
        assert deal_params("秋草") == "秋草秋草秋草"  
  
class TestFixtureScope2:  
    def test_list(self):  
        assert deal_params(["城下","秋草"]) == "城下_秋草"  
  
    def test_dict(self):  
        with pytest.raises(TypeError):  
            deal_params({"name": "秋草"})

在公共方法文件conftest.py中定义fixture: prepare, 设置了autouse=True,即会根据fixture的设置范围自动应用

@pytest.fixture(autouse=True, scope='function')  
def prepare():  
    print('-----some setup actions.....')  
    yield  
    print('-----some teardown actions!!')

这里我们分别调整prepare的scope为不同取值,然后得到对应的输出

function

(.venv) C:\Chengxiaqiucao
pytest
======================================== test session starts =========================================
collected 8 items                                                                                     

BlogDemo/testDemo/test_ch_parm.py::test_params_mark[10] -----some setup actions.....
input :10
100
PASSED-----some teardown actions!!

BlogDemo/testDemo/test_ch_parm.py::test_params_mark[城下秋草] -----some setup actions.....
input :城下秋草
城下秋草城下秋草城下秋草
PASSED-----some teardown actions!!

BlogDemo/testDemo/test_ch_parm.py::test_params_mark[软件测试] -----some setup actions.....
input :软件测试
软件测试软件测试软件测试
PASSED-----some teardown actions!!

BlogDemo/testDemo/test_ch_parm.py::test_params_mark[param3] -----some setup actions.....
input :('示例', '代码')
示例_代码
PASSED-----some teardown actions!!

BlogDemo/testDemo/test_fixture_scope.py::TestFixtureScope1::test_int -----some setup actions.....
input :2
PASSED-----some teardown actions!!

BlogDemo/testDemo/test_fixture_scope.py::TestFixtureScope1::test_str -----some setup actions.....      
input :秋草
PASSED-----some teardown actions!!

BlogDemo/testDemo/test_fixture_scope.py::TestFixtureScope2::test_list -----some setup actions.....     
input :['城下', '秋草']
PASSED-----some teardown actions!!

BlogDemo/testDemo/test_fixture_scope.py::TestFixtureScope2::test_dict -----some setup actions.....     
input :{'name': '秋草'}
PASSED-----some teardown actions!!


========================================= 8 passed in 0.27s ========================================== 

fixture运行了8次

class

(.venv) C:\Chengxiaqiucao
pytest
======================================== test session starts =========================================
collected 8 items                                                                                     

BlogDemo/testDemo/test_ch_parm.py::test_params_mark[10] -----some setup actions.....
input :10
100
PASSED-----some teardown actions!!

BlogDemo/testDemo/test_ch_parm.py::test_params_mark[城下秋草] -----some setup actions.....
input :城下秋草
城下秋草城下秋草城下秋草
PASSED-----some teardown actions!!

BlogDemo/testDemo/test_ch_parm.py::test_params_mark[软件测试] -----some setup actions.....
input :软件测试
软件测试软件测试软件测试
PASSED-----some teardown actions!!

BlogDemo/testDemo/test_ch_parm.py::test_params_mark[param3] -----some setup actions.....
input :('示例', '代码')
示例_代码
PASSED-----some teardown actions!!

BlogDemo/testDemo/test_fixture_scope.py::TestFixtureScope1::test_int -----some setup actions.....
input :2
PASSED
BlogDemo/testDemo/test_fixture_scope.py::TestFixtureScope1::test_str input :秋草
PASSED-----some teardown actions!!

BlogDemo/testDemo/test_fixture_scope.py::TestFixtureScope2::test_list -----some setup actions.....     
input :['城下', '秋草']
PASSED
BlogDemo/testDemo/test_fixture_scope.py::TestFixtureScope2::test_dict input :{'name': '秋草'}
PASSED-----some teardown actions!!


========================================= 8 passed in 0.27s ========================================== 

test_ch_param中的测试方法,因为直接定义在文件中,也属于类级别,所以每次赋值参数,fixture也被调用。 而 test_fixture_scope中明确定义了两个测试类,所以运行了2次

module

(.venv) C:\Chengxiaqiucao
pytest
======================================== test session starts =========================================
collected 8 items                                                                                     

BlogDemo/testDemo/test_ch_parm.py::test_params_mark[10] -----some setup actions.....
input :10
100
PASSED
BlogDemo/testDemo/test_ch_parm.py::test_params_mark[城下秋草] input :城下秋草
城下秋草城下秋草城下秋草
PASSED
BlogDemo/testDemo/test_ch_parm.py::test_params_mark[软件测试] input :软件测试
软件测试软件测试软件测试
PASSED
BlogDemo/testDemo/test_ch_parm.py::test_params_mark[param3] input :('示例', '代码')
示例_代码
PASSED-----some teardown actions!!

BlogDemo/testDemo/test_fixture_scope.py::TestFixtureScope1::test_int -----some setup actions.....
input :2
PASSED
BlogDemo/testDemo/test_fixture_scope.py::TestFixtureScope1::test_str input :秋草
PASSED
BlogDemo/testDemo/test_fixture_scope.py::TestFixtureScope2::test_list input :['城下', '秋草']
PASSED
BlogDemo/testDemo/test_fixture_scope.py::TestFixtureScope2::test_dict input :{'name': '秋草'}
PASSED-----some teardown actions!!


========================================= 8 passed in 0.27s ========================================== 

修改为module范围后,可以看到,每个模块文件调用了一次fixture

package

(.venv) C:\Chengxiaqiucao
pytest
======================================== test session starts =========================================
collected 8 items                                                                                     

BlogDemo/testDemo/test_ch_parm.py::test_params_mark[10] -----some setup actions.....
input :10
100
PASSED
BlogDemo/testDemo/test_ch_parm.py::test_params_mark[城下秋草] input :城下秋草
城下秋草城下秋草城下秋草
PASSED
BlogDemo/testDemo/test_ch_parm.py::test_params_mark[软件测试] input :软件测试
软件测试软件测试软件测试
PASSED
BlogDemo/testDemo/test_ch_parm.py::test_params_mark[param3] input :('示例', '代码')
示例_代码
PASSED
BlogDemo/testDemo/test_fixture_scope.py::TestFixtureScope1::test_int input :2
PASSED
BlogDemo/testDemo/test_fixture_scope.py::TestFixtureScope1::test_str input :秋草
PASSED
BlogDemo/testDemo/test_fixture_scope.py::TestFixtureScope2::test_list input :['城下', '秋草']
PASSED
BlogDemo/testDemo/test_fixture_scope.py::TestFixtureScope2::test_dict input :{'name': '秋草'}
PASSED-----some teardown actions!!


========================================= 8 passed in 0.27s ========================================== 

修改为package, 这是因为两个测试文件位于同一个package内, 所以运行了一次

session

(.venv) C:\Chengxiaqiucao
pytest
======================================== test session starts =========================================
collected 8 items                                                                                     

BlogDemo/testDemo/test_ch_parm.py::test_params_mark[10] -----some setup actions.....
input :10
100
PASSED
BlogDemo/testDemo/test_ch_parm.py::test_params_mark[城下秋草] input :城下秋草
城下秋草城下秋草城下秋草
PASSED
BlogDemo/testDemo/test_ch_parm.py::test_params_mark[软件测试] input :软件测试
软件测试软件测试软件测试
PASSED
BlogDemo/testDemo/test_ch_parm.py::test_params_mark[param3] input :('示例', '代码')
示例_代码
PASSED
BlogDemo/testDemo/test_fixture_scope.py::TestFixtureScope1::test_int input :2
PASSED
BlogDemo/testDemo/test_fixture_scope.py::TestFixtureScope1::test_str input :秋草
PASSED
BlogDemo/testDemo/test_fixture_scope.py::TestFixtureScope2::test_list input :['城下', '秋草']
PASSED
BlogDemo/testDemo/test_fixture_scope.py::TestFixtureScope2::test_dict input :{'name': '秋草'}
PASSED-----some teardown actions!!


========================================= 8 passed in 0.27s ========================================== 

最后,当设置为session时,也就是运行pytest的一次执行会话,才会触发一次fixture调用

所以可以看到,我们通过fixture的不同scope定义,可以根据需要,来确定我们编写的fixture夹具的作用范围。有很好的灵活性

复杂fixture的scope灵活定义

有时在实际使用的时候,特别是我们的一些fixture初始化工作比较复杂但同时在不同作用范围下都可能会用到,这时如果仅仅因为针对不同的作用范围,就要编写多个不同的fixture,代码就显得比较冗余。这时可以怎么处理呢? 其实可以利用上下文contextmanager来灵活实现

比如我们再编写一个fixture的基本代码上下文:

@contextmanager  
def fixture_base():  
    print('~~~~~base fixture setup actions.....')  
    yield  
    print('~~~~~base fixture teardown actions!!')

然后针对不同的fixture,我们就可以根据不同的scope来定义不同的fixture并调用这里的context实现。 比如我们再定义一个scope为package的fixture

@pytest.fixture(autouse=False, scope='package')  
def fixture_module():  
    """  
    对于复杂的fixture但希望灵活处理scope,可以将公共代码放到一个contextmanager中,  
    再针对不同scope定义相关对应fixture  
    """    with fixture_base() as result:  
        yield result

👍👍这个方法来自pytest的社区总结,原始问题链接

不同scope的执行顺序

上面例子中我们其实看到package和session的执行效果,因为测试方法都在同一个package中,所以效果上没什么差异。但其实不同scope也是有执行顺序的

顺序总结如下:

session > package > module > class > function

这里增加到两个fixture以后,执行的结果:

(.venv) C:\Chengxiaqiucao
pytest
======================================== test session starts =========================================
collected 8 items                                                                                     

BlogDemo/testDemo/test_ch_parm.py::test_params_mark[10] -----some setup actions.....
~~~~~base fixture setup actions.....
input :10
100
PASSED
BlogDemo/testDemo/test_ch_parm.py::test_params_mark[城下秋草] input :城下秋草
城下秋草城下秋草城下秋草
PASSED
BlogDemo/testDemo/test_ch_parm.py::test_params_mark[软件测试] input :软件测试
软件测试软件测试软件测试
PASSED
BlogDemo/testDemo/test_ch_parm.py::test_params_mark[param3] input :('示例', '代码')
示例_代码
PASSED
BlogDemo/testDemo/test_fixture_scope.py::TestFixtureScope1::test_int input :2
PASSED
BlogDemo/testDemo/test_fixture_scope.py::TestFixtureScope1::test_str input :秋草
PASSED
BlogDemo/testDemo/test_fixture_scope.py::TestFixtureScope2::test_list input :['城下', '秋草']
PASSED
BlogDemo/testDemo/test_fixture_scope.py::TestFixtureScope2::test_dict input :{'name': '秋草'}
PASSED~~~~~base fixture teardown actions!!
-----some teardown actions!!


========================================= 8 passed in 0.27s ========================================== 

可以看到 sessionpackage 更早执行,同时更晚被销毁。

那么以上就是关于pytest scope作用范围的总结


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

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

相关文章

8.优化存储过程的性能(8/10)

优化存储过程的性能 1.引言 存储过程是数据库系统中预先编写好的SQL语句集合,它们被保存在数据库服务器上,可以在需要时被调用执行。存储过程的使用可以提高数据库操作的效率,减少网络通信,并且可以封装复杂的逻辑,使…

中科星图GVE(案例)——AI实现建筑用地变化前后对比情况

目录 简介 函数 gve.Services.AI.ConstructionLandChangeExtraction(image1,image2) 代码 结果 知识星球 机器学习 简介 AI可以通过分析卫星图像、航拍影像或其他地理信息数据,实现建筑用地变化前后对比。以下是一种可能的实现方法: 数据获取&am…

全能PDF工具集 | PDF Shaper Ultimate v14.6 便携版

软件简介 PDF Shaper是一款功能强大的PDF工具集,它提供了一系列用于处理PDF文档的工具。这款软件使用户能够轻松地转换、分割、合并、提取页面以及旋转和加密PDF文件。PDF Shaper的界面简洁直观,使得即使是新手用户也能快速上手。它支持广泛的功能&…

牛客一>DP34 【模板】前缀和

1.题目: 【模板】前缀和_牛客题霸_牛客网 2.解析:这里可以看成一个缩小版动态规划 代码: import java.util.Scanner;// 注意类名必须为 Main, 不要有任何 package xxx 信息 public class Main {public static void main(String[] args) {Scan…

【无人机设计与控制】滑模控制、反步控制、传统PID四旋翼无人机轨迹跟踪控制仿真

摘要 本文基于滑模控制、反步控制和传统PID控制,设计了针对四旋翼无人机的轨迹跟踪控制系统。通过对比这三种控制策略在四旋翼无人机轨迹跟踪中的表现,分析了各自的优缺点和适用场景。仿真结果表明,滑模控制具有更强的鲁棒性,反步…

Windows 远程桌面提示没有远程桌面授权服务器可以提供许可证 无法保存对 graceperiod 权限所作的更改

参考文章:远程连接提示 由于没有远程桌面授权服务器提供许可证 Windows 远程桌面提示没有远程桌面授权服务器可以提供许可证 远程桌面到windows服务器上时报错:由于没有远程桌面授权服务器可以提供许可证,远程会话被中断。请跟服务器管理员…

系统缺失mfc140.dll的修复方法,有效修复错误mfc140.dll详细步骤

mfc140.dll丢失原因分析 1 系统文件损坏或病毒感染 系统文件损坏或被病毒感染是导致mfc140.dll丢失的常见原因之一。根据用户反馈和安全研究报告,大约有30%的mfc140.dll丢失案例与系统文件损坏或病毒感染有关。病毒、木马或其他恶意软件可能会破坏或删除系统中的m…

kafka-manager修改zookeeper端口号后启动仍然连接2181端口

问题描述: zookeeper默认端口号修改为了2182,kafka-manager的配置文件application.conf中也已经修改了zkhosts为新的端口号,然而启动kafka-manger时报错连接连接超时,发现连接的还是2181端口,很奇怪?&…

大语言模型入门(五)——思维链

一、什么是思维链 思维链(Chain-of-Thought,简称CoT)是一种在大型语言模型(LLMs)中使用的技术,旨在提升模型在复杂推理任务上的表现。这种方法通过模拟人类解决问题时的思考过程,将问题分解为一…

信号量(Semaphore)是什么,如何使用?

信号量(Semaphore)是 Java java.util.concurrent 包中的一种同步辅助类,用于控制对共享资源的访问。在并发编程中,信号量常用于限制同时访问特定资源的线程数量,避免过多线程同时访问可能导致的资源竞争或性能下降。 …

verilog 介绍(附状态机实例)

author: hjjdebug date: 2024年 10月 12日 星期六 15:02:56 CST description: verilog 介绍(附状态机实例) 初学者可以把菜鸟教程中的verilog 当参考手册. 但那里介绍的太多了,精简入门(或者入门后的概括)看看本博就够了. 1. 什么是HDL ? HDL, hardware descrip…

FPM工具制作RPM包

文章目录 一、fpm工具介绍1、什么是fpm?2、fpm技术分析3、fpm应用场景4、fpm与rpmbuild的区别 二、fpm安装及构建操作1、安装fpm工具1.1、安装ruby环境1.2、Ruby Gems源更换为国内的源1.3、删除官方源1.4、查看当前源列表1.5、安装fpm版本1.5.1、报错解决 2、fpm常用参数 三、…

Kaggle竞赛——森林覆盖类型分类

目录 1. 竞赛简要2. 数据分析2.1 特征类型统计2.2 四个荒野区域数据分析2.3 连续特征分析2.4 离散特征分析2.5 特征相关性热图2.6 特征间的散点关系图 3. 特征工程3.1 特征组合3.2 连续特征标准化 4. 模型搭建4.1 模型定义4.2 绘制混淆矩阵和ROC曲线4.3 模型对比与选择 5. 测试…

详解安卓和IOS的唤起APP的机制,包括第三方平台的唤起方法比如微信

网页唤起APP是一种常见的跨平台交互方式,它允许用户从网页直接跳转到移动应用程序。 这种技术广泛应用于各种场景,比如让用户在浏览器中点击链接后直接打开某个应用,或者从网页引导用户下载安装应用。实现这一功能主要依赖于URL Scheme、Univ…

线性代数 行列式

一、行列式 1、定义 一个数学概念,主要用于 线性代数中,它是一个可以从方阵(即行数和列数相等的矩阵)形成的一个标量(即一个单一的数值) 2、二阶行列式 ,像这样将一个式子收缩称为一个 2*2 的…

校车购票微信小程序的设计与实现(lw+演示+源码+运行)

摘 要 由于APP软件在开发以及运营上面所需成本较高,而用户手机需要安装各种APP软件,因此占用用户过多的手机存储空间,导致用户手机运行缓慢,体验度比较差,进而导致用户会卸载非必要的APP,倒逼管理者必须改…

基于深度学习的细粒度图像分析综述【翻译】

🥇 版权: 本文由【墨理学AI】原创首发、各位读者大大、敬请查阅、感谢三连 🎉 声明: 作为全网 AI 领域 干货最多的博主之一,❤️ 不负光阴不负卿 ❤️ 文章目录 基础信息0 摘要1 INTRODUCTION2 识别与检索 RECOGNITION VS. RETRIEVAL3 问题和…

腾讯云视立方TRTCCalling Web 相关

基础问题 什么是 TRTCCalling? TRTCCalling 是在 TRTC 和 TIM 的基础上诞生的一款快速集成的音视频的解决方案。支持1v1和多人视频/语音通话。 TRTCCalling 是否支持接受 roomID 为字符串? roomID 可以 string,但只限于数字字符串。 环境问题 Web …

QD1-P24 CSS 组合选择器

本节学习:CSS 组合选择器 本节视频 https://www.bilibili.com/video/BV1n64y1U7oj?p24 组合选择器是使用多个基础选择器组合在一起来选择更具体的目标元素的方法。以下是几种常见的组合选择器: 下面四个选择器是本节学习内容 后代选择器(De…

在线Ipv4转Ipv6工具

具体请前往:Ipv4到Ipv6在线转换工具--可将Ipv4换算为Ipv6地址和Ipv6的缩写格式