第22章 测试驱动开发
第22章 测试驱动开发
学习目标
完成本章学习后,读者应能够:
- 理解TDD方法论:掌握红-绿-重构循环与测试金字塔
- 精通pytest框架:灵活运用夹具、参数化、标记与插件
- 掌握unittest体系:使用标准库构建完整测试套件
- 实现Mock与桩代码:隔离外部依赖,编写独立可重复的单元测试
- 掌握集成测试:测试数据库、API与Web应用
- 运用性能测试:使用cProfile与pytest-benchmark进行性能分析
- 精通调试技术:使用pdb、日志与性能分析定位问题
22.1 测试驱动开发方法论
22.1.1 TDD核心循环
测试驱动开发(Test-Driven Development)遵循”红-绿-重构”循环:
1 | ┌─────────────────────────────────────────┐ |
22.1.2 测试金字塔
1 | ╱╲ |
22.1.3 TDD实践示例
以开发一个购物车系统为例:
1 | class ShoppingCart: |
22.2 pytest框架
22.2.1 pytest核心特性
1 | import pytest |
22.2.2 夹具系统
1 | import pytest |
22.2.3 参数化与标记
1 | import pytest |
pytest配置文件 pytest.ini:
1 | [pytest] |
22.3 Mock与桩代码
22.3.1 unittest.mock
1 | from unittest.mock import Mock, patch, MagicMock, call |
22.3.2 pytest-mock
1 | def test_with_mocker(mocker): |
22.4 集成测试
22.4.1 Flask应用测试
1 | import pytest |
22.4.2 数据库集成测试
1 | import pytest |
22.5 性能测试
22.5.1 pytest-benchmark
1 | def fibonacci_recursive(n: int) -> int: |
22.5.2 cProfile分析
1 | import cProfile |
22.6 调试技术
22.6.1 pdb调试器
1 | import pdb |
pdb常用命令:
| 命令 | 缩写 | 说明 |
|---|---|---|
next | n | 执行下一行(不进入函数) |
step | s | 单步执行(进入函数) |
continue | c | 继续执行到下一个断点 |
break | b | 设置断点 |
print | p | 打印变量值 |
pp | 美化打印 | |
list | l | 显示源代码 |
where | w | 显示调用栈 |
up/down | u/d | 在调用栈中上下移动 |
quit | q | 退出调试 |
22.6.2 结构化日志
1 | import logging |
22.7 测试覆盖率
22.7.1 coverage.py
1 | pip install pytest-cov |
1 | [tool.coverage.run] |
22.7.2 覆盖率实践
1 | class Calculator: |
22.8 前沿技术动态
22.8.1 现代测试工具
- pytest-asyncio:异步代码测试
- hypothesis:基于属性的测试(Property-Based Testing)
- mutmut:变异测试(Mutation Testing)
- pytest-cov:覆盖率集成
- allure-pytest:测试报告生成
22.8.2 基于属性的测试
1 | from hypothesis import given, strategies as st, settings |
22.9 本章小结
本章系统阐述了测试驱动开发的核心知识体系:
- TDD方法论:红-绿-重构循环与测试金字塔
- pytest框架:夹具系统、参数化、标记与配置
- Mock与桩代码:unittest.mock、pytest-mock与依赖隔离
- 集成测试:Flask应用测试与数据库测试
- 性能测试:pytest-benchmark与cProfile分析
- 调试技术:pdb调试器与结构化日志
- 测试覆盖率:coverage.py与覆盖率最佳实践
- 前沿工具:基于属性的测试与变异测试
22.10 习题与项目练习
基础题
使用TDD方式开发一个
Stack类,要求先写测试再写实现,覆盖push、pop、peek、is_empty、size等方法。为一个
StringCalculator类编写pytest测试,要求支持:空字符串返回0、单个数字、逗号分隔、换行分隔、自定义分隔符。使用Mock对象测试一个发送HTTP请求的函数,不实际发送网络请求。
进阶题
为Flask应用编写完整的测试套件,包含单元测试、集成测试和API端点测试,使用夹具管理测试数据库。
使用hypothesis编写基于属性的测试,验证排序算法的正确性(幂等性、稳定性、长度保持)。
实现一个日志装饰器,支持函数调用追踪、异常捕获和性能计时,编写测试验证其行为。
综合项目
电商系统测试套件:为一个电商系统编写完整的测试套件,包含:
- 用户注册/登录的单元测试
- 购物车逻辑的参数化测试
- 订单处理的集成测试(含数据库)
- 支付服务的Mock测试
- API端点的端到端测试
- 覆盖率目标 ≥ 90%
CI/CD测试流水线:配置一个完整的测试流水线,包含:
- pytest配置与conftest.py
- 单元测试/集成测试/端到端测试分层
- 覆盖率报告与阈值检查
- GitHub Actions工作流配置
- 测试报告生成(Allure)
思考题
在TDD中,如何决定测试的粒度?过度测试与测试不足各有什么问题?请结合测试金字塔理论分析。
Mock对象在测试中可能带来哪些问题?如何避免”Mock过度”导致的测试脆弱性?请讨论何时应该使用真实依赖而非Mock。
22.11 延伸阅读
22.11.1 测试理论
- 《Test Driven Development》 (Kent Beck) — TDD经典著作
- 《xUnit Test Patterns》 (Gerard Meszaros) — 单元测试模式
- 《Growing Object-Oriented Software, Guided by Tests》 — 测试驱动开发实践
22.11.2 pytest生态
- pytest官方文档 (https://docs.pytest.org/) — pytest权威指南
- pytest插件索引 (https://docs.pytest.org/en/latest/reference/plugin_list.html) — 官方插件列表
- hypothesis (https://hypothesis.readthedocs.io/) — 基于属性的测试
22.11.3 测试工具
- coverage.py (https://coverage.readthedocs.io/) — 代码覆盖率
- pytest-cov (https://pytest-cov.readthedocs.io/) — pytest覆盖率插件
- mutmut (https://mutmut.readthedocs.io/) — 变异测试
- Allure Report (https://docs.qameta.io/allure/) — 测试报告
22.11.4 调试与日志
- Python调试器 (https://docs.python.org/3/library/pdb.html) — pdb文档
- logging模块 (https://docs.python.org/3/library/logging.html) — 日志模块
- structlog (https://www.structlog.org/) — 结构化日志
下一章:第23章 版本控制与协作



