October 29, 2026
🧪 Test Case 真係好煩?談 Test Case的愛恨情仇
如果你是一名 Developer,相信一定講過類似說話:

By 思維舞步 MindSteps
6 min read
「功能都做完啦,還要寫 Test Case?」
或者:
「寫 Code 用兩日,寫 Test Case 用三日。」
甚至:
「我自己試過沒問題,還測什麼?」
很多 Developer 第一次接觸 Test Case 時,都會覺得它十分煩。功能做好了,畫面出到了,API 回應正確,User Acceptance Test 似乎都通過了,但還要補 Test Case、補 Unit Test、補測試報告。感覺就像明明考試已經交卷,老師又叫你重新檢查一次答案。
然而,隨著工作經驗增加,你會慢慢發現:
最煩的不是寫 Test Case,而是沒有 Test Case。
因為很多 Production Bug 並不是程式寫完當天出現,而是半年後修改功能、系統整合、同事接手甚至大型 Release 時才爆出來。而 Test Case 的真正價值,正是在這些時候開始浮現。
🤔 什麼是 Test Case?
Test Case(測試案例)可以理解為:
驗證系統是否符合預期行為的一組測試情境。
它通常包含:
- 測試目的
- 前置條件
- 測試資料
- 測試步驟
- 預期結果
- 實際結果
例如登入功能。
Test Case 1
輸入:
- User ID 正確
- Password 正確
預期結果:
- 成功登入
Test Case 2
輸入:
- User ID 正確
- Password 錯誤
預期結果:
- 顯示錯誤訊息
Test Case 3
輸入:
- User ID 不存在
預期結果:
- 顯示帳號不存在
這些都是最基本的 Test Case。
🐞 為什麼需要 Test Case?
很多 Developer 都有一個錯覺:
「我自己試過啦。」
問題是:Developer 最容易忽略自己的假設。例如:
public decimal CalculatePremium(int age)
{
if (age < 18)
return 1000;
return 500;
}
完成後測試:age = 25
正常,然後覺得功能完成。但 User 未必按照你的劇本做事。
可能輸入:age = 18,age = 0,age = -1,age = 999
真正的問題往往就藏在這些地方,而 Test Case 的價值正正在於:
強迫自己從 User 的角度思考問題。
📖 實際案例
假設系統有以下需求:根據生日自動計算年齡
Developer 完成後測試:1990-01-01
正常,於是上線。數天後收到 Bug Report。
User 輸入:2000-02-29
閏年出現問題,接著再收到另一個 Bug。
User 輸入:2035-01-01
未來日期,系統又出錯。如果當初 Test Case 包含:
- 一般日期
- 閏年日期
- 當天日期
- 未來日期
- 空白日期
這些問題其實很大機會上線前已被發現。
💻 實際 Unit Test 範例
假設有以下程式:
public bool IsAdult(int age)
{
return age >= 18;
}
不少新手會寫:
[TestMethod]
public void IsAdult_Test()
{
Assert.IsTrue(IsAdult(20));
}
測試成功,於是覺得完成,但這其實只測了一種情況。較完整的寫法應該是:
[TestMethod]
public void Age20_ShouldBeAdult()
{
Assert.IsTrue(IsAdult(20));
}
[TestMethod]
public void Age18_ShouldBeAdult()
{
Assert.IsTrue(IsAdult(18));
}
[TestMethod]
public void Age17_ShouldNotBeAdult()
{
Assert.IsFalse(IsAdult(17));
}
因為:17,18,19才是真正容易發生問題的邊界值(Boundary Value)。
✅ 什麼是好 Test Case?
很多人認為:
測得愈多就是愈好。
其實未必,一個好 Test Case 最重要的標準是:
只要全部 Test Case 跑完,而且全部 Pass,我們就有信心 Deploy。
如果測試全部通過之後,你仍然覺得:
「唔知會唔會爆。」
那麼 Test Case 其實並不夠好。好的 Test Case 通常有以下特徵:
✅ 能驗證核心業務規則
例如:18歲以上才能投保
那麼:17,18,19就一定要測。
✅ 能測試邊界值
例如:最低金額 100 元,最高金額 100000 元。
應該測試:99,100,101,99999,100000,100001
✅ 能測試異常情況
例如:NULL,空白,特殊字元,負數,超大數值。
現實世界的 User 往往比 Developer 更有創意。
✅ 測試名稱容易理解
例如:Age18_ShouldBeAdult()
比起:Test01()
清晰得多。
✅ 能保護未來修改
當同事半年後修改程式時,只要跑一次測試,便知道是否破壞既有功能。這才是 Test Case 長遠最大的價值。
❌ 什麼是壞 Test Case?
同樣地,很多 Test Case 雖然數量很多,但實際價值不高。
❌ 只測 Happy Path
只測:正常情況
卻完全不測:異常情況
這是最常見問題。
❌ 測試名稱完全看不懂
例如:Test1(),Test2(),Test3()
半年後沒有人知道在測什麼。
❌ Copy & Paste 大量重覆案例
例如:20,21,22,23,24,25,全部都是同類情況。
卻忘記測:17,18,19,真正有風險的邊界值。
❌ 測試不重要的細節
例如:驗證某個 Private Method 是否被呼叫,而不是驗證業務結果是否正確。這類 Test Case 非常脆弱,一旦重構就大量失敗。
❌ 全部 Pass 仍然不敢 Deploy
這是最差的 Test Case。如果測試全部成功後,團隊仍然覺得:
「不敢 Deploy。」
代表測試根本沒有覆蓋真正重要的風險。
📊 什麼是 Code Coverage?
談到測試,就一定會接觸:Code Coverage(程式碼覆蓋率)
它用來衡量:
有多少程式碼曾經被測試執行過。
例如:總共 100 行程式
測試執行過:80 行
那麼:Coverage = 80%
不少公司會要求:
- 70%
- 80%
- 90%
作為品質目標。
⚠️ Code Coverage 高,不代表沒有 Bug
這是最常見的誤解,例如:
public bool IsAdult(int age)
{
if(age >= 18)
return true;
return false;
}
測試:
Assert.IsTrue(IsAdult(20));
Assert.IsFalse(IsAdult(10));
Coverage 可能已達100%,但如果業務要求:年齡不能為負數,而你從未測試:
IsAdult(-1);
那麼 Coverage 即使 100%,Bug 仍然存在。因此:
Code Coverage 高 ≠ 測試品質高。
Coverage 只是告訴你:
程式有沒有被執行過。
並不能告訴你:
功能有沒有被測好。
🎯 Test Case 與 Code Coverage 的分別
很多新人經常混淆兩者,其實它們回答的是不同問題。Test Case 在問:
功能是否正確?
Code Coverage 在問:
有多少程式碼被執行過?
例如登入功能,Coverage 告訴你:LoginService 被測過,但 Test Case 才告訴你:
密碼錯誤如何處理?
帳號不存在如何處理?
空白輸入如何處理?
SQL Injection 如何處理?
所以:
Coverage 是數量。
Test Case 是品質。
😅 Test Case 真是好煩,但沒有更煩
很多 Developer 都會承認:
寫 Test Case 很煩,更新 Test Case 好煩,維護 Test Case 最煩。
但如果你經歷過幾次 Production Incident,就會明白:
沒有 Test Case 更煩。
因為到時面對的可能是:
- User 投訴
- 客戶追問
- Manager 開會
- 凌晨緊急修復
- Weekend 回公司 Deploy
這些成本,通常遠遠高於開發時多花幾十分鐘寫測試,成熟團隊通常不會問:
為什麼要寫 Test Case?
而會問:
什麼地方最值得測?
🎯 結語
Test Case 的真正價值,不是交功課,也不是滿足 QA,而是降低風險。好的 Test Case 應該能驗證重要業務規則、覆蓋邊界值與異常情況,並在測試全部通過後,讓團隊有信心把系統 Deploy 到 Production。
至於 Code Coverage,它是一個有用的參考指標,但不應成為最終目標。100% Coverage 不代表沒有 Bug,而高品質測試也不一定需要 100% Coverage。
真正成熟的團隊追求的,從來不是漂亮的數字。
而是:
當所有 Test Case 通過時,我們能夠安心按下 Deploy 按鈕。
👉 一句話總結:Code Coverage 告訴你測了多少,Test Case 告訴你測得好不好;一個真正好的 Test Case,不是數量多,而是全部 Pass 後能讓團隊放心 Deploy。 🧪🚀💻📊