200 個測試全過,上線還是出 bug
那是一個週五下午。
我剛導入 Claude Code 來寫測試,效果好得不可思議。跟它說「幫我把這個模組的測試補完整」,10 分鐘後,200 個測試就生出來了。
跑 CI,全部綠燈。覆蓋率從 45% 跳到 89%。
我想:太棒了,終於可以安心上線了。
週五傍晚部署到 staging 環境,準備週一上線。
週六早上,QA 同事做 UAT 驗收時發現問題。
她把 iPhone 和預購的 AirPods 放進購物車。結帳時,系統應該只對 iPhone 打 85 折——預購商品不參與促銷,這是寫在活動規則裡的。
但系統把兩個商品都打了折。
還好是 staging 環境,沒上到 production。但如果不是 QA 同事剛好測這個情境,這個 bug 就會直接上線。
週六下午,我回頭看那 200 個測試。
搜尋「預購」:0 個結果。 搜尋「混合」:0 個結果。 搜尋「促銷排除」:0 個結果。
200 個測試,沒有一個涵蓋「一般商品 + 預購商品混合結帳」的情況。
為什麼?
因為 AI 是根據程式碼結構去猜「什麼值得測」。它看到折扣計算函數,就測了各種折扣比例。它看到購物車邏輯,就測了新增、刪除、修改數量。
但它不知道「預購商品 + 一般商品混合」是上個月客訴最多的情境。 它不知道這個促銷規則是行銷部門臨時加的,程式碼裡只有一行不起眼的 if 判斷。 它不知道這個 bug 三個月前就出過一次,只是當時沒人發現。
那天我學到一件事:問題不是 AI 寫錯了,是 AI 測的東西根本不是該測的東西。
核心框架:What vs How
這個經驗讓我重新思考 AI 測試這件事。
後來我想通了:AI 測試要分兩層。
What(測什麼)= 人決定
- 哪些功能要測?
- 哪些場景最重要?
- 優先順序是什麼?
- 上次出包的地方要不要加強?
這些問題的答案,不在程式碼裡。
在業務邏輯裡。在客訴記錄裡。在上次 incident 的 postmortem 裡。在你的腦袋裡。
AI 看不到這些。
How(怎麼測)= AI 執行
- 測試程式怎麼寫?
- 斷言怎麼下?
- 邊界條件怎麼覆蓋?
- 測試資料怎麼準備?
這些 AI 很擅長。給它明確的目標,它能寫出比你更完整的測試。
整篇文章就在講這件事:怎麼把 What 和 How 分開。
為什麼 What 不能交給 AI?
你可能會想:AI 現在這麼強,為什麼不能讓它決定測什麼?
讓我用幾個真實場景說明。
AI 看不到你的 incident 歷史
上個月,我們的結帳流程在高併發時出現 race condition。兩個請求同時進來,庫存扣了兩次,但訂單只成立一個。
這個 incident 花了我們三天修復,寫了 15 頁的 postmortem。
這些資訊在哪裡?在 Notion 裡。在 Slack 的 #incident 頻道裡。在 on-call 工程師的記憶裡。
不在程式碼裡。
所以當我請 AI「測結帳流程」,它會測正常結帳、測庫存不足、測付款失敗。
但它不會特別測「兩個請求同時結帳」,因為它不知道這裡出過事。
AI 不知道哪些功能客戶最常用
我們的產品有 50 個 API。
但看 analytics,80% 的流量集中在 5 個 API:登入、首頁、搜尋、加入購物車、結帳。
這 5 個 API 出問題,使用者馬上感受到。其他 45 個出問題,可能一週都沒人發現。
AI 不知道這個分佈。它只會根據程式碼複雜度來判斷「這個函數很複雜,應該要多測一點」。
但複雜不代表重要。那個複雜的函數可能是一個月用一次的報表匯出。
AI 看不到程式碼以外的規格
讓我說一個具體的例子。
我們的結帳 API 有一個參數叫 apply_coupon。
AI 很認真地測了: – apply_coupon = true,有 coupon,成功折扣 ✓ – apply_coupon = false,不折扣 ✓ – apply_coupon = null,預設不折扣 ✓ – apply_coupon = "invalid",回傳錯誤 ✓
技術上完美。四個 case 都過了。
但它沒測到一件事:當 apply_coupon = true 但使用者帳戶裡沒有可用的 coupon 時,系統應該顯示「您目前沒有可用的優惠券」提示,而不是直接報 400 錯誤。
為什麼它沒測?
因為這個行為寫在三個月前的需求文件裡,標題是「優化結帳體驗」。PM 在裡面寫了一行:「當使用者嘗試使用不存在的優惠券時,顯示友善提示。」
這行字不在程式碼裡。不在 API 文件裡。不在任何 AI 能讀到的地方。
這就是我說的:AI 看得到程式碼,看不到業務 context。
為什麼 How 適合交給 AI?
說完 AI 的限制,來說它擅長的部分。
「怎麼測」這件事,AI 做得比人好。
API 測試:AI 的甜蜜點
問自己一個問題:如果 AI 只能幫你測一種東西,你會選什麼?
我的答案是 API 測試。
為什麼?因為 API 的特性讓它特別適合 AI:
輸入輸出明確。 Request 長什麼樣、response 應該長什麼樣,都寫在 API 文件裡。AI 不用猜。
邊界條件有規則。 必填欄位、格式驗證、長度限制——這些規則是明確的,AI 可以自動推導出所有邊界條件。
成功失敗判斷清楚。 200 就是成功,400 就是 client 錯誤,500 就是 server 錯誤。不存在「有點成功」這種模糊地帶。
我的經驗:API 測試交給 AI,幾乎不用改。
我會跟它說:「這是我們的 User API,測 CRUD 和權限驗證。」
它會產出: – 正常 CRUD 流程 – 必填欄位缺失 – 格式錯誤(email 格式、電話格式) – 權限不足(一般使用者試圖刪除別人的資料) – 邊界條件(名字 256 字元、超長 email)
這些 case,人寫要 2 小時。AI 寫只要 5 分鐘。而且它不會漏,因為它是系統性地推導。
單元測試:需要給 context
單元測試比 API 測試難一點。
因為 AI 需要理解「這個函數為什麼存在」。
舉個例子。我們有一個函數叫 calculateDiscount()。
AI 看到這個函數,會測: – 輸入 100,折扣 10%,輸出 90 ✓ – 輸入 0,輸出 0 ✓ – 輸入負數,丟出錯誤 ✓
技術上正確。但沒有業務意義。
因為這個函數真正的複雜度在於: – VIP 客戶有額外 5% 折扣 – 週年慶期間全館再 85 折 – 但 VIP 折扣和週年慶折扣不能疊加 – 除非是黑卡會員,可以疊加 – 但黑卡會員如果是員工,就不能用員工價又用黑卡折扣
這些規則 AI 不知道。
所以我會先跟它說:
「這個函數計算訂單折扣。有以下規則: 1. 基本折扣根據 promotionType 決定 2. VIP 會員額外 5% 3. VIP 折扣和活動折扣不疊加,取高者 4. 黑卡會員例外,可以疊加 5. 員工不能同時用員工價和會員折扣
請針對這些規則寫測試。」
給了 context,AI 產出的測試就從「技術正確」變成「業務有意義」。
E2E 測試:一定要拆分
E2E 測試是最容易踩坑的地方。
我第一次請 AI 寫 E2E 測試,跟它說:「測整個購物流程,從登入到結帳。」
它產出了一個 500 行的測試檔案。
問題來了: – 登入、瀏覽、加入購物車、結帳,全部混在一起 – 一下測正常流程,一下測庫存不足,一下又跳回正常流程測不同付款方式 – 我光是讀懂這個測試就花了 30 分鐘
更慘的是維護。兩週後,登入流程改了,這個 500 行的測試有 47 個地方要改。
後來我學乖了:拆分。
- 登入流程 →
login.spec.ts - 商品瀏覽 →
browse.spec.ts - 購物車操作 →
cart.spec.ts - 結帳流程 →
checkout.spec.ts
每個檔案請 AI 分開寫。每次只給它一個明確範圍。
結果?每個測試檔案都很清楚,維護的時候也只需要改對應的檔案。
更重要的是:邏輯差異大的場景,絕對不要放在同一批。
我曾經請 AI 同時寫「正常結帳流程」和「各種錯誤情況的處理」。
結果測試變成這樣:
1. 測試正常結帳
2. 測試信用卡過期
3. 測試正常結帳但換一種付款方式
4. 測試餘額不足
5. 測試正常結帳但用不同折扣碼
6. 測試 API timeout
正常和異常交錯,根本沒辦法讀。
現在我會分開: – 先請 AI 寫正常流程的所有變化(不同付款方式、不同折扣碼、不同運送方式) – 確認沒問題後,再請它寫異常處理(付款失敗、庫存不足、API 錯誤)
兩批測試邏輯清楚,維護也容易。
怎麼把 What 和 How 分開?
知道原則不夠,要能執行。
第一步:在請 AI 寫測試之前,先列「關鍵場景清單」
這是人的工作。
問自己: – 這個模組最重要的 3 個場景是什麼? – 上次出包的地方是哪裡? – 客戶最常用的功能是什麼? – 如果只能測 5 個東西,我會測哪 5 個?
把答案寫下來。
像這樣:
結帳模組關鍵場景:
1. 正常結帳(信用卡)- 最常見的付款方式,佔 70% 訂單
2. 一般商品 + 預購商品混合 - 上個月客訴 3 次
3. VIP 折扣計算 - 複雜規則,容易出錯
4. 高併發下的庫存扣減 - 上次 incident 的地方
5. 結帳中途 session 過期 - 使用者常反映的 UX 問題
這就是你的「What」。這個清單上的東西,一定要有測試覆蓋。
第二步:拆分工作,一次給 AI 一個明確範圍
不要說:「幫我寫結帳模組的測試。」
要說:
「幫我寫結帳 API 的測試,情境是『一般商品 + 預購商品混合結帳』。
預購商品不能參與促銷折扣。 一般商品可以用 coupon。
請測試以下情況: 1. 只有一般商品,套用 coupon 2. 只有預購商品,不能套用 coupon 3. 混合商品,只有一般商品被折扣 4. 混合商品,coupon 金額超過一般商品總額的情況」
範圍明確,AI 就不用猜。產出的測試會精準很多。
第三步:反饋要具體到 AI 不用猜
AI 寫的測試有問題,很正常。關鍵是怎麼給反饋。
壞的反饋: > 「這個測試不對,重寫。」
AI 會問:哪裡不對?它不知道,只能猜。猜錯的機率很高。
好的反饋: > 「第 23 行的斷言有問題。預期的折扣金額應該是 85,不是 80。 > 因為 VIP 折扣是 15%,100 × 0.85 = 85。 > 另外請加一個 case:VIP + 週年慶折扣不能疊加,應該取較高的那個。」
具體到 AI 不用猜,它就能一次改對。
我自己的經驗:模糊反饋一次,AI 會來回 3-4 次才改對。具體反饋一次,通常第二次就對了。
怎麼驗收 AI 的驗收?
這是 Tech Lead 和 QA Lead 最常問我的問題。
「AI 說測試通過了,我敢信嗎?」
答案是:要看你驗收了什麼。
驗收的三個層次
讓我用一個例子說明。
假設 AI 幫你的結帳模組寫了 50 個測試,全部通過。
層次 1:測試有沒有跑過
CI 跑了嗎?全部綠燈嗎?有沒有 flaky test?
這是最基本的。這一層可以完全自動化,不需要人。
但「跑過」不代表「測對」。
層次 2:測試有沒有測對東西
打開那 50 個測試,看一下:
- 斷言是對的嗎?(確認金額是 100,但 100 這個數字對嗎?)
- 測的是這個函數「應該做的事」嗎?(還是只測了它「做了什麼事」?)
- 邊界條件有覆蓋嗎?(0 元、負數、超大金額)
這一層需要「懂程式」的人來 review。
我的經驗:花 15 分鐘 review AI 寫的測試,可以省 3 小時 debug。
層次 3:測試有沒有涵蓋業務關鍵路徑
回去看你的「關鍵場景清單」:
- 「一般商品 + 預購商品混合」有測到嗎?
- 「高併發庫存扣減」有測到嗎?
- 「VIP 折扣計算」有測到嗎?
就算那 50 個測試技術上都正確,如果沒有覆蓋這些關鍵場景,測試還是不及格。
這一層需要「懂業務」的人來判斷。
實際流程
我現在的做法:
- 人定義關鍵場景清單(What)
- 拆分工作,分批請 AI 寫(控制範圍)
- Review AI 寫的測試(確認 How 正確)
- 對照關鍵場景清單(確認 What 有被覆蓋)
- 跑測試(AI 執行)
- 最終判斷:能不能上線(人決定)
第 1 步和第 6 步,一定是人做決定。
中間的步驟,人機協作。
這不只是測試的問題
寫到這裡,我想說一件更大的事。
這篇文章講的是 AI 測試,但背後的問題更普遍:
什麼該讓 AI 做?什麼該自己做?邊界在哪裡?
測試只是一個案例。答案是:What 留給人,How 交給 AI。
這個框架可以套用到很多地方:
寫程式: – What = 寫什麼功能、解決什麼問題 → 人決定 – How = 怎麼實作、程式碼怎麼寫 → 可以讓 AI 幫忙
寫文件: – What = 寫給誰看、要傳達什麼訊息 → 人決定 – How = 怎麼組織段落、怎麼遣詞用句 → 可以讓 AI 幫忙
做決策: – What = 要不要做這件事、優先順序是什麼 → 人決定 – How = 怎麼執行、步驟是什麼 → 可以讓 AI 幫忙
AI 時代的核心能力,不是會用 AI。
是知道什麼時候用、什麼時候不用。
這就是判斷力。
而判斷力,只能靠你自己累積。