mcpField
P
python-testing

python-testing

github.com/ahgraber测试与质量681 次安装2 天前更新
代码仓库

关于 python-testing

python-testing 是面向编写或审查 Python 测试的技能,侧重可观察行为、确定性单元测试和模块边界打补丁,也涵盖回归、异步生命周期及 Python 版本相关测试。

主要功能

  1. 01测试行为与契约
  2. 02保持单元测试快速且确定
  3. 03在模块边界打补丁
  4. 04使用 autospec 和 Fake
  5. 05覆盖异步清理与取消
  6. 06处理 Python 版本矩阵

适用场景

  1. 01审查与实现细节耦合的测试
  2. 02为缺陷修复添加回归测试
  3. 03排查不稳定或缓慢的测试
  4. 04测试异步清理和取消路径

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/ahgraber/skills --skill python-testing

安装后在 Claude Code 中输入/python-testing确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

references/
async-and-concurrency-testing.md
free-threaded-testing.md
multi-python-testing.md
pytest-practices.md
reliability-lifecycle-testing.md
testing-strategy.md
scripts/
test_pypi_security_audit.py
test_uv_security_audit.py

详细介绍

Python 测试

概述

测试可观察行为和契约,而不是内部实现。 保持单元测试快速、确定,并在模块边界处打补丁。

以下是常见场景的首选默认做法。 如果默认做法与项目约束冲突,请提出更合适的替代方案,说明权衡,并指出相应的补偿性控制措施。

有关语言无关的测试原则(AAA 结构、命名、测试替身分类、测试组合策略),请参阅 writing-tests。 本技能在这些基础上扩展了 Python 专属实践。

调用须知

  • 调用此技能时,请告知用户技能名称:python-testing。

适用场景

  • 编写或审查单元测试、集成测试或对可靠性敏感的测试。
  • 测试不稳定、运行缓慢,或与实现细节耦合。
  • 修复 bug 后添加回归测试。
  • 测试异步生命周期、取消或清理路径。
  • 不确定某项更改需要哪些测试覆盖。
  • 跨多个 Python 版本进行测试(nox、CI 矩阵)。
  • 验证 free-threaded Python(禁用 GIL 的构建版本)的线程安全性。

不适用场景:

  • 纯粹的数据结构或模式验证(请参阅 python-types-contracts)。
  • 生产环境中的可观测性或监控问题(请参阅 python-runtime-operations)。
  • 测试框架之外的并发设计决策(请参阅 python-concurrency-performance)。

快速参考

  • 测试可观察行为,而不是内部实现。
  • 保持单元测试快速且确定。
  • 在被测单元使用的模块边界和导入位置处打补丁。
  • 修复 bug 时添加回归测试——先编写会失败的测试,再修复。
  • 在适用时覆盖超时、重试、取消和清理。
  • 针对多个 Python 版本:使用带有 uv 后端的 nox;针对依赖矩阵进行参数化。
  • 针对 free-threaded Python:使用 pytest-run-parallel,设置 PYTHON_GIL=0,并始终设置 CI 超时。

测试替身

有关完整的 Meszaros 分类(Dummy、Fake、Stub、Spy、Mock)、经典派与 Mock 派的区别,以及一般性指导,请参阅 writing-tests → references/test-doubles.md。 Python 专属说明:

unittest.mock 的命名容易造成误解。 Mock 和 MagicMock 名称中虽有“Mock”,但默认表现为 Stub——通过 return_value 或 side_effect 配置后,它们会返回预设值,但不会自行验证调用。 只有调用 .assert_called_with() / .assert_called_once_with() 时,它们才会成为 Mock(行为验证)。 优先断言可观察输出。

使用 create_autospec() 或 autospec=True。 普通的 Mock() 会静默接受任意参数。 create_autospec(SomeClass) 会强制遵循真实方法签名——调用位置不匹配会立即导致测试失败,而不是等到生产环境中才暴露 TypeError。

在被测模块使用的导入位置打补丁,而不是原始定义位置:

# Wrong: patches the definition; callers in other modules are unaffected
patch("requests.post", ...)

# Right: patches where your module imported it
patch("mymodule.client.requests.post", ...)

如果项目已在使用 pytest-mock,可考虑使用其 mocker fixture。 它集成了 pytest 的 fixture 生命周期,会自动处理拆卸,也避免在测试函数上层层叠加装饰器。 如果 pytest-mock 尚非依赖项,unittest.mock.patch 已足够——不值得仅为使用便利而添加依赖。

优先使用 Fake,而不是深层 Mock 链。 相比多层 Mock() 链,更推荐内存实现(如 FakeRepo、以 dict 为后端的存储)。 模拟生产环境调用图的链条很脆弱,也表明 I/O 尚未与逻辑解耦。

针对变更的诊断

  • 依赖项更新:运行 uv run pytest scripts/test_uv_security_audit.py scripts/test_pypi_security_audit.py -v。 test_uv_security_audit.py 使用 uv audit 检查锁文件,优先使用;test_pypi_security_audit.py 是 pip-audit 的备用方案,可在 uv audit 可运行时自动跳过。 两者发现问题时都会发出警告(而非失败),因此请检查警告。
  • 涉及大量异步操作的生命周期变更:运行 pyleak 诊断。
  • 多 Python 版本支持变更:通过 nox 运行完整矩阵。
  • 无 GIL 兼容性:在无 GIL 构建(3.13t+)上运行 PYTHON_GIL=0 uv run --python 3.Xt pytest --parallel-threads=auto --timeout=300。

常见错误

  • 只覆盖单个写入点 — 测试了规范代码路径,却没有测试会写入相同契约断言值的其他路径(去重快捷路径、缓存快速路径、重试分支)。 每个写入点都需要单独测试。 参见 references/testing-strategy.md § 多路径和派生字段模式。
  • 缺少组合后的不变量检查 — 当 field_a == f(field_b) 是必须满足的关系,且每个字段由不同的生产者(解析器、获取器、合并步骤)写入时,阶段级测试无法证明组合后的结果仍满足该不变量。 编写测试,断言组装后输出中的这一关系。 参见 references/testing-strategy.md § 多路径和派生字段模式。
  • 模拟得过于深入 — 修补内部实现,而不是模块边界的接缝,会导致测试脆弱且与实现耦合。
  • 测试模拟本身 — 只检查模拟调用次数,却不对可观察的输出作断言,无法证明任何行为。
  • 缺少回归测试 — 修复 bug 前没有编写能复现问题的测试;bug 还会再次出现。
  • 时间/顺序不确定 — 依赖挂钟时间或 dict/set 的顺序,而不是注入时钟并显式排序。
  • 跳过清理断言 — 验证了正常路径,却从未断言失败或取消时资源已释放。
  • 缺少无 GIL CI 矩阵项 — 发布多线程代码,却没有无 GIL(带 t 后缀)的矩阵项;GIL 会掩盖竞态条件,而当无 GIL Python 成为默认版本时,这些问题就会显现。
  • 忽略 GIL 重新启用 — 导入没有 Py_mod_gil 的 C 扩展会静默地重新启用 GIL;请在导入后检查 sys._is_gil_enabled()。
  • YAML 版本浮点数 — 在 CI 矩阵 YAML 中不加引号地写入 3.10;它会被解析为 3.1,并安装错误的 Python 版本。

参考资料

  • references/testing-strategy.md
  • references/pytest-practices.md
  • references/async-and-concurrency-testing.md
  • references/reliability-lifecycle-testing.md
  • references/multi-python-testing.md
  • references/free-threaded-testing.md
  • writing-tests 技能 — 与语言无关的基础知识(AAA、命名、测试替身、测试组合策略)

评论

支持 Markdown