Files
gh-cashwu-claude-code-tdd-m…/commands/kb-red.md
2025-11-29 18:03:43 +08:00

5.1 KiB
Raw Blame History

description
description
寫下一個測試Red 階段)。一次只寫一個最小的測試,讓它失敗。

TDD Red - 寫下一個測試Red

寫下一個小測試,看它失敗。

【功能名】{{feature_name}}

Kent Beck 的 Red 階段理念

"寫一個小測試。讓它失敗。"

一次一個測試的原則

為什麼一次只寫一個?

  • 保持專注
  • 快速反饋
  • 小步前進
  • 容易回退

如何選擇下一個測試?

Kent Beck 的建議:

  1. 從 To-Do List 選(心理 To-Do不是文件

    • 腦中想到什麼測試,記下來
    • 選最簡單的開始
  2. 從上一個測試的經驗

    • 上一個測試通過了,下一步自然浮現
    • "如果這樣,那會怎樣?"
  3. 三角測量

    • 如果不確定實作,寫第二個類似的測試
    • 從多個角度逼近正確實作

寫測試的步驟

1. 更新 journey.md

### 第 N 輪 - {日期時間}

#### 🤔 想法
{為什麼要寫這個測試?從上一輪學到什麼?}

#### 🔴 Red - 寫測試
測試名稱:{測試名稱}

2. 寫測試程式碼

測試結構Given-When-Then

test('簡短描述測試意圖', () => {
  // Given - 準備
  // 【準備】:{為什麼需要這些資料?}
  const input = testData;

  // When - 執行
  // 【執行】:{測試什麼行為?}
  const result = functionUnderTest(input);

  // Then - 驗證
  // 【驗證】:{為什麼期待這個結果?}
  expect(result).toBe(expected);
});

3. 執行測試,確認失敗

npm test

必須看到失敗!

  • 如果沒失敗,測試可能有問題
  • 失敗訊息要清楚

4. 記錄失敗訊息

在 journey.md 中:

#### 失敗訊息

{實際的錯誤訊息}


#### 📝 下一步
執行 /kb-green 讓測試通過

測試大小的藝術

測試要多小?

Kent Beck 的答案:取決於你的信心

信心低(不確定)

  • 寫更小的測試
  • 更頻繁的反饋

信心高(很確定)

  • 可以寫大一點的測試
  • 跨越明顯的步驟

範例:小測試 vs 大測試

小測試(信心低時)

// 第 1 個測試:最基本的
test('5 元乘以 2 等於 10 元', () => {
  const five = new Dollar(5);
  const product = five.times(2);
  expect(product.amount).toBe(10);
});

// 第 2 個測試:檢查副作用
test('乘法不改變原物件', () => {
  const five = new Dollar(5);
  five.times(2);
  expect(five.amount).toBe(5); // 原值不變
});

大測試(信心高時)

// 直接測試完整行為
test('Dollar 乘法運算', () => {
  const five = new Dollar(5);
  const ten = five.times(2);
  expect(ten.amount).toBe(10);
  expect(five.amount).toBe(5); // 也檢查副作用
});

三角測量的時機

當你不確定實作時,用三角測量:

// 第 1 個測試
test('1 + 1 = 2', () => {
  expect(add(1, 1)).toBe(2);
});

// 最簡單的假實作
function add(a, b) {
  return 2; // 硬編碼
}

// 第 2 個測試(三角測量)
test('2 + 3 = 5', () => {
  expect(add(2, 3)).toBe(5);
});

// 現在必須寫真正的實作
function add(a, b) {
  return a + b;
}

To-Do List 技巧

Kent Beck 建議在測試程式碼中寫註解:

describe('Dollar', () => {
  // TODO: 測試加法
  // TODO: 測試負數
  // TODO: 測試相等性

  test('乘法', () => {
    // 目前的測試
  });
});

或在 journey.md 中:

## 心理 To-Do List
- [x] 基本乘法
- [ ] 乘法副作用
- [ ] 加法運算
- [ ] 負數處理

常見問題

Q: 要不要測試所有邊界情況?

Kent Beck不用一開始就全測

  • 先從明顯的案例開始
  • 邊界情況在需要時再加入
  • 讓測試自然演進

Q: 測試名稱要多詳細?

Kent Beck描述意圖,不是實作

// ✅ 好的測試名稱
test('購物車加入商品後,總價增加')

// ❌ 不好的測試名稱
test('testAddItem')

Q: 要寫測試到什麼程度?

Kent Beck寫到你有信心為止

  • 如果還不確定,再寫一個測試
  • 如果已經確定,可以跳到實作

範例Money 第一個測試

// __tests__/money.test.js

describe('Dollar', () => {
  test('乘法運算', () => {
    // 【準備】:建立 5 元的 Dollar 物件
    const five = new Dollar(5);

    // 【執行】:乘以 2
    const product = five.times(2);

    // 【驗證】:結果應該是 10 元
    expect(product.amount).toBe(10);
  });
});

執行測試:

npm test

# 結果:失敗!
# Error: Dollar is not defined

在 journey.md 記錄:

### 第 1 輪

#### 🔴 Red - 寫測試
測試名稱Dollar 乘法運算

#### 失敗訊息

Error: Dollar is not defined


#### 📝 下一步
執行 /kb-green 建立 Dollar 類別

下一步

測試寫好且失敗了?執行:

/kb-green

用最簡單的方式讓測試通過!

記住

"測試不是目的,而是思考的工具。" "失敗的測試是進步的開始。" "一次一小步,但要持續前進。"