Pytest系列(31) - config.cache 使用
基础介绍
官方地址:https://docs.pytest.org/en/8.0.x/reference/reference.html#config-cache
- 在
pytest中,cache是一个非常有用的功能,它允许测试会话之间持久化状态 - 这意味着可以在一次测试运行中存储一些值,并在后续的测试运行中访问这些值
如何使用 cache
cache 对象通过 pytest 的 FixtureRequest 对象提供,通常在一个 fixture 中获取并返回它
@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 *****es 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

- pytest 的缓存机制是通过一个名为 .pytest_cache 的目录实现的,该目录位于项目的根目录下
- config.cache 对象提供了一个简单的键值存储接口,允许测试代码读取和写入缓存数据
- 一个 key 一个文件
存储和检索数据
cache 对象提供了两个主要方法:get 和 set。
get(key, default=None)方法用于检索之前存储的值。如果指定的key不存在,则返回default值。set(key, value)方法用于存储值。key应该是一个字符串,而value可以是任何可以被json标准库模块处理的对象。
# 设置缓存值
config.cache.set("key", "value")
# 获取缓存值
value = config.cache.get("key", None) # 如果键不存在,返回 None
键建议使用 / 分隔的字符串,其中第一部分通常是你的插件或应用程序的名称,以避免与其他使用 cache 的代码冲突
示例
假设有一个测试,需要从外部API获取数据,但这个操作很耗时,可以在第一次运行测试时从API获取数据,并将其存储在 cache 中。在后续的测试运行中,可以直接从 cache 中检索数据,避免重复的API调用
def test_external_api(cache):
# 尝试从缓存中获取数据
data = cache.get('external_api/data', default=None)
if data is None:
# 如果缓存中没有数据,则从API获取并存储到缓存中
data = fetch_data_from_external_api() # 假设这是一个函数来获取数据
cache.set('external_api/data', data)
# 使用数据进行测试
assert data is not None
源码解析
pytest 的缓存机制是在 _pytest/cacheprovider.py 文件中实现的
def get(self, key: str, default):
"""Return the cached value for the given key.
If no value was yet cached or the value cannot be read, the specified
default is returned.
:param key:
Must be a ``/`` separated value. Usually the first
name is the name of your plugin or your application.
:param default:
The value to return in case of a cache-miss or invalid cache value.
"""
path = self._getvaluepath(key)
try:
with path.open("r") as f:
return json.load(f)
except (ValueError, OSError):
return default
def set(self, key: str, value: object) -> None:
"""Save value for the given key.
:param key:
Must be a ``/`` separated value. Usually the first
name is the name of your plugin or your application.
:param value:
Must be of any combination of basic python types,
including nested types like lists of dictionaries.
"""
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, indent=2)
try:
f = path.open("w")
except OSError:
self.warn("cache could not write path {path}", path=path, _ispytest=True)
else:
with f:
f.write(data)
- 代码还是比较简单的,key 就是一个文件路径,不存在则创建,然后写入数据
- 这些方法最终会将数据序列化为 JSON 格式

浙公网安备 33010602011771号