关于 principle-test-behavior-not-implementation
面向开发者的测试技能,用于判断测试是否验证用户可观察的行为,而非内部结构。它通过设想行为被破坏或内部实现改变,识别无法验证契约或易受重构影响的测试。
主要功能
- 01围绕可观察行为编写测试
- 02检查行为破坏后的测试结果
- 03检查仅实现变化后的测试结果
- 04用具体输入和契约确定预期
- 05避免引入新的测试运行器
适用场景
- 01合并变更前审查测试
- 02重写依赖私有辅助函数的测试
- 03为外部影响和错误编写测试
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ mdsmithaustin/ pstack --skill principle-test-behavior-not-implementation安装后在 Claude Code 中输入/principle-test-behavior-not-implementation确认已加载。
附带文件agents/openai.yaml
详细介绍
测试行为,而非实现
测试是对代码为用户做了什么的断言:这里的用户可以是调用方、最终用户或其他服务。行为是用户通过所用接口能够观察到的内容,包括返回值、错误、可读取的状态,以及代码之外系统中发生的效果,例如发送请求、写入行或发出消息。实现则是用户无法观察到的内容:私有辅助函数、内部调用顺序、中间数据,以及具体由哪个内部协作者完成工作。
针对以下两种假想修改,逐一审视每个测试:
- 破坏行为。 让代码返回错误值、跳过某个效果,或重复执行某个效果。如果测试仍然通过,它就毫无证明力。常见原因包括:断言比契约宽松、预期值由被测代码计算得出、只是重述某个常量或提示词字符串,却没有运行读取它的代码,以及断言测试自身构造的数据。
- 更改内部实现。 保持所有可观察结果不变,只调整底层代码结构。如果测试因此失败,它就被实现细节束缚了。每次重构都需要重写它,而且它仍然抓不到任何 Bug。
保留能捕获第一种修改且经得起第二种修改的测试。重写或删除其余测试。要同时做到这两点,应通过用户使用的接口驱动代码,并提供具体输入。根据需求推导预期值,而不是运行代码后得出。严格断言契约承诺的内容,不多不少。
决定测试是否合适的是契约,而不是断言的形式。如果承诺是“空购物车绝不会扣款”,那么断言支付客户端未被调用属于对行为的断言。再配一个确实会扣款的案例,证明测试能够检测到调用。模拟外部服务收到的负载属于行为,因为该服务能观察到它。调用内部辅助函数属于实现,因为用户看不到它。如果没有记录匹配,空列表就是确切答案;如果测试只需要某个结果,空列表检查就形同虚设。精确错误消息会把测试束缚在没有调用方读取的措辞上。调用方据以分支处理的错误类型才是契约。
测试可以验证不变量,而非调用,例如必须同时存在于两张表中的键,或编译时类型检查。不变量就是行为。
生产环境前提。 验收测试不能因为其设置建立了生产环境中永远不会建立的状态或顺序而通过。应执行真实的初始化流程,或证明调用方会提供该前提。真实调用方能够提供的常规夹具输入是有效的。
记法,而非运行时。 使用项目现有框架编写 Given、When、Then 或 Gherkin 风格的测试。除非项目已经运行相关工具,或用户明确要求使用 Cucumber、Gherkin 运行器或 .feature 文件,否则不要添加 Cucumber、Gherkin 运行器或 .feature 文件。要求编写 Gherkin 风格的测试,不等于提出了上述要求。