pytest中跨用例传参应使用config.cache而非全局变量,因其线程安全、兼容多进程、支持session级生命周期;推荐封装为session-scoped fixture统一管理key前缀与读写逻辑。

pytest 中不能靠全局变量传用例参数
直接在测试函数里改 global 变量,或者在 conftest.py 里定义模块级变量并试图跨用例读写,基本无效。pytest 默认每个测试函数运行在独立的上下文里,即使用了 scope="session" 的固件,也不代表全局变量能被后续用例“看到”——因为 Python 模块导入和测试收集顺序、多进程/多线程执行模式(比如 -n auto)都会让这种写法行为不可控,实际跑起来经常是空值或旧值。
常见错误现象:AttributeError: 'module' object has no attribute 'shared_data',或者第二条用例读到的是第一条用例未完成时的中间状态。
- 不要在
test_*.py文件顶层写shared = {}然后在不同def test_*里读写它 - 避免在
setup_module/teardown_module中操作模块变量来“传递”数据 - 即使加了
@pytest.mark.xfail或pytest.skip(),也不能修复全局变量失效的本质问题
用 cache 固件存取跨用例数据最稳妥
pytest-cache 已废弃,现在统一走 config.cache ——它是 pytest 内置的跨用例键值存储,底层基于文件,线程安全,支持 session 级生命周期,且兼容 -n 多进程(会自动同步)。
使用场景:A 用例生成 token/B ID,B 用例需要这个值做请求;或前置用例创建资源,后续用例复用其 ID 做清理。
def test_create_user(cache):
user_id = "usr_" + str(time.time())
cache.set("user_id", user_id, timeout=600) # 单位秒,可选
assert user_id
<p>def test_use_user_id(cache):
user_id = cache.get("user_id", None)
assert user_id is not None
assert user<em>id.startswith("usr</em>")
</p>
-
cache.set(key, value)的value必须是可序列化对象(str/int/dict等),不支持函数、类实例、文件句柄 -
cache.get(key, default)的default建议显式传,比如None,避免误判为缓存未命中 - 缓存路径默认在
.pytest_cache/v/cache/,可通过--cache-dir指定,CI 环境注意清理或挂载持久卷
用自定义 session-scoped 固件封装 cache 更清晰
把 cache 操作收拢到一个固件里,比每个测试都写 cache.get/set 更易维护,也方便加类型提示和校验逻辑。
让 macOS 自动化像说话一样简单 —— 用代码控制你的 Mac,无需学习 AppleScript 系统要求 macOS 14+ (Sonoma) Python 3.9+ 需要开启:辅助功能 + 屏幕录制权限
# conftest.py
import pytest
<p>@pytest.fixture(scope="session")
def shared_data(request):
cache = request.config.cache
class Shared:
def set(self, key, value):
cache.set(f"shared/{key}", value)
def get(self, key, default=None):
return cache.get(f"shared/{key}", default)
return Shared()
</p>
然后在测试中直接用:
def test_login(shared_data):
shared_data.set("token", "abc123")
<p>def test_api_call(shared_data):
token = shared_data.get("token")
assert token == "abc123"
</p>
- 加前缀(如
shared/)是为了避免和其他插件缓存 key 冲突 - 固件 scope 必须是
"session","module"或"function"都无法跨用例共享 - 如果固件内部做了耗时操作(比如调用 API),记得加
@pytest.fixture(scope="session", autouse=True)控制初始化时机
为什么不用 pytest-dependency 或 yield 固件?
pytest-dependency 只控制执行顺序,不提供数据传递能力;而 yield 固件(如 def my_fixture(): yield data)生命周期绑定在单个测试内,哪怕 scope 是 session,yield 后的 cleanup 也会清掉引用,无法被下一个测试读取。
性能与兼容性影响:cache 方案几乎没有运行时开销,所有操作都是本地文件读写;但要注意 Windows 下文件锁、CI 中容器重启导致缓存丢失等问题——这不是 bug,而是设计使然:cache 本质是临时存储,关键数据仍应由测试自身负责生成或从真实服务获取。
真正容易被忽略的是缓存过期和清理策略。别指望它长期保存数据,也别在 teardown 里手动删 .pytest_cache 目录——那会破坏 pytest 自身的缓存机制(比如 lastfailed)。需要重置时,用 --cache-clear 参数更安全。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!










