7.1 KiB
7.1 KiB
description
| description |
|---|
| 讓測試通過(Green 階段)。用最簡單、甚至是"錯誤"的方式快速讓測試變綠。 |
TDD Green - 讓測試通過(Green)
用最簡單的方式讓測試通過。可以作弊、可以硬編碼、可以"錯誤"。
【功能名】:{{feature_name}}
Kent Beck 的 Green 階段理念
"快速讓測試通過,用任何手段。" "乾淨的程式碼是目標,但先讓它能動。"
三種讓測試通過的策略
Kent Beck 在書中提出的三種策略:
策略 1:Fake It(假實作)
最快速的方式:回傳常數
// 測試
test('5 * 2 = 10', () => {
expect(multiply(5, 2)).toBe(10);
});
// 假實作:直接回傳 10!
function multiply(a, b) {
return 10;
}
為什麼這樣做?
- 快速得到綠燈
- 心理上的安全感
- 用下一個測試來逼出真正的實作
策略 2:Obvious Implementation(明顯實作)
當實作很明顯時,直接寫出來
// 測試
test('加法運算', () => {
expect(add(2, 3)).toBe(5);
});
// 明顯實作:加法很簡單
function add(a, b) {
return a + b;
}
何時使用?
- 實作非常簡單
- 你很有信心
- 不需要三角測量
策略 3:Triangulation(三角測量)
用多個測試來推導正確實作
// 第 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;
}
何時使用?
- 不確定正確的實作方式
- 想從多個角度驗證
- 設計還不清楚
實作步驟
1. 選擇策略
根據你的信心程度:
信心很低 → Fake It(假實作)
信心中等 → Triangulation(三角測量)
信心很高 → Obvious Implementation(明顯實作)
2. 寫最少的程式碼
重點:最少
// 測試需要一個類別
test('Dollar 乘法', () => {
const five = new Dollar(5);
const product = five.times(2);
expect(product.amount).toBe(10);
});
// 最少的實作
class Dollar {
constructor(amount) {
this.amount = amount;
}
times(multiplier) {
return new Dollar(10); // 假實作!
}
}
3. 執行測試
npm test
看到綠燈! 🟢
4. 更新 journey.md
#### 🟢 Green - 讓測試通過
策略:{Fake It / Obvious / Triangulation}
實作說明:
{簡述你做了什麼}
程式碼位置:{檔案路徑}
測試結果:✅ 通過
#### 🤔 反思
- 這個實作明顯是假的/硬編碼的嗎?
- 需要下一個測試來逼出真正的實作嗎?
- 有沒有重複的程式碼?
#### 📝 下一步
執行 /kb-refactor 重構
Fake It 的威力
範例:Money 的演進
第 1 輪:完全假實作
test('5 * 2 = 10', () => {
const five = new Dollar(5);
expect(five.times(2).amount).toBe(10);
});
class Dollar {
constructor(amount) {
this.amount = amount;
}
times(multiplier) {
return new Dollar(10); // 硬編碼!
}
}
第 2 輪:三角測量逼出真實作
test('5 * 3 = 15', () => {
const five = new Dollar(5);
expect(five.times(3).amount).toBe(15);
});
class Dollar {
times(multiplier) {
return new Dollar(this.amount * multiplier); // 真實作!
}
}
常見的"作弊"技巧
技巧 1:回傳常數
function getWelcomeMessage() {
return "Hello, World!"; // 先硬編碼
}
技巧 2:複製測試資料
// 測試
expect(processData(input)).toEqual({
status: 'success',
count: 5
});
// 實作:直接回傳期待值
function processData(input) {
return { status: 'success', count: 5 };
}
技巧 3:最簡單的 if
// 測試 1
test('even number', () => {
expect(classify(2)).toBe('even');
});
// 假實作
function classify(n) {
if (n === 2) return 'even';
}
// 測試 2 會逼出真實作
test('another even number', () => {
expect(classify(4)).toBe('even');
});
function classify(n) {
return n % 2 === 0 ? 'even' : 'odd';
}
實作的禁忌
Kent Beck 說明在 Green 階段應該避免的:
❌ 不要過度設計
// ❌ 不要這樣(太複雜)
class Dollar {
constructor(amount, currency = 'USD') {
this.amount = amount;
this.currency = currency;
}
times(multiplier) {
// 處理多幣別、匯率轉換...
}
// 一堆還不需要的方法
add() {}
subtract() {}
convert() {}
}
// ✅ 要這樣(夠用就好)
class Dollar {
constructor(amount) {
this.amount = amount;
}
times(multiplier) {
return new Dollar(this.amount * multiplier);
}
}
❌ 不要一次實作多個測試
// 目前只有一個測試需要 times()
// 不要順便實作 add(), subtract()
// 等有測試需要時再加
❌ 不要重構
// ❌ Green 階段不要重構
// 先讓測試通過
// 重構留給下一步
// ✅ 先這樣
function calculate(x) {
return x * 2;
}
// 不要在這裡就改成
const MULTIPLIER = 2;
function calculate(x) {
return x * MULTIPLIER;
}
// 重構留給 /kb-refactor
心態:接受"醜陋"的程式碼
Kent Beck 強調的心態轉變:
階段 1:讓它能動 (Make it work) ← 現在在這裡
↓
階段 2:讓它正確 (Make it right)
↓
階段 3:讓它快速 (Make it fast)
Green 階段只追求"能動"
- 硬編碼?沒關係
- 重複?沒關係
- 醜陋?沒關係
下一步會改善
範例完整流程
測試(失敗)
test('購物車初始總價為 0', () => {
const cart = new ShoppingCart();
expect(cart.getTotal()).toBe(0);
});
實作策略選擇
信心評估:這個很簡單,用 Obvious Implementation
實作程式碼
// src/shopping-cart.js
class ShoppingCart {
getTotal() {
return 0; // 最簡單的實作
}
}
module.exports = ShoppingCart;
執行測試
npm test
# ✅ 通過!
記錄到 journey.md
#### 🟢 Green - 讓測試通過
策略:Obvious Implementation
實作說明:
建立 ShoppingCart 類別,getTotal() 回傳 0。
雖然是硬編碼,但足以通過目前的測試。
程式碼位置:src/shopping-cart.js
測試結果:✅ 通過
#### 🤔 反思
- 實作很簡單,是硬編碼
- 下一個測試:加入商品後總價應該改變
- 目前沒有明顯重複
#### 📝 下一步
執行 /kb-refactor 檢查是否需要重構
速度的重要性
Kent Beck:Green 階段要快
目標:
- 幾秒鐘到幾分鐘
- 不要花太久時間
- 快速得到綠燈的心理回饋
如果卡住:
- 寫更小的測試
- 用更假的實作
- 回退重來
下一步
測試通過了?執行:
/kb-refactor
檢查是否有重複,進行重構!
記住 Kent Beck 的話
"讓測試通過的技巧是暫時降低對程式碼品質的標準。" "骯髒的程式碼是通往乾淨程式碼的墊腳石。" "當你看到綠燈時,那是重構的信號。"