tdd-workflow
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseTest-Driven Development (TDD) Workflow
测试驱动开发(TDD)工作流
A disciplined approach to development where tests drive design and implementation.
一种以测试驱动设计与实现的严谨开发方法。
The TDD Mantra
TDD准则
"Never write a line of code without a failing test."
"在写出失败的测试之前,绝不编写任何代码。"
The RED-GREEN-REFACTOR Cycle
RED-GREEN-REFACTOR循环
RED Phase: Write a Failing Test
RED阶段:编写失败的测试
Goal: Define the expected behavior BEFORE implementation.
Rules:
- Write the smallest test that fails
- Test must fail for the RIGHT reason
- Test should clearly express intent
- Don't write implementation yet
Example:
typescript
// RED: Test the behavior we want
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 ✓Checklist:
- Test is written
- Test fails when run
- Failure message is clear
- Test name describes expected behavior
目标:在实现代码之前,先定义预期行为。
规则:
- 编写最小规模的失败测试
- 测试必须因正确的原因失败
- 测试应清晰表达意图
- 暂不编写实现代码
示例:
typescript
// RED: Test the behavior we want
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 Phase: Make the Test Pass
GREEN阶段:让测试通过
Goal: Write the MINIMUM code to pass the test.
Rules:
- Do the simplest thing that works
- Don't add extra features
- Don't optimize
- Just make it green
Example:
typescript
// GREEN: Minimum implementation to pass
class Calculator {
add(a: number, b: number): number {
return a + b; // Simplest thing that works
}
}
// Run: npm test
// Result: PASS
// This is GREEN ✓Checklist:
- Test passes
- No extra code added
- Implementation is minimal
目标:编写最少的代码使测试通过。
规则:
- 采用最简单可行的实现方式
- 不添加额外功能
- 不进行优化
- 只需让测试变绿(通过)
示例:
typescript
// GREEN: Minimum implementation to pass
class Calculator {
add(a: number, b: number): number {
return a + b; // Simplest thing that works
}
}
// Run: npm test
// Result: PASS
// This is GREEN ✓检查清单:
- 测试已通过
- 未添加多余代码
- 实现保持最小化
REFACTOR Phase: Improve the Code
REFACTOR阶段:优化代码
Goal: Clean up while keeping tests green.
Rules:
- Only refactor with passing tests
- Run tests after each change
- Improve design, not behavior
- Small, incremental changes
Examples of refactoring:
- Extract methods
- Rename for clarity
- Remove duplication
- Improve performance
- Add types/documentation
Checklist:
- Tests still pass
- Code is cleaner
- No behavior changed
- Ready for next RED
目标:在保持测试通过的前提下清理代码。
规则:
- 仅在测试通过时进行重构
- 每次修改后运行测试
- 优化设计而非改变行为
- 采用小步、增量式的修改
重构示例:
- 提取方法
- 重命名以提升可读性
- 消除重复代码
- 提升性能
- 添加类型/文档
检查清单:
- 测试仍能通过
- 代码更加简洁
- 未改变原有行为
- 为下一个RED阶段做好准备
TDD in Practice
TDD实践指南
Starting a New Feature
启动新功能
1. Write high-level acceptance test (may not run yet)
2. Write first unit test (RED)
3. Implement minimum code (GREEN)
4. Refactor if needed (REFACTOR)
5. Repeat 2-4 until feature complete
6. Verify acceptance test passes1. 编写高层级验收测试(可能暂无法运行)
2. 编写首个单元测试(RED阶段)
3. 实现最小化代码(GREEN阶段)
4. 如有需要进行重构(REFACTOR阶段)
5. 重复步骤2-4直至功能完成
6. 验证验收测试通过Test Structure (AAA Pattern)
测试结构(AAA模式)
typescript
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");
});typescript
it("should [behavior] when [condition]", () => {
// Arrange - 设置测试数据与依赖项
const user = createTestUser({ role: "admin" });
const service = new UserService();
// Act - 执行待测试代码
const result = service.getPermissions(user);
// Assert - 验证预期结果
expect(result).toContain("delete");
expect(result).toContain("edit");
});Test Naming Convention
测试命名规范
[Unit]_[Scenario]_[ExpectedResult]Examples:
add_withPositiveNumbers_returnsSumlogin_withInvalidPassword_throwsAuthErrorgetUser_whenNotFound_returnsNull
[单元]_[场景]_[预期结果]示例:
add_withPositiveNumbers_returnsSumlogin_withInvalidPassword_throwsAuthErrorgetUser_whenNotFound_returnsNull
Test Categories
测试分类
Unit Tests
单元测试
- Single function/class in isolation
- Mock all dependencies
- Fast (<10ms per test)
- Run constantly during development
- 孤立测试单个函数/类
- 模拟所有依赖项
- 执行速度快(每个测试<10ms)
- 开发过程中持续运行
Integration Tests
集成测试
- Multiple components together
- Real database (test instance)
- Slower but more realistic
- Run before commits
- 测试多个组件协同工作
- 使用真实数据库(测试实例)
- 速度较慢但更贴近真实场景
- 提交代码前运行
End-to-End Tests
端到端测试
- Full system through UI
- Slowest, most realistic
- Run in CI/CD pipeline
- Cover critical user paths
- 通过UI测试完整系统
- 速度最慢、最贴近真实场景
- 在CI/CD流水线中运行
- 覆盖关键用户路径
TDD Best Practices
TDD最佳实践
DO:
建议:
- Start with the simplest case
- Write one test at a time
- Keep tests independent
- Test behavior, not implementation
- Use descriptive test names
- Commit after each green
- 从最简单的场景入手
- 一次编写一个测试
- 保持测试的独立性
- 测试行为而非实现细节
- 使用描述性的测试名称
- 每次测试变绿后提交代码
DON'T:
避免:
- Write code before tests
- Test private methods directly
- Test framework code
- Overfit tests to implementation
- Skip the refactor phase
- 在编写测试前先写代码
- 直接测试私有方法
- 测试框架代码
- 过度贴合实现细节编写测试
- 跳过重构阶段
Edge Cases to Test
需测试的边缘场景
Always test:
- Empty inputs (null, undefined, [], {}, '')
- Boundary values (0, -1, MAX_INT, min/max dates)
- Error conditions (network fail, invalid input)
- Permission boundaries
- Concurrent access
- Unicode/special characters
务必测试以下场景:
- 空输入(null, undefined, [], {}, '')
- 边界值(0, -1, MAX_INT, 最小/最大日期)
- 错误条件(网络故障、无效输入)
- 权限边界
- 并发访问
- Unicode/特殊字符
Test Coverage Guidelines
测试覆盖率指南
| Metric | Minimum | Target |
|---|---|---|
| Statements | 70% | 85% |
| Branches | 70% | 80% |
| Functions | 80% | 90% |
| Lines | 70% | 85% |
Coverage is a metric, not a goal. 100% coverage doesn't mean bug-free.
| 指标 | 最小值 | 目标值 |
|---|---|---|
| 语句覆盖率 | 70% | 85% |
| 分支覆盖率 | 70% | 80% |
| 函数覆盖率 | 80% | 90% |
| 行覆盖率 | 70% | 85% |
覆盖率是一个指标而非目标。100%覆盖率不代表没有bug。
Quick Reference
快速参考
RED → Write failing test (define behavior)
GREEN → Minimum code to pass (make it work)
REFACTOR → Clean up (make it right)
COMMIT → Save progress (make it permanent)RED → 编写失败的测试(定义行为)
GREEN → 编写最小代码使测试通过(让它工作)
REFACTOR → 清理代码(让它更优)
COMMIT → 保存进度(固化成果)Common TDD Mistakes
常见TDD误区
| Mistake | Problem | Solution |
|---|---|---|
| Testing implementation | Brittle tests | Test behavior/outcomes |
| Tests too large | Hard to debug | Smaller, focused tests |
| Shared state | Flaky tests | Isolate each test |
| Slow tests | Skipped tests | Mock external deps |
| Testing obvious code | Wasted time | Focus on logic |
| 误区 | 问题 | 解决方案 |
|---|---|---|
| 测试实现细节 | 测试用例脆弱 | 测试行为/输出结果 |
| 测试用例过于庞大 | 难以调试 | 编写更小、聚焦的测试用例 |
| 共享状态 | 测试用例不稳定 | 隔离每个测试用例 |
| 测试执行速度慢 | 被跳过不执行 | 模拟外部依赖项 |
| 测试显而易见的代码 | 浪费时间 | 聚焦业务逻辑测试 |