測試策略:該測什麼?測多少?
測試金字塔
△
/ \
/ E2E \ ← 少(慢、貴、脆弱)
/───────\
/Integration\ ← 中等
/─────────────\
/ Unit Tests \ ← 多(快、便宜、穩定)
/─────────────────\
| 類型 | 測什麼 | 速度 | 數量 |
|---|---|---|---|
| Unit | 單一方法/類別的邏輯 | 毫秒 | 多(70%) |
| Integration | 多個元件的互動(API + DB) | 秒 | 中等(20%) |
| E2E | 整個使用者流程 | 分鐘 | 少(10%) |
什麼該測、什麼不該測
✅ 該測:
- 商業邏輯(折扣計算、訂單狀態轉換)
- 邊界條件(空值、極端數字、空字串)
- 已知的 bug(寫測試防止再發生)
❌ 不該測:
- 框架本身(EF Core 的 CRUD 不需要你測)
- Getter/Setter(沒有邏輯的屬性)
- Private 方法(透過 public 方法間接測試)
- 外部 API(用 mock)
好的測試 vs 壞的測試
// ❌ 壞的測試:測試實作細節
[Test]
public void CreateOrder_ShouldCallRepository() {
_service.CreateOrder(order);
_mockRepo.Verify(r => r.Add(It.IsAny<Order>()), Times.Once);
// 如果改了內部實作(不用 Repository),測試就壞了
}
// ✅ 好的測試:測試行為結果
[Test]
public void CreateOrder_ShouldReturnOrderWithCorrectTotal() {
var result = _service.CreateOrder(items);
Assert.Equal(150m, result.Total); // 只關心結果,不關心怎麼做到的
}
Mock vs 真實依賴
用 Mock:
- 外部 API(不想真的打)
- Email 服務(不想真的寄信)
- 不可控的依賴(時間、隨機數)
用真實依賴:
- 資料庫(Integration Test 用測試 DB)
- 檔案系統(簡單的讀寫可以用真的)
原則:Unit Test 用 Mock,Integration Test 用真實依賴
測試的目的是讓你有信心改程式碼,而不是追求 100% 覆蓋率。80% 有意義的覆蓋率 > 100% 無意義的覆蓋率。