pytest fixture 的生命周期由作用域(scope)决定,包括 function、class、module、package、session 五种,scope 越大复用越广但资源占用越久;setup 在函数体或 yield 前执行,teardown 在 yield 后或 addfinalizer 注册的回调中执行;高 scope fixture 可被低 scope 测试使用,但反之不行;需避免状态污染与资源泄漏。

pytest fixture 的生命周期取决于它的 作用域(scope),它决定了 fixture 实例被创建、复用和销毁的时机。理解 scope 是控制资源初始化、共享和清理的关键。
scope 决定 fixture 的存在周期
fixture 的 scope 有五种:function(默认)、class、module、package、session。scope 越大,fixture 复用范围越广,但生命周期越长,资源占用时间也越久。
- function:每个测试函数执行前创建,结束后立即销毁。适合轻量、隔离性强的资源,如临时文件、mock 对象。
- class:同一个测试类中的所有测试函数共享一个实例。类开始前 setup,类结束后 teardown。
- module:同一 Python 模块(.py 文件)内所有测试共享。模块导入后首次需要时创建,模块运行完毕后销毁。
- package:整个包(含子模块)内所有测试共享。包内第一个测试需要时创建,整个包运行完后销毁。
- session:整个 pytest 会话(即一次 pytest 命令执行)中只创建一次。常用于数据库连接、启动 Web 服务等开销大的全局资源。
setup 和 teardown 的执行时机
fixture 函数体本身是 setup 阶段;若使用 yield,yield 后的代码就是 teardown 阶段;若用 addfinalizer,注册的回调会在对应 scope 结束时执行。
- yield 方式更直观:yield 前为 setup,yield 后为 teardown,且保证执行(即使测试异常也会运行 teardown)。
- addfinalizer 更灵活:可多次调用,适合动态注册多个清理动作,但需确保在 fixture 函数返回前注册完成。
- teardown 总是在对应 scope 的生命周期结束时触发,不是按测试函数顺序,而是按 scope 层级自然结束。
跨 scope 依赖时的生命周期规则
高 scope 的 fixture 可被低 scope 的测试使用,但反过来不行。pytest 会自动按需创建并缓存高 scope fixture,并在整个其作用域内复用。
本文档主要讲述的是Android四种Activity的加载模式;每个Activity的状态是由它在Activity栈(是一个后进先出LIFO,包含所有正在运行Activity的队列)中的位置决定的。Activty的生命周期的也就是它所在进程的生命周期。希望本文档会给有需要的朋友带来帮助;感兴趣的朋友可以过来看看
立即学习“Python免费学习笔记(深入)”;
- 例如 module 级 fixture 被 function 级测试使用:该 fixture 在模块首次被访问时创建,之后所有同模块测试都复用它。
- 若 function 级测试同时依赖 session 和 function 级 fixture,session 级只初始化一次,function 级每次新建 —— 它们互不干扰。
- 注意:如果低 scope fixture 依赖高 scope fixture,pytest 仍按各自 scope 管理生命周期,不会提前销毁高 scope 实例。
常见误用与注意事项
生命周期管理不当容易引发状态污染、资源泄漏或并发问题(尤其在 pytest-xdist 并行运行时)。
- 避免在 function 级 fixture 中缓存可变对象(如 list、dict)并直接返回,否则多个测试可能意外共享修改。
- session 级 fixture 不要返回带内部状态的单例对象(如未重置的计数器),除非你明确控制其线程/进程安全性。
- 使用 --setup-show 查看 fixture setup/teardown 的实际执行顺序,调试生命周期问题很有效。
- 在 conftest.py 中定义高 scope fixture 时,注意其生效范围 —— session 级 fixture 放在项目根目录 conftest.py 才能覆盖全部测试。









