进阶篇 · Advanced
lv.3 进阶
kp-035
测试实践(pytest)
1. 一句话定义
pytest 以"普通 assert + fixture 注入 + 参数化"三件套取代 unittest 的样板代码:测试函数写在 test_*.py 里即可运行,断言失败自动展开上下文。
2. 为什么重要
测试是重构的保险带、AI 时代工程协作的契约。Python 社区事实标准是 pytest(Django/FastAPI 官方教程也用它);会写"能维护的测试"是区分玩具项目与工程项目的分水岭。
3. 前置知识
4. 核心概念
python
# test_cart.py
import pytest
from cart import Cart, OutOfStock
@pytest.fixture
def cart(): # fixture:可复用的"测试前提"
return Cart()
def test_add_item(cart): # fixture 按名注入
cart.add("apple", qty=2)
assert cart.count("apple") == 2
@pytest.mark.parametrize("price, qty, total", [
(10.0, 2, 20.0),
(0.5, 4, 2.0),
])
def test_total(cart, price, qty, total): # 参数化:一函数多用例
cart.add("x", price=price, qty=qty)
assert cart.total == total
def test_out_of_stock(cart):
with pytest.raises(OutOfStock, match="insufficient"):
cart.add("ghost", qty=99)- 发现规则:
test_*.py/*_test.py,函数test_*。 - 运行:
pytest(全量)、pytest test_cart.py::test_total(单个)、-k price(按名过滤)、-x(首败即停)。
5. 原理与机制
bash
uv add --dev pytest ruff
pytest --cov=src --cov-report=term-missing # 覆盖率(pytest-cov)- fixture 生命周期:默认函数级;
scope="module"/"session"提升复用(DB 连接等贵资源)。 - conftest.py:同目录及以下的 fixture 自动可见——共享前提的标准位置。
- mock:
mocker.patch("mymodule.http_get")替换外部依赖;原则——mock 你不拥有的东西的边界(网络/时钟/随机),不要 mock 内部实现。
6. 关键事实(模型/图示)
text
测试金字塔(心智):
多 单元测试(快、隔离、mock 边界)
中 集成测试(真文件/真小库)
少 端到端(真环境,冒烟)
命名即文档:test_<行为>_<条件>_<期望>TDD 节奏(可选方法论):红(写失败测试)→ 绿(最小实现)→ 重构。
7. 直观类比
fixture 是提前布好的舞台(道具按需递给演员);parametrize 是同一剧本的多组台词;mock 是替身演员——危险镜头(真网络/真删除)由替身上,主角逻辑(业务函数)仍然真演。
8. 实例与案例
python
# 测试时间依赖:freezeGun(或 freezegun 库)冻结时钟
from freezegun import freeze_time
@freeze_time("2025-01-01")
def test_expiry():
...9. 常见误区
- 测实现而不是行为 —— mock 内部方法、断言调用次数,一重构全红;断言对外可观察的结果。
- 没有断言的"测试" —— 只跑不验,绿得毫无意义。
- fixture 依赖链过深 —— A 依赖 B 依赖 C…;拆分、命名清晰、必要时直接在测试里构造。
- 追求 100% 覆盖率 —— 覆盖率是下限指标不是目标;核心业务逻辑覆盖 > 边角凑数。
10. 自测题
pytest.raises断言什么?match参数的作用?- fixture 放
conftest.py与放测试文件里,可见范围差异? - 什么该 mock、什么不该 mock?
参考答案
- 断言代码块抛出指定异常;match 用正则校验异常消息内容。
- conftest.py 中对同目录及所有子目录测试可见;文件内 fixture 仅本文件。
- mock 外部边界(网络、时钟、随机、文件系统副作用);不 mock 被测函数自身与纯逻辑内部协作。
11. 与其他知识点的关系
12. 延伸阅读
- pytest 官方文档:https://docs.pytest.org/
- 《Effective pytest》系列实践