Pytest Fixtures 完全指南
Pytest fixtures 是消除测试准备代码重复的利器。本文系统讲解 fixture 的创建、fixture 间依赖、conftest.py 共享、五种作用域、参数化 fixture 与内置 fixture 用法。
本文依据官方文档整理,未执行运行验证或性能基准。代码片段展示局部用法,业务函数、数据和环境需按项目补齐;版本与配置以所引文档为准。
直接回答:Pytest fixture 是一种声明式的测试准备机制:把重复的 setup 代码封装成可复用的函数,测试通过参数注入自动获得所需资源——消除复制粘贴、集中维护测试数据、提升可读性,按作用域复用资源;是否隔离仍取决于数据设计与清理。
为什么需要 fixture
没有 fixture 时,测试文件里往往堆满重复的"建连接、造数据、清现场"代码。fixture 把这些准备工作抽出来,由 pytest 按需注入,测试函数只留核心断言。
第一个 fixture
import pytest
@pytest.fixture
def sample_user():
return {"name": "Ada", "email": "ada@example.com"}
def test_user_email(sample_user):
assert sample_user["email"].endswith("@example.com")
测试函数把 fixture 名写进参数列表,pytest 自动调用并传入返回值。需要清理时用 yield:
@pytest.fixture
def db():
conn = connect("sqlite:///:memory:")
yield conn # 测试执行
conn.close() # 正常pytest收尾时执行;进程强杀/崩溃不保证
fixture 依赖 fixture
fixture 之间可以互相请求,构建出层次化的准备链:
@pytest.fixture
def admin_user(db):
return db.create_user(role="admin")
def test_admin_can_ban(admin_user):
assert admin_user.has_permission("ban")
conftest.py:跨文件共享
把 fixture 放进 conftest.py,同目录及子目录的所有测试文件都能直接使用,无需 import。目录可以嵌套多层 conftest,就近覆盖——这是 pytest 项目组织测试基础设施的标准做法。
四种作用域
| 作用域 | 生命周期 | 典型用途 |
|---|---|---|
function(默认) |
每条用例重建 | 需要干净状态的资源 |
class |
每个测试类一次 | 类内共享的重资源 |
module |
每个文件一次 | 只读配置、种子数据 |
package |
包内测试结束后清理 | 包级共享资源 |
session |
每个测试进程的会话一次 | 数据库容器、浏览器 |
yield之前若已分配资源又报错,不会运行yield后的清理,可用try/finally或及时注册finalizer。pytest-xdist中session fixture通常每个worker各一份。重资源用长作用域提速,状态敏感的资源保持 function 级保隔离——性能与独立性之间的取舍就藏在这一参数里。
参数化 fixture
一个 fixture 跑多份配置:
@pytest.fixture(params=["sqlite", "postgres"], scope="session")
def engine(request):
return create_engine(request.param)
def test_migration(engine):
assert run_migrations(engine)
每条使用它的测试会按参数各跑一遍,报告里清晰标注 test_migration[sqlite] / test_migration[postgres]。跨数据库兼容性测试这类场景因此变得极其简洁。
好用的内置 fixture
tmp_path:每条测试独立临时目录;默认会保留最近几次运行的目录用于排错,不保证测试结束立刻删除;capsys:捕获 print 输出做断言;monkeypatch:安全地打补丁(改属性、环境变量),测完自动还原;request:访问当前测试上下文,高级参数化的钥匙。
常见问题(FAQ)
Q:fixture 和 setUp/tearDown 有什么区别?
A:fixture 是声明式、可组合、带作用域的依赖注入;unittest setUp 是命令式、每条测试前执行,setUpClass 才是类级。pytest 项目统一用 fixture,表达力和复用性都更好。
Q:什么时候该把 fixture 提到 session 级?
A:创建代价高且测试不会修改其状态的资源(只读数据、容器、浏览器驱动)。一旦被某些测试"写脏",降级或加清理逻辑。
Q:fixture 报错会怎样?
A:使用它的测试标记为 ERROR 而非 FAILED,pytest 会展示 fixture 内部的完整堆栈。调试时可以先单独跑一条用例缩小范围。
官方参考
资料核对日期:2026-09-29。