利用 Pytest Cache Fixture 实现测试结果缓存

news2024/10/7 17:32:58

前言

接口自动关过程中,经常会遇到这样一些场景,"请求2需要用到请求1响应的数据",常见的做法,进行用例依赖或者将请求1的响应结果写入一个文件,用到的时候读取文件。当然这都不是这篇文章的重点,本片文章主要介绍cache写入和读取缓存数据。

request.config.cache

还不了解request fixture的同学可以先看看这篇文章,pytest 的 request fixture:实现个性化测试需求

我们先看看使用案例:

def test_01(cache):
    cache.set("token", "uiouoouoiou")
​
def test_02(cache):
    r = cache.get("token", None)

这样段代码在执行test_01会将token值缓存,任何执行test_02时就可以从缓存中读取token值。那Cache是如何实现的呢?我们一起来看看源码。源码直达

实现原理

def test_01(cache):
    cache.set("token", {"token": "1212121"})

我们在cache.set()这一行进行断点,debug执行后,debug结果为

cache = Cache()
_CACHE_PREFIX_DIRS = 'd'
_CACHE_PREFIX_VALUES = 'v'
_cachedir = /PycharmProjects/panda-test/org/.pytest_cache
_config = <_pytest.config.Config object at 0x109e80d60>

可以看到会自动创建一个缓存实例,而且初始化了一些数据,默认应该缓存文件会在.pytest_cache目录下

/_pytest/cacheprovider.py

@fixture
def cache(request: FixtureRequest) -> Cache:
    """Return a cache object that can persist state between testing sessions.
​
    cache.get(key, default)
    cache.set(key, value)
​
    Keys must be ``/`` separated strings, where the first part is usually the
    name of your plugin or application to avoid clashes with other cache users.
​
    Values can be any object handled by the json stdlib module.
    """
    assert request.config.cache is not None
    return request.config.cache

可以看到,cache返回的是Cache对象,我们看看Cache对象是如何实现的

def set(self, key: str, value: object) -> None:
        path = self._getvaluepath(key)
        try:
            if path.parent.is_dir():
                cache_dir_exists_already = True
            else:
                cache_dir_exists_already = self._cachedir.exists()
                path.parent.mkdir(exist_ok=True, parents=True)
        except OSError:
            self.warn("could not create cache path {path}", path=path, _ispytest=True)
            return
        if not cache_dir_exists_already:
            self._ensure_supporting_files()
        data = json.dumps(value, ensure_ascii=False, indent=2)
        try:
            f = path.open("w", encoding="UTF-8")
        except OSError:
            self.warn("cache could not write path {path}", path=path, _ispytest=True)
        else:
            with f:
                f.write(data)

这段源码就是用来将键值对保存到缓存中。代码比较简单,简单解释一下

  1. 获取要保存的键值对的路径:通过调用 _getvaluepath() 方法,根据给定的键(key)获取值(value)在缓存中的路径(path)。这里的路径是一个字符串,使用/分隔不同的层级,通常第一个名称是插件或应用程序的名称。
  2. 检查路径是否存在:通过判断路径的父目录是否为目录来确定是否需要创建路径。如果父目录已经存在,则 cache_dir_exists_already 设置为 True;否则,它会检查缓存目录是否存在,并且如果缓存目录已经存在,则 cache_dir_exists_already 设置为 True,否则创建缓存目录。
  3. 确保支持文件已存在:如果缓存目录是新创建的,则调用 _ensure_supporting_files() 方法确保支持文件存在。这个方法可能是用来创建其他与缓存相关的文件或目录。
  4. 序列化数据并写入文件:将值(value)使用 JSON 格式进行序列化,以确保它是基本的 Python 类型或包含了嵌套类型(例如列表和字典)。然后,尝试打开路径对应的文件(使用 UTF-8 编码),并将序列化后的数据写入文件中。
def get(self, key: str, default):
        
        path = self._getvaluepath(key)
        try:
            with path.open("r", encoding="UTF-8") as f:
                return json.load(f)
        except (ValueError, OSError):
            return default

这段源码用来从缓存中获取指定键的值,简单解释一下:

  1. 获取要获取值的路径:通过调用 _getvaluepath() 方法,根据给定的键(key)获取值在缓存中的路径(path)。这里的路径是一个字符串,使用 / 分隔不同的层级,通常第一个名称是插件或应用程序的名称。
  2. 尝试读取文件并返回已缓存的值:使用路径对应的文件(使用 UTF-8 编码)打开,并使用 json.load(f) 将文件中的数据加载为 Python 对象。然后将加载的值返回。
  3. 处理异常情况:如果无法将文件中的内容解析为有效的 JSON 数据或者打开文件失败,则捕获异常(ValueErrorOSError),并返回默认值(default)。

这里还是学习到了一种新奇的写法,以前没用过with path.open("r", encoding="UTF-8") as f:等价于open(path, "r", encoding="UTF-8")

这是两个常用的方法,当然还提供了更多方法,这里简单介绍一下:

  1. __init__(self, cachedir: Path, config: Config, *, _ispytest: bool = False) -> None

    • 初始化方法,用于设置类的属性 _cachedir_config
  2. for_config(cls, config: Config, *, _ispytest: bool = False) -> "Cache"

    • 类方法,根据给定的配置信息创建并返回 Cache 实例。
    • 如果配置项 cacheclear 设置为 True,并且缓存目录存在,则调用 clear_cache 方法清空缓存。
    • 最后返回一个新的 Cache 实例。
  3. clear_cache(cls, cachedir: Path, _ispytest: bool = False) -> None

    • 类方法,清空缓存目录下的子目录。
    • 根据参数 cachedir 构建子目录路径,并使用 rm_rf 函数递归删除该目录。
  4. cache_dir_from_config(config: Config, *, _ispytest: bool = False) -> Path

    • 静态方法,从给定的配置信息中获取缓存目录的路径。
    • 首先从配置中获取缓存目录的字符串表示,然后使用 resolve_from_str 函数将其解析为 Path 对象返回。
  5. warn(self, fmt: str, *, _ispytest: bool = False, **args: object) -> None

    • 发出缓存警告的方法。
    • 使用 warnings.warn 函数发出警告信息,并指定警告类型为 PytestCacheWarning
    • 如果存在参数 args,则将其作为格式化参数替换格式字符串中的占位符。
  6. mkdir(self, name: str) -> Path

    • 创建一个目录路径对象,并在缓存目录下创建该目录。
    • 参数 name 是要创建的目录名称。
    • 检查目录名是否包含路径分隔符 /,如果有则抛出异常。
    • 使用 _cachedir.joinpath 方法构建完整的目录路径,并使用 mkdir 方法创建目录。
    • 返回创建的目录路径对象。
  7. _getvaluepath(self, key: str) -> Path

    • 根据给定的键生成值文件的路径。
    • 在缓存目录下构建值文件路径,使用 _CACHE_PREFIX_VALUES 作为子目录前缀。
  8. _ensure_supporting_files(self) -> None

    • 创建缓存目录中的支持文件。
    • 创建 README.md 文件,用于说明缓存目录的用途。
    • 创建 .gitignore 文件,忽略缓存目录下的所有文件。
    • 创建 CACHEDIR.TAG 文件,用于标记缓存目录。

最后

cache功能还是很实用的,比如登录功能,可以在登录之后,将token写入缓存,这样进行其他接口请求时,需要token时直接从缓存获取token即可。

最后:下面是配套学习资料,对于做【软件测试】的朋友来说应该是最全面最完整的备战仓库,这个仓库也陪伴我走过了最艰难的路程,希望也能帮助到你!【100%无套路免费领取】

软件测试面试小程序

被百万人刷爆的软件测试题库!!!谁用谁知道!!!全网最全面试刷题小程序,手机就可以刷题,地铁上公交上,卷起来!

涵盖以下这些面试题板块:

1、软件测试基础理论 ,2、web,app,接口功能测试 ,3、网络 ,4、数据库 ,5、linux

6、web,app,接口自动化 ,7、性能测试 ,8、编程基础,9、hr面试题 ,10、开放性测试题,11、安全测试,12、计算机基础

  全套资料获取方式:点击下方小卡片自行领取即可

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

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

相关文章

Redis性能滑坡:哈希表碰撞的不速之客【redis第二部分】

Redis性能滑坡&#xff1a;哈希表碰撞的不速之客 前言第一部分&#xff1a;Redis哈希表简介第二部分&#xff1a;哈希表冲突原因第三部分&#xff1a;Redis哈希函数第四部分&#xff1a;哈希表冲突的性能影响第五部分&#xff1a;解决冲突策略第六部分&#xff1a;redis是如何解…

nginx常见报错及解决acme.sh给Nginx配置SSL证书

问题排查&#xff1a; nginx -t //检查配置是否正确只要返回ok就说明配置没问题。 Nginx报错Failed to restart nginx.service: Unit not found 解决方法&#xff1a; 1、在根目录下执行 vim /etc/init.d/nginx2、插入以下代码 #!/bin/sh # nginx - this script starts …

Python rich库

1. 安装 pip install rich Collecting richDownloading rich-13.6.0-py3-none-any.whl.metadata (18 kB) Collecting markdown-it-py>2.2.0 (from rich)Downloading markdown_it_py-3.0.0-py3-none-any.whl.metadata (6.9 kB) Collecting pygments<3.0.0,>2.13.0 (f…

1024程序员节,给大家送份福利

各位“爱码士”们 一年一度的1024程序员节就要到了 提前祝程序猿/媛们节日快乐 除了祝福&#xff0c;肯定少不了福利啦&#xff5e; 废话不多说&#xff0c;直接上福利 知了堂1024加油包 用心成就你的IT梦想 价值9800的程序员助梦加油包 仅需1.24元 内含1024元助学金 …

Sui成为DeFi增长的首选平台

Sui网络在过去的三个月内DeFi活动增长迅速&#xff0c;其中TVL增长了341&#xff05;&#xff0c;交易量增长了229&#xff05;。这一增长对于Sui来说是一个重要的里程碑&#xff0c;它展示了Sui为其DeFi生态中的第三方开发者提供的实用性&#xff0c;以及他们支持数百万用户进…

element-ui 以CDN 方式引入原生js开发的几个别坑 (+vue)

element-ui 以CDN 方式引入原生js开发的几个坑 最近两个月太忙了 忙的没空写文章 两个月赶出来了几个的项目 一个是雪佛兰裸眼3D的一个商品屏幕展示项目 一个是广汽云渲染的一个云看车项目 一个是奥迪中国充电桩的网页开发项目&#xff0c; 奥迪中国做个饭也是目前正在做的 不…

Linux系统编程04

进程的概念 进程&#xff08;动态&#xff09;是一个正在运行的程序&#xff08;静态&#xff09; 多道程序设计缺点&#xff1a; &#xff08;1&#xff09;缺乏隔离&#xff0c;各个程序之间可以直接访问&#xff0c;使用对方的数据 &#xff08;2&#xff09;内存使用率低&a…

正点原子嵌入式linux驱动开发——LED驱动开发

在上一篇笔记中&#xff0c;详细的讲解了字符设备驱动开发步骤&#xff0c;并且用一个虚拟的chrdevbase设备为例完成了第一个字符设备驱动的开发。本章就开始编写第一个真正的Linux字符设备驱动。在正点原子STM32MP157开发板上有一个LED灯&#xff0c;本章就学习一下如何编写Li…

探讨Unity新的收费模式:对开发者与游戏行业的影响、负面因素的解析及面对挑战的建议

本人详解 作者&#xff1a;王文峰&#xff0c;参加过 CSDN 2020年度博客之星&#xff0c;《Java王大师王天师》采购供应链共享平台人员,财务规则对账人员&#xff0c;物流门禁计量系统对接人员&#xff0c;ERP事业部人员 Unity是一款备受开发者欢迎的跨平台游戏引擎&#xff0c…

基于SSM的台球厅管理系统

末尾获取源码 开发语言&#xff1a;Java Java开发工具&#xff1a;JDK1.8 后端框架&#xff1a;SSM 前端&#xff1a;Vue 数据库&#xff1a;MySQL5.7和Navicat管理工具结合 服务器&#xff1a;Tomcat8.5 开发软件&#xff1a;IDEA / Eclipse 是否Maven项目&#xff1a;是 目录…

【再识C进阶5(上)】详细介绍C语言文件操作——文件是用于存储数据

前言 &#x1f493;作者简介&#xff1a; 加油&#xff0c;旭杏&#xff0c;目前大二&#xff0c;正在学习C&#xff0c;数据结构等&#x1f440; &#x1f493;作者主页&#xff1a;加油&#xff0c;旭杏的主页&#x1f440; ⏩本文收录在&#xff1a;再识C进阶的专栏&#x1…

成绩查询页面和自助查询方式

科技发展让我们有更多的方式来发布和查询学生成绩。今天&#xff0c;我想向大家介绍什么是成绩查询页面&#xff0c;并分享如何通过各种代码和Excel来实现让学生自助查询成绩。 成绩查询页面是一个专门用来发布和查询学生成绩的网络页面。这个页面具有发布、查询、统计成绩等功…

Vue 3使用 Iconify 作为图标库与图标离线加载的方法、 Icones 开源在线图标浏览库的使用

之前一直naive-ui搭配使用的是xicons&#xff0c;后来发现Iconify支持的图标合集更多&#xff0c;因此转而使用Iconify。 与FontAwesome不同的是&#xff0c;Iconify配合Icones相当于是一个合集&#xff0c;Iconify提供了快捷引入图标的方式&#xff0c;而Icones是一个大的图标…

二、vue基础语法

一、模板语法 1、文本渲染 使用双花括号语法插入文本 <template><div><h3>msg: {{ message }}</h3></div> </template><script> export default {data() {return {message: "输出信息"}} } </script><style s…

SAP 路径及运输功能

一、 概述 SAP的发运功能包括两部份内容&#xff0c;一是运输路径&#xff1b;二是运输功能。运输路径是运输功能的基础。 SAP 中的运输功能是后勤执行的一部分&#xff0c;用于自动计算交货成本&#xff1b;也就是说&#xff0c;SAP 可以让系统自动对销售发货的商品计算运费&…

web APIs——第一天(上)

变量声明的时候建议 const优先&#xff0c;尽量使用const 原因&#xff1a; const语义化更好很多变量我们声明的时候就知道他不会被更改了&#xff0c;那为什么不用const呢&#xff1f;实际开发中也是&#xff0c;比如react框架&#xff0c;基本const如果你有纠结的时候&…

记一次Clickhouse 复制表同步延迟排查

现象 数据从集群中一个节点写入之后&#xff0c;其他两个节点无法及时查询到数据&#xff0c;等了几分钟。因为我们ck集群是读写分离架构&#xff0c;也就是一个节点写数据&#xff0c;其他节点供读取。 排查思路 从业务得知&#xff0c;数据更新时间点为&#xff1a;11:30。…

信驰达RF-BM-2340x系列BLE蓝牙模块正式登录TI官网

信驰达作为TI中国低功耗连接技术第三方IDH&#xff0c;RF-BM-2340x系列低功耗蓝牙模块正式通过TI认证并在全球进行推广。 图 1 TI官网信驰达RF-BM-2340x系列BLE蓝牙模块 一直以来&#xff0c;信驰达重视在无线射频通信领域基础技术上的投入&#xff0c;奠定了公司在低功耗蓝牙…

Redis数据结构之SDS

前言 字符串在 Redis 中的应用场景十分广泛&#xff0c;所有的键都是字符串类型&#xff0c;值也可能是字符串类型。 比如电商系统用 Redis 缓存商品信息&#xff0c;可以把商品 ID 作为键&#xff0c;商品信息序列化为 JSON 后作为值写入&#xff1a; SET item:1001 {"…

使用python自动化操作如何使用subprocess,mac如何查看软件安装路径

使用下面这种方法实现需要配置全局的环境变量&#xff0c;很麻烦 import subprocessdef open_wps_new_doc():try:# 打开WPS应用程序subprocess.Popen(wps)# 等待一段时间&#xff0c;确保WPS完全打开time.sleep(2)# 发送快捷键组合&#xff0c;新建一个Word文档pyautogui.hotk…