AI 寫的 Test 怎麼信任

「Claude 幫我生了 30 個 test、全綠、可以合了吧?」這是 QA 最該警覺的一句話。AI 生測試最大的風險不是它寫不出來、是它寫出一堆綠燈但根本沒測到東西的假測試、給你虛假的安全感。這篇給你一套信任邊界 + review SOP。

核心問題:綠 ≠ 有測到

flowchart LR
    A[AI 生 30 個 test] --> B[全部綠燈 ✅]
    B --> C{綠燈代表什麼?}
    C --> D["只代表:沒拋錯"]
    C -.以為.-> E["以為:有測到 bug"]
    D --> F[改壞 code<br>test 還是綠 ❌]

    style B fill:#10b981,color:#fff
    style E fill:#ef4444,color:#fff
    style F fill:#ef4444,color:#fff

傳統人寫 test、至少寫的時候腦中有「我要抓什麼」。AI 生 test 是從語法層補出一個看起來合理的 test、不保證背後有測試意圖。綠燈只證明「程式沒爆」、不證明「斷言有意義」。

7 種「綠燈但沒用」的假測試

mindmap
  root((AI 假測試))
    恆真斷言
      assert true
      expect 1 == 1
    過度 mock
      mock 掉被測對象本身
      測到的是 mock 不是 code
    驗呼叫不驗結果
      只 assert 函式被呼叫
      沒驗回傳值對不對
    幻覺預期值
      AI 自己編的 expected
      沒對規格
    只測 happy path
      0 個邊界
      0 個異常
    快照記錯誤
      snapshot 記下當前 bug
      把錯的當基準
    重複洗數量
      10 個 case 測同一條路
      覆蓋假象
# 假測試 怎麼看出來
1 恆真斷言 expect(result).toBeDefined() 永遠過、沒驗內容
2 過度 mock 連被測 function 都 mock 掉、測的是假貨
3 驗呼叫不驗結果 toHaveBeenCalled()、沒比對回傳值
4 幻覺預期值 expected 是 AI 算的、不是規格給的
5 只有 happy path 0 邊界、0 異常、0 安全
6 快照記錯誤 snapshot 把當前(含 bug)行為當基準
7 重複洗數量 10 個 case 其實測同一條路徑

信任分級 — 哪些能交給 AI

flowchart TB
    subgraph Green["🟢 可放心交給 AI"]
        G1[Boilerplate / setup]
        G2[明確規格的 happy path]
        G3[重複結構的 case]
        G4[測試命名 / 註解]
    end
    subgraph Yellow["🟡 AI 出草稿 + 人工把關"]
        Y1[邊界 / 異常覆蓋]
        Y2[斷言的預期值]
        Y3[mock 邊界該畫在哪]
    end
    subgraph Red["🔴 不可全交給 AI"]
        R1[Domain 規則 預期值]
        R2[安全相關斷言]
        R3[覆蓋是否足夠的判斷]
    end

    style Green fill:#10b981,color:#fff
    style Yellow fill:#f59e0b,color:#fff
    style Red fill:#ef4444,color:#fff

一句話:AI 可以幫你「打字」、不能幫你「決定預期值對不對」跟「覆蓋夠不夠」。預期值與覆蓋判斷、是 QA 不外包的核心。

5 步 Review SOP

flowchart LR
    S1["1、改壞測試<br>mutation 抽查"] --> S2["2、查斷言<br>驗結果非呼叫"]
    S2 --> S3["3、查預期值<br>對規格不對 AI"]
    S3 --> S4["4、查覆蓋<br>邊界/異常/安全"]
    S4 --> S5["5、查 mock<br>沒 mock 掉被測對象"]

    style S1 fill:#a855f7,color:#fff
    style S3 fill:#a855f7,color:#fff
    style S5 fill:#a855f7,color:#fff

Step 1 — 改壞 code,看 test 會不會紅

最快的真假測試判別法。故意把被測邏輯改錯一行:

# 被測 code(故意改壞)
def calc_overtime(hours):
    # return hours * 1.33   # 原本對的
    return hours * 1.0      # 故意改錯

# 如果 AI 生的 test 還是綠 → 這 test 是假的

合併前對關鍵模組做這件事、或直接上 mutation testing 工具自動跑(見下)。

Step 2 — 斷言驗「結果」不是驗「呼叫」

// ❌ AI 常生這種:只驗有被叫
expect(saveUser).toHaveBeenCalled();

// ✅ 要的是驗結果對不對
expect(result.status).toBe('active');
expect(result.email).toBe('[email protected]');

Step 3 — 預期值必須來自規格、不是 AI 腦補

這是最隱蔽的雷。AI 會「算」一個預期值填進去、看起來合理但跟業務規則不符。

Prompt 改法:
「產生 test、但 expected 值欄位先留 TODO、
 並在旁邊註明這個值該依據哪條規格決定。
 不要自己猜數字。」

預期值你親自對規格填、或 review 時逐一對。金融 / 稅務 / 健保類的數字、100% 人工核對

Step 4 — 覆蓋盤點

要求 AI 自己列覆蓋矩陣、你檢查缺口:

Prompt:
「用表格列出你產的 test 覆蓋哪些情境:
 happy / 邊界 / 異常 / 安全 / 併發。
 哪些情境『沒』被覆蓋?老實列出來。」

AI 常只給 happy path。缺的邊界 / 異常自己補。

Step 5 — 檢查 mock 邊界

// ❌ 把被測對象本身 mock 掉 → 測了個寂寞
jest.mock('./userService');  // 然後又在測 userService

// ✅ 只 mock 外部邊界(DB / API / 時間)
jest.mock('./db');

原則:只 mock external boundary、不 mock 被測主體

用 Mutation Testing 反向驗證

Review 靠肉眼會累、用 mutation testing 自動驗「測試真的會抓 bug」:

# JS/TS
npx stryker run

# Python
mutmut run

# Java
mvn org.pitest:pitest-maven:mutationCoverage
flowchart LR
    M[Mutation Tool] --> C[自動改壞 code 100 處]
    C --> T[每改一處跑一次 test]
    T --> R{test 有紅嗎?}
    R -->|紅| K["killed ✅ 好測試"]
    R -->|綠| S["survived ❌ 假測試"]

    style K fill:#10b981,color:#fff
    style S fill:#ef4444,color:#fff

Mutation score 比 coverage 誠實。Line coverage 90% 但 mutation score 30%、代表 test 跑過了 code 卻抓不到 bug — 正是 AI 假測試的典型特徵。CI 設 mutation score 門檻、AI 假測試直接被擋。

CI 守門設定

# AI 生的 test 進 CI 前的守門
gates:
  - 改壞抽查(關鍵模組 mutation testing)
  - 禁恆真斷言(lint 規則 no-tautology)
  - 覆蓋矩陣需附在 PR description
  - 預期值需標規格來源
  - 禁 mock 被測主體(review checklist)

反模式

flowchart TD
    Anti[AI 測試反模式] --> A1["全綠就合、不抽查"]
    Anti --> A2["相信 AI 算的預期值"]
    Anti --> A3["只看 coverage %、不看 mutation"]
    Anti --> A4["AI 生多少 case 就交多少"]
    Anti --> A5["mock 到測不到真實邏輯"]
    Anti --> A6["snapshot 全收、含 bug 一起記"]

    style A1 fill:#ef4444,color:#fff
    style A2 fill:#ef4444,color:#fff
    style A3 fill:#ef4444,color:#fff
    style A4 fill:#ef4444,color:#fff
    style A5 fill:#ef4444,color:#fff
    style A6 fill:#ef4444,color:#fff

給 QA 的 5 句

  1. 綠燈只代表沒爆、不代表有測到
  2. 改壞 code 不紅的 test 是假的
  3. 預期值對規格、不對 AI
  4. Mutation score 比 coverage 誠實
  5. AI 幫打字、覆蓋判斷你自己扛

最後

AI 生 test 能省一半打字時間、但省不掉 QA 的判斷。把這套 review SOP 變成 PR checklist、再加一道 mutation testing 守門、你就能放心讓 AI 加速、又不會被假測試騙。信任不是「相信 AI」、是「建立可驗證的信任流程」。

延伸: - AI 生成 Code 怎麼測 - 用 LLM 生 Test Case - QA 的 AI Workflow Daily Routine - Self-healing Tests with LLM