pytest fixture 是什么
fixture 是 pytest 的依赖注入机制:用 @pytest.fixture 声明一个可复用的前置资源(数据库连接、临时目录、测试客户端、浏览器实例),用例把夹具名写成参数即可获得注入。scope 控制生命周期(函数、类、模块、会话),生成器写法的夹具在 yield 之后执行清理——无论用例失败与否都会执行,这是资源归还可靠性的来源。夹具既可以替代传统的 setUp/tearDown,也比它更灵活:按需组合、跨文件共享、可参数化。
基本信息
| 声明方式 | @pytest.fixture 装饰器标注函数 |
|---|---|
| 注入方式 | 用例把夹具名作为形参 |
| 生命周期 | scope 取值:function、class、module、session |
| 清理机制 | yield 之后的代码在用例结束后执行 |
| 共享范围 | 同文件直接可用;跨文件放在 conftest.py |
| 内置夹具 | tmp_path、capsys、monkeypatch 等由 pytest 提供 |
典型使用场景
- 数据库连接管理:会话级建连、用例级事务回滚
- 临时文件与目录:用内置 tmp_path 生成隔离的测试工作区
- 登录态复用:会话级登录一次,函数级复制用户上下文
- 测试客户端:为接口测试准备带鉴权的 client 对象
- 参数化夹具:用 params 对同一用例跑多组环境配置
- 清理兜底:yield 后关闭连接、停止容器、回滚数据
夹具示例
夹具示例
import pytest
@pytest.fixture
def db():
conn = connect() # 建立资源
yield conn # 注入给用例使用
conn.close() # 用例结束后清理(失败也会执行)
def test_query(db):
assert db.query("select 1") == 1
@pytest.fixture(scope="session")
def api_client():
client = login() # 整个会话只登录一次
yield clientscope 取值与代价
| scope | 生命周期 | 适用与注意 |
|---|---|---|
| function | 每个用例一次(默认) | 状态隔离最好,重资源场景代价高 |
| class | 每个测试类一次 | 类内用例共享,跨类重新构建 |
| module | 每个模块一次 | 模块级数据准备,注意用例顺序耦合 |
| session | 整个会话一次 | 最省资源,但修改会串场需复位 |
session 级夹具产出的对象被用例修改会串场:共享状态要在用例间复位,或者把可变部分降到 function 级;依赖执行顺序互不得的套件在并行下必炸。
夹具间的依赖也能注入:一个夹具把另一个夹具名写成参数即形成链式构建;把公共组合沉淀成高层夹具,用例只声明它真正需要的资源。
conftest.py 按目录层级生效:子目录可以看到父目录的夹具,反向不可见;跨团队共享的夹具放在对应层级的 conftest 中,避免全项目铺开。