【superpowers基本Skill】test-driven-development 技能
在实现任何功能或bug修复时使用在编写实现代码之前技能概述test-driven-development 技能先写测试。看它失败。编写最小代码通过。核心原则:如果你没有看测试失败你就不知道它是否测试了正确的东西。违反规则的字面意思就是违反规则的精神。主要功能RED - 编写失败测试: 编写一个显示应该发生什么的最小测试验证RED: 观看它失败(强制)GREEN - 最小代码: 编写最简单的代码通过测试验证GREEN: 观看它通过(强制)REFACTOR - 清理: 删除重复改进名称提取助手触发条件在以下情况下应该调用此技能:总是:新功能Bug修复重构行为更改例外(询问你的合作伙伴):一次性原型生成的代码配置文件铁律没有失败测试就没有生产代码在测试之前写代码?删除它。重新开始。无例外:不保留它作为参考不适应它而写测试不看它删除意味着删除从测试开始实现。周期。红-绿-重构循环RED - 编写失败测试编写一个显示应该发生什么的最小测试。好:test(retries failed operations 3 times, async () {let attempts 0;const operation () {attempts;if (attempts 3) throw new Error(fail);return success;};const result await retryOperation(operation);expect(result).toBe(success);expect(attempts).toBe(3);});清晰的名称测试真实行为一件事坏:test(retry works, async () {const mock jest.fn().mockRejectedValueOnce(new Error()).mockRejectedValueOnce(new Error()).mockResolvedValueOnce(success);await retryOperation(mock);expect(mock).toHaveBeenCalledTimes(3);});模糊名称测试模拟而不是代码要求:一个行为清晰名称真实代码(除非不可避免否则没有模拟)验证RED - 观看它失败强制。从不跳过。npm test path/to/test.test.ts确认:测试失败(不是错误)失败消息是预期的失败因为功能缺失(不是拼写错误)测试通过?你在测试现有行为。修复测试。测试错误?修复错误重新运行直到它正确失败。GREEN - 最小代码编写最简单的代码通过测试。好:async function retryOperationT(fn: () PromiseT): PromiseT {for (let i 0; i 3; i) {try {return await fn();} catch (e) {if (i 2) throw e;}}throw new Error(unreachable);}刚好足够通过坏:async function retryOperationT(fn: () PromiseT,options?: {maxRetries?: number;backoff?: linear | exponential;onRetry?: (attempt: number) void;}): PromiseT {// YAGNI}过度工程不要添加功能重构其他代码或改进超出测试。验证GREEN - 观看它通过强制。npm test path/to/test.test.ts确认:测试通过其他测试仍然通过输出干净(无错误警告)测试失败?修复代码不是测试。其他测试失败?现在修复。REFACTOR - 清理仅在绿色之后:删除重复改进名称提取助手保持测试绿色。不要添加行为。重复下一个功能的下一个失败测试。好测试质量好坏最小一件事。名称中有and?拆分它。test(validates email and domain and whitespace)清晰名称描述行为test(test1)显示意图演示期望的API模糊代码应该做什么为什么顺序很重要我会在之后写测试以验证它工作代码之后写的测试立即通过。立即通过证明什么都没有:可能测试错误的东西可能测试实现不是行为可能错过你忘记的边缘情况你从未看到它捕获bug测试先强制你看测试失败证明它实际测试某些东西。我已经手动测试了所有边缘情况手动测试是临时的。你认为你测试了一切但:没有你测试的记录代码更改时无法重新运行压力下容易忘记情况它工作时我试过≠全面自动化测试是系统性的。它们每次以相同方式运行。删除X小时工作是浪费沉没成本谬误。时间已经消失。你现在选择:删除并用TDD重写(X更多小时高信心)保持并在之后添加测试(30分钟低信心可能bug)浪费是保持你无法信任的代码。没有真实测试的工作代码是技术债务。TDD是教条的务实意味着适应TDD是务实的:在提交前发现bug(比之后调试更快)防止回归(测试立即捕获中断)文档行为(测试显示如何使用代码)启用重构(自由更改测试捕获中断)务实捷径 在生产中调试 更慢。测试后达到相同目标 - 是精神不是仪式不。测试后回答这做什么?测试先回答这应该做什么?测试后被你的实现偏见。你测试你构建的不是要求的。你验证记住的边缘情况不是发现的。测试先强制边缘情况发现在实现之前。测试后验证你记住了一切(你没有)。测试后30分钟≠TDD。你获得覆盖失去证明测试工作。常见合理化借口现实太简单无法测试简单代码中断。测试需要30秒。我会在之后测试测试立即通过证明什么都没有。测试后达到相同目标测试后这做什么?测试先这应该做什么?已经手动测试临时≠系统。无记录无法重新运行。删除X小时是浪费沉没成本谬误。保持未验证代码是技术债务。保持为参考先写测试你会适应它。那是测试后。删除意味着删除。需要先探索好。丢弃探索从TDD开始。测试难 设计不清楚听测试。难测试 难使用。TDD会减慢我TDD比调试更快。务实 测试先。手动测试更快手动不证明边缘情况。你会重新测试每次更改。现有代码没有测试你在改进它。为现有代码添加测试。红旗警告 - 停止并重新开始代码在测试之前实现后测试测试立即通过不能解释为什么测试失败稍后添加测试合理化只是这一次我已经手动测试了测试后达到相同目的是精神不是仪式保持为参考或适应现有代码已经花了X小时删除是浪费TDD是教条的我是务实的这是不同的因为...所有这些意味着:删除代码。从TDD重新开始。示例: Bug修复Bug:空电子邮件被接受REDtest(rejects empty email, async () { const result await submitForm({ email: }); expect(result.error).toBe(Email required); });验证RED$ npm test FAIL: expected Email required, got undefinedGREENfunction submitForm(data: FormData) { if (!data.email?.trim()) { return { error: Email required }; } // ... }验证GREEN$ npm test PASSREFACTOR如果需要提取验证以用于多个字段。验证检查清单在标记工作完成之前:[ ] 每个新函数/方法有测试[ ] 在实现之前观看每个测试失败[ ] 每个测试因预期原因失败(功能缺失不是拼写错误)[ ] 编写最小代码通过每个测试[ ] 所有测试通过[ ] 输出干净(无错误警告)[ ] 测试使用真实代码(仅不可避免时模拟)[ ] 边缘情况和错误覆盖不能检查所有框?你跳过了TDD。重新开始。卡住时问题解决方案不知道如何测试编写期望的API。先写断言。询问你的合作伙伴。测试太复杂设计太复杂。简化接口。必须模拟一切代码太耦合。使用依赖注入。测试设置巨大提取助手。仍然复杂?简化设计。调试集成发现bug?编写重现它的失败测试。遵循TDD循环。测试证明修复并防止回归。从不没有测试修复bug。最终规则生产代码 → 测试存在并先失败否则 → 不是TDD没有你的合作伙伴许可无例外。下载地址:https://github.com/obra/superpowers/tree/main/skills/test-driven-development
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2444481.html
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!