测试与质量保证
本章讲解Cython项目的测试和质量保证。高质量代码需要全面的测试覆盖和持续的性能监控。
学习路径:单元测试 → 性能测试 → 静态分析 → 文档
核心工具:
- pytest:Cython单元测试
- time/perf_counter:性能基准测试
- mypy:类型检查
- sphinx:API文档
18.1 单元测试
Section titled “18.1 单元测试”pytest配置
Section titled “pytest配置”功能说明:使用pytest测试Cython模块。
import pytestcimport mypackage.core as core
def test_sum(): """测试基本求和功能""" assert core.sum(10) == 45
def test_sum_large(): """测试大数求和""" assert core.sum(1000000) == 499999500000运行测试:
pytest tests/ -v功能说明:生成测试覆盖率报告。
# 运行测试并生成覆盖率pytest tests/ --cov=mypackage --cov-report=html
# 生成HTML报告# 打开htmlcov/index.html查看功能说明:测试边界条件和极端输入。
def test_edge_cases(): """边界测试""" # 空输入 assert core.sum(0) == 0
# 单元素 assert core.sum(1) == 0
# 负数输入 assert core.sum(-5) == -10 # -5 + -4 + -3 + -2 + -1 = -15? 实际0+...+(-1)输出示例:
>>> core.sum(0)0>>> core.sum(1)0>>> core.sum(-5)018.2 性能测试
Section titled “18.2 性能测试”基准测试框架
Section titled “基准测试框架”功能说明:测量函数执行时间。
import time
def benchmark_sum(n, iterations=100): from mypackage import sum_fast
start = time.perf_counter() for _ in range(iterations): sum_fast(n) elapsed = time.perf_counter() - start
return elapsed / iterations
# 运行for n in [100, 1000, 10000, 100000, 1000000]: t = benchmark_sum(n) print(f"n={n}: {t*1000:.3f}ms")输出示例:
n=100: 0.012msn=1000: 0.108msn=10000: 1.056msn=100000: 10.432msn=1000000: 104.521ms功能说明:对比Python和Cython版本性能。
def test_performance(): from mypackage import sum_fast import time
n = 10000000
# Cython版本 start = time.perf_counter() result_cy = sum_fast(n) time_cy = time.perf_counter() - start
# Python版本 start = time.perf_counter() result_py = sum_slow(n) time_py = time.perf_counter() - start
assert result_cy == result_py print(f"Speedup: {time_py/time_cy:.1f}x")输出示例:
Speedup: 68.5x功能说明:确保优化后结果不变。
def test_regression(): """回归测试:优化前后结果必须一致""" test_cases = [ (0, 0), (1, 0), (10, 45), (100, 4950), (1000, 499500), ]
for n, expected in test_cases: assert sum_fast(n) == expected18.3 静态分析
Section titled “18.3 静态分析”功能说明:mypy检查类型错误。
# mypy类型检查mypy mypackage/*.pyx --ignore-missing-imports输出示例:
mypackage/core.pyx:10: error: Argument 1 to "sum_fast" has incompatible type "str"; expected "int"功能说明:使用pyflakes/rruff检查代码规范。
# pyflakes检查pip install pyflakespyflakes mypackage/
# ruff检查(更快)pip install ruffruff check mypackage/功能说明:radon分析圈复杂度。
# 安装radonpip install radon
# 分析复杂度radon cc mypackage/*.pyx -a
# 复杂度等级:A(简单) -> F(复杂)18.4 文档
Section titled “18.4 文档”docstring
Section titled “docstring”功能说明:Google风格文档字符串。
cpdef double sum_squares(int n) except -1.0: """Calculate sum of squares from 0 to n-1.
Args: n: Number of terms to sum
Returns: Sum of squares 0^2 + 1^2 + ... + (n-1)^2
Raises: ValueError: If n is negative
Example: >>> sum_squares(5) 30 """ if n < 0: raise ValueError("n must be non-negative") return n * (n - 1) * (2 * n - 1) // 6功能说明:Sphinx自动生成API文档。
extensions = ["sphinx.ext.autodoc"]| 类型 | 工具 | 目的 |
|---|---|---|
| 单元测试 | pytest | 功能验证 |
| 性能测试 | time/perf_counter | 回归检测 |
| 类型检查 | mypy | 错误预防 |
| 代码规范 | ruff | 代码质量 |
| 文档 | sphinx | 可维护性 |
- 测试覆盖率至少80%
- 每次PR必须通过测试
- 性能测试防止退化(>10%退化需审查)
- docstring描述参数、返回值、异常
- 为Cython模块编写pytest测试(覆盖率>80%)
- 实现基准测试,对比Python和Cython性能
- 配置mypy类型检查,修复类型错误
- 为关键函数编写docstring文档
- 设置GitHub Actions CI/CD自动测试
- 使用radon分析代码复杂度,优化高复杂度函数