用途
tdd-workflow 是一个测试驱动开发(Test-Driven Development)工作流技能,用于在开发中以测试驱动设计与实现。资料明确说明:仅在用户明确要求测试优先或希望改进测试覆盖率时使用该技能;否则应通过审查代码差异(diff)及其触及的代码来进行验证。
其核心理念表述为:"Never write a line of code without a failing test."(没有失败测试,就不要写一行代码。)
主要能力:RED-GREEN-REFACTOR 循环
RED 阶段:编写失败的测试
目标:在实现之前先定义预期行为。 规则:
- 写最小的失败测试。
- 测试必须因正确的原因失败。
- 测试应清晰表达意图。
- 此时不写实现。
示例(TypeScript):
describe("Calculator", () => {
it("should add two numbers", () => {
const calc = new Calculator();
expect(calc.add(2, 3)).toBe(5);
});
});
// Run: npm test
// Result: FAIL - Calculator is not defined
// This is RED ✓
检查清单:
- [ ] 测试已编写
- [ ] 运行测试时失败
- [ ] 失败信息清晰
- [ ] 测试名称描述预期行为
GREEN 阶段:让测试通过
目标:编写让测试通过的最小代码。 规则:
- 用最简单可行的方法。
- 不添加额外功能。
- 不做优化。
- 只需让它变绿。
示例(TypeScript):
class Calculator {
add(a: number, b: number): number {
return a + b; // Simplest thing that works
}
}
// Run: npm test
// Result: PASS
// This is GREEN ✓
检查清单:
- [ ] 测试通过
- [ ] 未添加多余代码
- [ ] 实现最小化
REFACTOR 阶段:改进代码
目标:在保持测试通过的前提下清理代码。 规则:
- 只在测试通过时重构。
- 每次改动后运行测试。
- 改进设计,不改变行为。
- 小步、增量地改动。
重构示例包括:提取方法、为清晰而重命名、消除重复、改进性能、添加类型/文档。
检查清单:
- [ ] 测试仍然通过
- [ ] 代码更整洁
- [ ] 行为未改变
- [ ] 可进入下一个 RED
使用方式
开始一个新功能
1. 编写高层验收测试(可能尚不能运行)
2. 编写第一个单元测试(RED)
3. 实现最小代码(GREEN)
4. 必要时重构(REFACTOR)
5. 重复 2-4 直到功能完成
6. 验证验收测试通过
测试结构(AAA 模式)
it("should [behavior] when [condition]", () => {
// Arrange - Set up test data and dependencies
const user = createTestUser({ role: "admin" });
const service = new UserService();
// Act - Execute the code under test
const result = service.getPermissions(user);
// Assert - Verify expected outcomes
expect(result).toContain("delete");
expect(result).toContain("edit");
});
测试命名约定
[Unit]_[Scenario]_[ExpectedResult]
示例:
add_withPositiveNumbers_returnsSumlogin_withInvalidPassword_throwsAuthErrorgetUser_whenNotFound_returnsNull
测试类别
- 单元测试:隔离的单个函数/类;模拟所有依赖;快速(每个测试 <10ms);开发过程中持续运行。
- 集成测试:多个组件一起;使用真实数据库(测试实例);较慢但更真实;提交前运行。
- 端到端测试:通过 UI 覆盖整个系统;最慢、最真实;在 CI/CD 流程中运行;覆盖关键用户路径。
最佳实践
DO:
- 从最简单的情况开始
- 一次只写一个测试
- 保持测试相互独立
- 测试行为,而不是实现
- 使用描述性测试名称
- 每次变绿后提交
DON'T:
- 在测试之前写代码
- 直接测试私有方法
- 测试框架代码
- 让测试过度贴合实现
- 跳过重构阶段
需要测试的边界情况
始终测试:
- 空输入(null、undefined、[]、{}、'')
- 边界值(0、-1、MAX_INT、最小/最大日期)
- 错误情况(网络失败、无效输入)
- 权限边界
- 并发访问
- Unicode/特殊字符
测试覆盖率指南
| 指标 | 最低 | 目标 |
|---|---|---|
| Statements | 70% | 85% |
| Branches | 70% | 80% |
| Functions | 80% | 90% |
| Lines | 70% | 85% |
资料强调:覆盖率是一个指标,不是目标;100% 覆盖率并不意味着没有缺陷。
快速参考
RED → 编写失败测试(定义行为)
GREEN → 让测试通过的最小代码(让它工作)
REFACTOR → 清理(让它正确)
COMMIT → 保存进度(让它持久)
常见 TDD 错误
| 错误 | 问题 | 解决 |
|---|---|---|
| 测试实现 | 测试脆弱 | 测试行为/结果 |
| 测试过大 | 难以调试 | 更小、更聚焦的测试 |
| 共享状态 | 测试不稳定 | 隔离每个测试 |
| 测试过慢 | 测试被跳过 | 模拟外部依赖 |
| 测试显而易见的代码 | 浪费时间 | 聚焦于逻辑 |
适用场景与限制
适用:用户明确要求测试优先的工作,或需要改进测试覆盖率时;以 RED-GREEN-REFACTOR 循环规范开发流程,并借助单元、集成、端到端三类测试组织验证。
限制:资料明确说明该技能仅在用户明确要求测试时使用,否则应通过审查代码差异及其触及代码来验证。资料未提供安装命令、打包分发方式、价格或收费信息、支持的具体编程语言或框架范围、以及运行环境要求,这些暂未提供。