bw-mini-app/CLAUDE.md

9.0 KiB
Raw Blame History

本文档展示如何在 Claude 环境中严格遵循 测试驱动开发 (TDD) 规范。

必须使用简体中文(严格遵守)

界面(pages/components等)不写测试

依赖网络请求、文件请求等外部环境不写测试(mock替代)

🎯 TDD 核心原则 (严格遵守)

🔴 红阶段:编写失败测试

// ❌ 必须先写失败的测试
describe('Calculator', () => {
  it('should add two numbers', () => {
    const calc = new Calculator(); // 这里会失败 - 正确的!
    expect(calc.add(2, 3)).toBe(5);
  });
});

🟢 绿阶段:最小实现

// ✅ 只写刚好让测试通过的代码
export class Calculator {
  add(a: number, b: number): number {
    return a + b; // 最简实现
  }
}

🔄 重构阶段:优化代码

// ✅ 在绿灯状态下安全重构
export class Calculator {
  /**
   * 两数相加
   * @param a 第一个数
   * @param b 第二个数
   * @returns 和
   */
  add(a: number, b: number): number {
    return a + b;
  }
}

🚫 TDD 强制规则 (绝不违反)

禁止行为

  • 绝对不允许在没有测试的情况下编写生产代码
  • 绝对不允许跳过红阶段直接写实现
  • 绝对不允许在红灯状态下进行重构
  • 绝对不允许同时处理多个失败测试
  • 绝对不允许写example示例代码
  • 绝对不允许业务中写测试代码
  • 绝对不允许业务中写简化或mock代码

必须行为

  • 必须切换新分支 切换新的分支后开始新功能开发
  • 必须确认测试在功能实现前是失败的
  • 必须编写刚好让测试通过的最小代码
  • 必须在所有测试通过的绿灯状态下进行重构
  • 必须保持每个测试的独立性
  • 必须遵守单个文件代码行数不超过500行
  • 必须遵守环境依赖性测试(文件系统监控、网络连接、性能测试),使用模拟对象(Mock)替代真实环境依赖,确保测试的稳定性

🛠️ Claude TDD 工作流程

Step 1: 需求分析 → 测试设计

# 在 Claude 中的对话流程
用户: "我需要一个计算器功能"
Claude: "让我们从测试开始。首先写一个失败的测试..."

Step 2: 🔴 红阶段执行

// 1. 先创建测试文件
// src/calculator.test.ts
import { Calculator } from './calculator'; // ❌ 这会失败

describe('Calculator', () => {
  it('should add two positive numbers', () => {
    const calculator = new Calculator();
    expect(calculator.add(2, 3)).toBe(5);
  });
});
# 2. 运行测试确认失败
npm run test
# ❌ Cannot find module './calculator' - 正确的失败!

Step 3: 🟢 绿阶段执行

// 3. 创建最小实现
// src/calculator.ts
export class Calculator {
  add(a: number, b: number): number {
    return a + b; // 最简实现
  }
}
# 4. 运行测试确认通过
npm run test
# ✅ Tests: 1 passed, 1 total

Step 4: 🔄 重构阶段执行

// 5. 在绿灯状态下改进代码质量
export class Calculator {
  /**
   * 添加两个数字
   * @param a 第一个数字
   * @param b 第二个数字
   * @returns 两数之和
   */
  add(a: number, b: number): number {
    // 可以添加输入验证等
    if (typeof a !== 'number' || typeof b !== 'number') {
      throw new Error('Both arguments must be numbers');
    }
    return a + b;
  }
}
# 6. 确保重构后测试仍然通过
npm run test
# ✅ Tests: 1 passed, 1 total

📊 Claude TDD 质量检查清单

🔴 红阶段检查清单

  • 测试用例清晰表达了期望的行为
  • 测试失败的原因是功能未实现,而非测试错误
  • 测试范围适中,只验证一个具体功能点
  • 测试用例名称具有良好的可读性

🟢 绿阶段检查清单

  • 所有测试都通过
  • 实现代码尽可能简单
  • 没有实现当前测试不需要的功能
  • 代码能够正确处理测试用例的所有场景

🔄 重构阶段检查清单

  • 消除了代码重复
  • 提高了代码可读性
  • 改善了代码结构
  • 所有测试仍然通过
  • 没有改变外部行为

🎓 Claude TDD 最佳实践

1. 对话驱动的 TDD

用户: "添加减法功能"
Claude: "让我们遵循 TDD 流程:
1. 🔴 先写减法的失败测试
2. 🟢 实现最小的减法功能
3. 🔄 重构优化代码"

2. 增量式开发

// 第一个测试:基本功能
it('should subtract two positive numbers', () => {
  expect(calc.subtract(5, 3)).toBe(2);
});

// 第二个测试:边界情况
it('should handle negative results', () => {
  expect(calc.subtract(3, 5)).toBe(-2);
});

// 第三个测试:零值处理
it('should handle zero values', () => {
  expect(calc.subtract(5, 0)).toBe(5);
});

3. 测试即文档

describe('Calculator', () => {
  describe('add method', () => {
    it('should add two positive integers correctly', () => {
      // 测试名称就是功能文档
    });

    it('should handle floating point numbers with precision', () => {
      // 清晰表达预期行为
    });
  });
});

🚀 Claude TDD 命令速查

快速启动 TDD 循环

# 1. 创建测试文件
touch src/feature.test.ts

# 2. 运行测试 (红阶段)
npm run test:watch

# 3. 创建实现文件
touch src/feature.ts

# 4. 运行构建 (绿阶段后)
npm run build

# 5. 查看覆盖率
npm run test:coverage

TDD 开发节奏

# 保持快速的红-绿-重构循环
🔴 写测试 → ❌ 运行测试 → 🟢 写代码 → ✅ 运行测试 → 🔄 重构 → ✅ 运行测试

📈 成功的 TDD 指标

代码质量指标

  • 测试覆盖率: 95%+ (强制要求)
  • 测试执行时间: < 2 秒 (快速反馈)
  • 测试独立性: 100% (无依赖测试)
  • 代码重复度: 最小化

TDD 流程指标

  • 红-绿-重构循环: 严格遵循
  • 测试先行率: 100% (无例外)
  • 最小实现原则: 始终遵守
  • 重构安全性: 测试保护下进行

🎯 下一步 TDD 开发

继续使用 Claude 进行 TDD 开发时:

  1. 🔴 红阶段: 告诉 Claude 你需要什么功能,让它先写失败测试
  2. 🟢 绿阶段: 让 Claude 实现最小代码使测试通过
  3. 🔄 重构阶段: 与 Claude 一起改进代码质量
  4. 重复循环: 为每个新功能重复此过程

记住:在 Claude 环境中TDD 不仅是开发方法,更是确保代码质量和设计优雅的严格纪律! 🎉

💡 Claude TDD 实战示例

示例:添加乘法功能

🔴 红阶段:用户请求

用户: "我需要添加乘法功能"
Claude: "好的,让我们严格遵循 TDD 流程。首先写一个失败的测试:"

测试代码 (先写)

// src/calculator.test.ts
describe('Calculator', () => {
  // ... 现有测试 ...

  describe('multiply', () => {
    it('should multiply two positive numbers correctly', () => {
      const calculator = new Calculator();
      expect(calculator.multiply(3, 4)).toBe(12); // ❌ 这会失败
    });
  });
});

🟢 绿阶段:最小实现

// src/calculator.ts
export class Calculator {
  add(a: number, b: number): number {
    return a + b;
  }

  multiply(a: number, b: number): number {
    return a * b; // 最简实现
  }
}

🔄 重构阶段:优化代码

export class Calculator {
  /**
   * 两数相加
   */
  add(a: number, b: number): number {
    return a + b;
  }

  /**
   * 两数相乘
   * @param a 被乘数
   * @param b 乘数
   * @returns 乘积
   */
  multiply(a: number, b: number): number {
    return a * b;
  }
}

🔧 Claude TDD 故障排除

常见问题与解决方案

问题 1: 测试没有失败

// ❌ 错误:测试一开始就通过了
it('should return true', () => {
  expect(true).toBe(true); // 这不是有效的 TDD 测试
});

// ✅ 正确:测试应该验证具体功能
it('should validate email format', () => {
  const validator = new EmailValidator();
  expect(validator.isValid('test@example.com')).toBe(true); // 会失败,因为类不存在
});

问题 2: 实现过度复杂

// ❌ 错误:过度实现
multiply(a: number, b: number): number {
  // 不需要的复杂逻辑
  if (a === 0 || b === 0) return 0;
  if (a === 1) return b;
  if (b === 1) return a;
  // ... 更多不必要的逻辑
  return a * b;
}

// ✅ 正确:最小实现
multiply(a: number, b: number): number {
  return a * b; // 简单直接
}

问题 3: 在红灯状态下重构

# ❌ 错误流程
npm run test  # ❌ 测试失败
# 开始重构代码 <- 错误!应该先让测试通过

# ✅ 正确流程
npm run test  # ❌ 测试失败
# 写最小代码让测试通过
npm run test  # ✅ 测试通过
# 现在可以安全重构

关键文件说明

  • jest.config.js - 测试框架配置
  • tsconfig.json - TypeScript 严格模式配置
  • package.json - TDD 相关脚本命令
  • src/*.test.ts - 测试文件 (TDD 的核心)