Python 现代开发学习笔记

(十)fixture 准备与回收测试资源

1. 从重复准备书目引出 fixture

多份测试都要三本书和一份空数据库。把准备动作集中放进 tests/conftest.py,用 @pytest.fixture 注册:

# 项目文件:quality_project/tests/conftest.py
# 每次测试都创建新书目和新数据库;yield 之后退出 Library 上下文,关闭连接。
import pytest

from bookdata.library import Library
from bookdata.models import Book


@pytest.fixture
def books():
    return [Book("Python", False, ["基础", "语法"]), Book("NumPy", True, ["数值"]), Book("Pygame")]


@pytest.fixture
def library(tmp_path, books):
    with Library(tmp_path / "library.sqlite3") as opened:
        opened.import_books(books)
        yield opened

测试函数写 def test_something(library):,pytest 就会查找同名 fixture。准备 library 又需要 tmp_path 与 books,因此先准备这两项,再打开数据库,最后把 opened 交给测试。conftest.py 由 pytest 按目录发现,测试不需要手动导入它。

tmp_path 是 pytest 自带的 fixture,提供本次测试独立的 Path 目录。这里建立的是临时数据库,不是第五章日常练习的 data/library.sqlite3。临时目录

从测试参数反推 fixture 依赖,再按准备、执行、退出的顺序运行

2. 把资源的使用范围画清楚

fixture 默认每次测试调用重新准备,同一次调用中多处请求同一个 fixture 会复用这一次的结果。参数化生成六次测试,也分别准备六次。书目在测试 A 被修改,不会留给测试 B。

yield 前是准备,交出的对象供测试使用,yield 后是收尾。断言失败后 pytest 仍会恢复已经成功到达 yield 的 fixture,本例因此离开 with Library(...) 关闭连接。准备阶段在 yield 前失败时,仍由外层 with 的退出动作关闭已打开连接。fixture 的准备与收尾

scope="module" 可以让同一模块中的测试共用一份资源,scope="session" 则跨本次运行共享。书目与可写数据库会变动,这里保留每次调用独立创建;共享不可变的大文件时,再考虑扩大范围。

笔记正文与全部题解 · Ctrl / ⌘ K