在pytest测试框架里,fixture是管理测试前置与后置逻辑的核心机制。其中scope参数直接决定了fixture函数的执行次数与存活范围,合理设置能避免重复创建昂贵资源,显著缩短用例运行时间。理解function、module、session三种常见作用域的差异,是编写高效测试代码的基础。

一、scope参数的基本语义
scope用于声明fixture的作用范围,pytest据此缓存fixture实例。默认scope为function,即每个测试函数都会重新调用该fixture。当设置为module时,同一测试文件内的所有用例共享同一个fixture返回对象。session则是最高层级,整个测试会话中所有用例只初始化一次。
这种缓存逻辑意味着:如果fixture内部包含连接远程服务、读取大文件或启动容器等耗时动作,提升scope层级就能将这些动作从“每函数一次”压缩为“每模块一次”甚至“每会话一次”。但也要注意,共享状态可能带来用例间耦合,因此需要根据资源是否可变来权衡。
1.1 function作用域示例
下面代码演示默认的function级fixture,每个测试都会打印初始化信息:
import pytest
@pytest.fixture
def temp_config():
# 每个测试函数都会执行一次
print("n[setup] 初始化配置")
cfg = {"env": "test"}
yield cfg
print("n[teardown] 清理配置")
def test_a(temp_config):
assert temp_config["env"] == "test"
def test_b(temp_config):
assert temp_config["env"] == "test"
运行上述用例,setup与teardown各出现两次。对于轻量数据这无所谓,但若换成启动浏览器则成本极高。
二、module与session作用域的写法
通过给@pytest.fixture添加scope参数即可切换层级。module适合文件内共享且无需跨文件复用的资源;session适合全局唯一资源,例如测试数据库实例。
2.1 session级共享数据库连接
以下示例将连接动作放在session级fixture中,保证所有用例仅连一次库:
import pytest
@pytest.fixture(scope="session")
def db_conn():
# 模拟建立连接,整个会话只执行一次
print("n[session setup] 连接数据库")
conn = {"status": "connected"}
yield conn
print("n[session teardown] 关闭数据库")
def test_insert(db_conn):
assert db_conn["status"] == "connected"
def test_query(db_conn):
assert db_conn["status"] == "connected"
执行后可见连接日志仅打印一次。若改为scope="module",则每个测试文件会各连一次,适合多文件并行且库连接数受限的场景。
2.2 不同作用域的调用顺序
当高层级fixture依赖低层级fixture时,pytest会先实例化高层级。可利用该特性组合资源,例如session级fixture内部调用module级fixture做分库配置。但要注意,低层级不能在参数上反向依赖高层级,否则会引发作用域冲突报错。
| scope值 | 执行频率 | 适用场景 |
|---|---|---|
| function | 每函数一次 | 独立数据、无共享状态 |
| module | 每文件一次 | 文件内共用服务、配置 |
| session | 每会话一次 | 全局连接、容器、环境变量 |
三、结合autouse与终结逻辑提效
除了显式传参,还可使用autouse=True让fixture自动生效。将耗时初始化设为session级autouse,既减少重复代码,也确保效率提升无遗漏。
3.1 自动会话级准备
如下代码在会话开始时自动准备浏览器驱动,结束时退出:
import pytest
@pytest.fixture(scope="session", autouse=True)
def browser():
print("n[session] 启动浏览器")
driver = {"ready": True}
yield driver
print("n[session] 关闭浏览器")
def test_page():
assert True
该方式下,即便测试函数未声明browser,也会在会话首部启动一次。若误设为function级autouse,则每个用例都启停浏览器,效率反而下降,因此作用域选择必须匹配资源特性。
3.2 避免共享状态污染
session级fixture返回可变对象时,用例修改它会影响后续用例。建议返回不可变配置或提供重置方法。也可在module级fixture中用深拷贝隔离,兼顾复用与安全。
综上,控制fixture执行次数的核心就是scope参数。把重资源提到session或module,轻量数据留function,配合autouse与清晰终结逻辑,即可在保障测试稳定性的同时明显提升执行效率。
Pythonpytest_fixturescope修改时间:2026-08-10 01:27:31