Files
everything-claude-code-zh/commands/tdd.md

327 lines
8.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
description: Enforce test-driven development workflow. Scaffold interfaces, generate tests FIRST, then implement minimal code to pass. Ensure 80%+ coverage.
---
# TDD 命令
此命令调用 **tdd-guide** 智能体Agent来强制执行测试驱动开发TDD方法论。
## 此命令的作用
1. **搭建接口Scaffold Interfaces** - 首先定义类型/接口
2. **先生成测试** - 编写失败的测试(红/RED
3. **编写最小化实现代码** - 只编写刚好能通过测试的代码(绿/GREEN
4. **重构Refactor** - 在保持测试通过的前提下优化代码(重构/REFACTOR
5. **验证覆盖率** - 确保测试覆盖率达到 80% 以上
## 适用场景
在以下情况下使用 `/tdd`
- 实现新功能
- 添加新的函数/组件
- 修复 Bug先编写重现该 Bug 的测试)
- 重构现有代码
- 构建核心业务逻辑
## 工作原理
tdd-guide 智能体将:
1. 为输入/输出**定义接口**
2. **编写会失败FAIL的测试**(因为代码尚未存在)
3. **运行测试**并验证它们因预期的原因而失败
4. **编写最小化实现**以使测试通过
5. **运行测试**并验证它们通过
6. 在保持测试通过的前提下**重构**代码
7. **检查覆盖率**,如果低于 80% 则添加更多测试
## TDD 循环
```
红 (RED) → 绿 (GREEN) → 重构 (REFACTOR) → 重复 (REPEAT)
红 (RED): 编写一个失败的测试
绿 (GREEN): 编写最小化代码以通过测试
重构 (REFACTOR): 改进代码,保持测试通过
重复 (REPEAT): 下一个功能/场景
```
## 使用示例
```
User: /tdd 我需要一个计算市场流动性评分market liquidity score的函数
Agent (tdd-guide):
# TDD 会话:市场流动性评分计算器
## 步骤 1定义接口 (SCAFFOLD)
```typescript
// lib/liquidity.ts
export interface MarketData {
totalVolume: number
bidAskSpread: number
activeTraders: number
lastTradeTime: Date
}
export function calculateLiquidityScore(market: MarketData): number {
// TODO: 待实现
throw new Error('Not implemented')
}
```
## 步骤 2编写失败的测试 (RED)
```typescript
// lib/liquidity.test.ts
import { calculateLiquidityScore } from './liquidity'
describe('calculateLiquidityScore', () => {
it('should return high score for liquid market', () => {
const market = {
totalVolume: 100000,
bidAskSpread: 0.01,
activeTraders: 500,
lastTradeTime: new Date()
}
const score = calculateLiquidityScore(market)
expect(score).toBeGreaterThan(80)
expect(score).toBeLessThanOrEqual(100)
})
it('should return low score for illiquid market', () => {
const market = {
totalVolume: 100,
bidAskSpread: 0.5,
activeTraders: 2,
lastTradeTime: new Date(Date.now() - 86400000) // 1 天前
}
const score = calculateLiquidityScore(market)
expect(score).toBeLessThan(30)
expect(score).toBeGreaterThanOrEqual(0)
})
it('should handle edge case: zero volume', () => {
const market = {
totalVolume: 0,
bidAskSpread: 0,
activeTraders: 0,
lastTradeTime: new Date()
}
const score = calculateLiquidityScore(market)
expect(score).toBe(0)
})
})
```
## 步骤 3运行测试 - 验证失败 (FAIL)
```bash
npm test lib/liquidity.test.ts
FAIL lib/liquidity.test.ts
✕ should return high score for liquid market (2 ms)
Error: Not implemented
1 test failed, 0 passed
```
✅ 测试如预期般失败。准备开始实现。
## 步骤 4编写最小化实现代码 (GREEN)
```typescript
// lib/liquidity.ts
export function calculateLiquidityScore(market: MarketData): number {
// 处理零交易量的边缘情况
if (market.totalVolume === 0) {
return 0
}
// 计算各项评分0-100 刻度)
const volumeScore = Math.min(market.totalVolume / 1000, 100)
const spreadScore = Math.max(100 - (market.bidAskSpread * 1000), 0)
const traderScore = Math.min(market.activeTraders / 10, 100)
// 最近活跃度奖励
const hoursSinceLastTrade = (Date.now() - market.lastTradeTime.getTime()) / (1000 * 60 * 60)
const recencyScore = Math.max(100 - (hoursSinceLastTrade * 10), 0)
// 加权平均
const score = (
volumeScore * 0.4 +
spreadScore * 0.3 +
traderScore * 0.2 +
recencyScore * 0.1
)
return Math.min(Math.max(score, 0), 100) // 限制在 0-100 之间
}
```
## 步骤 5运行测试 - 验证通过 (PASS)
```bash
npm test lib/liquidity.test.ts
PASS lib/liquidity.test.ts
✓ should return high score for liquid market (3 ms)
✓ should return low score for illiquid market (2 ms)
✓ should handle edge case: zero volume (1 ms)
3 tests passed
```
✅ 所有测试均已通过!
## 步骤 6重构 (IMPROVE)
```typescript
// lib/liquidity.ts - 使用常量重构以提高可读性
const WEIGHTS = {
VOLUME: 0.4,
SPREAD: 0.3,
TRADERS: 0.2,
RECENCY: 0.1,
} as const
const SCALE_FACTORS = {
VOLUME: 1000,
SPREAD: 1000,
TRADERS: 10,
RECENCY_PENALTY: 10,
} as const
function clamp(value: number, min: number, max: number): number {
return Math.min(Math.max(value, min), max)
}
export function calculateLiquidityScore(market: MarketData): number {
if (market.totalVolume === 0) return 0
const volumeScore = Math.min(market.totalVolume / SCALE_FACTORS.VOLUME, 100)
const spreadScore = clamp(100 - (market.bidAskSpread * SCALE_FACTORS.SPREAD), 0, 100)
const traderScore = Math.min(market.activeTraders / SCALE_FACTORS.TRADERS, 100)
const hoursSinceLastTrade = (Date.now() - market.lastTradeTime.getTime()) / (1000 * 60 * 60)
const recencyScore = clamp(100 - (hoursSinceLastTrade * SCALE_FACTORS.RECENCY_PENALTY), 0, 100)
const weightedScore =
volumeScore * WEIGHTS.VOLUME +
spreadScore * WEIGHTS.SPREAD +
traderScore * WEIGHTS.TRADERS +
recencyScore * WEIGHTS.RECENCY
return clamp(weightedScore, 0, 100)
}
```
## 步骤 7验证测试依然通过
```bash
npm test lib/liquidity.test.ts
PASS lib/liquidity.test.ts
✓ should return high score for liquid market (3 ms)
✓ should return low score for illiquid market (2 ms)
✓ should handle edge case: zero volume (1 ms)
3 tests passed
```
✅ 重构完成,测试依然通过!
## 步骤 8检查覆盖率
```bash
npm test -- --coverage lib/liquidity.test.ts
File | % Stmts | % Branch | % Funcs | % Lines
---------------|---------|----------|---------|--------
liquidity.ts | 100 | 100 | 100 | 100
Coverage: 100% ✅ (目标: 80%)
```
✅ TDD 会话完成!
```
## TDD 最佳实践
**建议做法:**
- ✅ **先**编写测试,在进行任何实现之前
- ✅ 在编写实现之前,先运行测试并验证它们**失败**
- ✅ 编写最小化代码以使测试通过
- ✅ 仅在测试通过(绿色)后才进行重构
- ✅ 涵盖边缘情况和错误场景
- ✅ 目标是 80% 以上的覆盖率(核心代码要求 100%
**避免做法:**
- ❌ 在测试之前编写实现
- ❌ 每次更改后跳过运行测试
- ❌ 一次性编写过多代码
- ❌ 忽略失败的测试
- ❌ 测试实现细节(应测试行为)
- ❌ 模拟Mock一切更推荐集成测试
## 应包含的测试类型
**单元测试** (函数级别):
- 核心流程Happy path场景
- 边缘情况空值、null、最大值
- 错误条件
- 边界值
**集成测试** (组件级别):
- API 端点
- 数据库操作
- 外部服务调用
- 带有 Hooks 的 React 组件
**E2E 测试** (使用 `/e2e` 命令):
- 关键用户流程
- 多步骤流程
- 全栈集成
## 覆盖率要求
- 所有代码**最低 80%**
- 以下内容**要求 100%**
- 财务计算
- 身份验证逻辑
- 关键安全代码
- 核心业务逻辑
## 重要提示
**强制性**必须在实现之前编写测试。TDD 循环是:
1. **红 (RED)** - 编写失败的测试
2. **绿 (GREEN)** - 实现代码以通过测试
3. **重构 (REFACTOR)** - 优化代码
切勿跳过红色RED阶段。切勿在测试之前编写代码。
## 与其他命令的集成
- 首先使用 `/plan` 了解要构建的内容
- 使用 `/tdd` 进行带测试的实现
- 如果出现构建错误,使用 `/build-and-fix`
- 使用 `/code-review` 审查实现
- 使用 `/test-coverage` 验证覆盖率
## 相关智能体Agents
此命令调用位于以下位置的 `tdd-guide` 智能体:
`~/.claude/agents/tdd-guide.md`
并可以参考位于以下位置的 `tdd-workflow` 技能Skill
`~/.claude/skills/tdd-workflow/`