綠燈是它自己出的考卷:86,156 個 agent 測試修補中,80.2% 沒有判斷對錯的能力
本文大綱
這篇文章適合你,如果你是…
- 每天 merge agent PR 的工程師:你已經不逐行讀 diff 了——你看 CI。這篇文章要告訴你,那個綠燈現在到底代表什麼,以及它從哪一刻開始不再代表你以為的東西。
- 技術主管 / 架構師:你的 coverage 儀表板數字漂亮甚至還在上升,但生產事故沒有變少。你需要知道這兩件事為什麼可以同時成立,而且要拿得出母體夠大的證據。
- 負責訂 AI 開發規範的人:你正在寫「agent PR 必須附測試」這條規則。讀完這篇你會知道,這條規則如果只寫到這裡,會製造出比沒有規則更危險的假象。
1. 前言:問題場景(約 620 字)
Hook 開場
我有一個習慣:agent 交付的測試,我一定挑一支出來,故意把被測的那段程式碼改壞,再跑一次。
上一次我這樣做,是一個很普通的重構任務。Agent 動了大概八個檔案,順手補了 14 個測試,CI 全綠,coverage 從 71% 漲到 83%。看起來是一次教科書等級的交付。
我把一個 if amount > limit 改成 if amount >= limit——一個典型的邊界錯誤,正是人類最常犯、也最該被測試攔下來的那種。重跑,14 個測試全部通過。
我回頭去讀那些測試。它們長這樣:呼叫函式、確認沒有拋出例外、確認回傳值不是 None、確認某個 mock 被呼叫過一次。每一支都執行到了那一行——所以 coverage 算它有測。但沒有任何一支對「那一行應該產生什麼結果」表達過意見。
這不是測試寫得爛。這是測試裡根本沒有 oracle。
數據佐證
**** 這不是我運氣差。2026 年 6 月一份分析了 86,156 個 agent 撰寫的測試檔修補(涵蓋 33,596 個 agent PR、2,807 個 repo、五家主流 coding agent)的研究給出的數字是:80.2% 落在「弱或無明確 oracle 訊號」的分類。只有 11.3% 含具體值斷言,只有 5.7% 屬於多重強訊號。論文標題直接把話說完了——All Smoke, No Alarm。
而同一個 33,596 個 PR 的母體,另一份研究量到:61.38% 完全沒有任何人類 review 紀錄。
解決方案預告
把這兩個數字放在一起,你會看到一件比「AI 測試品質不好」嚴重得多的事:人已經退出迴路,把判斷權交給了 CI;而 CI 裡面那份判斷標準,正在由同一批 agent 生產,且八成沒有判斷能力。
出題的、作答的、改考卷的,是同一個模型。
文章承諾
- 一條由六份 2026 年大樣本研究串成的完整因果鏈,不是單篇論文的心得
- 為什麼 coverage 這個指標恰好在程式有 bug 時失去預測力(有相關係數)
- Agent 之間 3.7 倍的品質差距,以及這對工具選型代表什麼
- 一個成本一小時以內、今天就能跑完的診斷
讀者收穫
讀完這篇文章,你將能夠:
- 分辨你的 CI 綠燈在量「有沒有爆炸」還是「對不對」,並拿出數字證明
- 判斷什麼時候 coverage 是有效訊號、什麼時候它是噪音
- 設計一套不依賴「請大家認真 review」的驗證防線
- 用一個具體演練,把這件事變成你團隊的數字,而不是這篇文章的數字
TL;DR
- 80.2% 的 agent 測試檔修補沒有有效 oracle 訊號(86,156 個 patch);同一批 PR 中 61.38% 沒有人類 review。人退場,但接手的閘門是空的。
- LLM 為改過的程式碼寫測試時,斷言仍對齊舊行為:22,374 個生成任務中,23,977 個在新程式上失敗的測試,超過 99% 在舊程式上會通過。
- Coverage 對缺陷偵測的預測力,在無 bug 程式上 r=0.861,在有 bug 程式上全面轉弱。你需要它的唯一場合,正是它失效的場合。
- 最強模型的測試 Pass@1 98.0%,但真正能重現目標缺陷的只有 40.4%;最弱的只有 10.2%。
- Agent 之間差距 3.7 倍(強 oracle 率 18% ↔ 67%)。這不是「AI 測試」的問題,是選型與流程的問題。
2. 核心概念解釋(約 700 字)
一個測試由三段構成,而我們只量了中間那段
任何一支測試,拆開來都是三段:
setup 準備資料與環境
prefix 執行到被測的那些行
oracle 判斷這次結果是對還是錯 ← assertion 在這裡
Code coverage 這個指標,在設計上只看 prefix。 它回答「哪幾行被執行了」,從來不回答「執行完之後有沒有人檢查結果」。
這在人類寫測試的年代是一個可接受的近似。因為對人類來說,寫一個跑得到某行卻不驗證任何事的測試,是一件費力又沒有回報的事。沒人會這樣做。所以 prefix 覆蓋到了,通常意味著 oracle 也在那裡。Coverage 就這樣搭了人類職業習慣的便車,當了二十年的代理指標。
LLM 把這個便車拆了。
對模型來說,獎勵訊號是「生出一個能跑、能通過的測試」。寫出嚴格的 assertion 需要模型對「正確行為應該是什麼」有獨立判斷;而寫 assert result is not None 永遠是安全的、永遠會綠。當模型對正確行為沒有把握時,最省力且最不會被懲罰的策略,就是assert 眼前程式碼現在的輸出。
於是測試從「規格的守門員」退化成「程式碼現況的快照」。它會 100% 通過,而且會永遠通過——包括程式碼是錯的那些時候。
關鍵術語
| 術語 | 英文 | 說明 |
|---|---|---|
| 測試神諭 | test oracle | 判定執行結果對錯的邏輯,通常是 assertion |
| 冒煙測試 | smoke test | 只驗證「跑得起來、沒爆炸」的測試 |
| 突變分數 | mutation score | 對程式碼植入人工缺陷後測試抓到的比例,比 coverage 更接近抓蟲能力 |
| 殘留對齊 | residual alignment | 測試斷言對齊舊版行為而非眼前程式碼 |
| 語意改變/語意保留變更 | SAC / SPC | semantic-altering change / semantic-preserving change |
| 驗證重現率 | VRR | 生成的測試真的能重現目標缺陷的比例 |
| 過度模擬 | over-mocking | 用 mock 取代真實依賴到失去驗證意義的程度 |
一句話版本
Coverage 量的是「你的測試去過哪裡」,不是「你的測試看懂了什麼」。過去這兩者高度相關,因為去那裡的是人。
3. 證據鏈:五個環節(約 2,300 字)
我不打算用單篇論文說服你。以下五個環節各自來自獨立研究、獨立方法論、獨立樣本,但指向同一個結論。
環節一:人類已經不在 agent PR 的迴路裡
來源:Duma 等人,These Aren't the Reviews You're Looking For,arXiv:2605.02273(2026-05-04),AIDev dataset,33,596 個 agent PR。
| 指標 | agent PR | 人類作者 PR |
|---|---|---|
| 無任何人類 review 紀錄 | 61.38% | — |
| review 留言由 agent 撰寫 | 71.58% | — |
| review 中出現 agent steering 指令 | 25.92% | 1.63% |
最後一列是我認為最值得停下來看的。25.92% vs 1.63%——人類在 agent PR 上的參與方式,已經從「評估」位移成「操作」。不是讀完之後說「這裡邏輯有問題」,而是留一句「去把這個修掉」然後等它回報。
**** 這個位移有一個必然的結構後果:當人不做獨立判斷時,merge 的決策依據只剩下自動化訊號。也就是 CI。這不是誰偷懶,這是量能問題——一個人一天能認真讀的 diff 是有上限的,而 agent 的產出速率沒有這個上限。整個產業其實是在無意識中,把最終驗收權移交給了 CI。
那我們最好確認一下,CI 裡面裝的是什麼。
環節二:那道閘門,80.2% 沒有判斷對錯的能力
來源:Banik, Chowdhury, Shamim,All Smoke, No Alarm: Oracle Signals in Agent-Authored Test Code,arXiv:2606.18168v1(2026-06-17)。
樣本規模值得完整寫出來:從 711,923 個 file patch 中抽出 103,976 個測試 patch,最終分析 86,156 個 agent 測試檔修補,出自 33,596 個 agent PR、2,807 個 GitHub repo,涵蓋 OpenAI Codex、GitHub Copilot、Devin、Cursor、Claude Code 五個系統。研究背景引用的統計是:目前已有超過 932,000 個 agent PR 分布在超過 116,000 個 repo。
| Oracle 訊號分類 | 佔比 |
|---|---|
| 弱或無明確 oracle 訊號(W1–W5) | 80.2% |
| 具體值斷言(S1) | 11.3% |
| 多重強訊號 oracle(S3) | 5.7% |
| 其他 | 2.8% |
方法可信度不錯:384 個分層抽樣 patch 由兩位作者獨立標註,Cohen's κ = 0.77;自動分類器與人工標註一致率 86.7%。
這篇研究裡我認為最有商業價值的數字,不是 80.2%,是這個:
在新建的測試檔上,強 oracle 比率跨 agent 從 18%(OpenAI Codex)到 67%(Claude Code)。
3.7 倍的差距。 把「AI 寫的測試」當成一個均質物件來討論是錯的。這裡有真實的、可操作的槓桿——工具選擇、提示方式、任務切法,都會顯著改變結果。
另外一個訊號:S3 強 oracle 顯著提高 merge 機率(odds ratio = 1.28, p<0.001)。也就是說,當人真的看了,他們是看得出差別的。問題純粹在於 61.38% 的時候沒人看。
誠實標註:這份研究沒有做人類撰寫測試的對照組。所以正確的主張不是「AI 比人爛」——人類寫的 smoke test 也一大堆,這是軟體工程幾十年的老問題。正確的主張是:AI 把這個既有問題的規模與速度放大了一到兩個數量級,同時把原本唯一能發現它的人工審查抽走了。
環節三:為什麼會這樣——oracle 的來源是先驗,不是眼前的程式碼
這是整條鏈的機制核心,也是我認為最反直覺的一段。
來源:Haroon, Khan, Gulzar,Evaluating LLM-Based Test Generation Under Software Evolution,arXiv:2603.23443v1(2026-03-24)。22,374 個測試生成任務、8 個 LLM、約 3.46 億 token,資料集 Project CodeNet。
實驗設計很乾淨:先讓模型為原始程式寫測試(基準線 line coverage 79.3%、branch coverage 76.1%、通過率 100%)。然後修改程式碼,再讓模型為修改後的版本重新生成測試,看那些新測試在新程式上的表現。
| 情境 | 通過率 | line cov | branch cov |
|---|---|---|---|
| 原始程式(基準) | 100% | 79.3% | 76.1% |
| 語意改變(SAC)後 | 66.5%(−33.4pp) | 67.4% | 60.6% |
| 語意保留(SPC)後 | 78.9%(−21.0pp) | 73.7% | 69.2% |
讀懂第二列:模型看著新的程式碼寫測試,寫出來的測試在新的程式碼上有三分之一跑不過。
然後是決定性的那個數字。SAC 情境下總共生成 119,163 個測試,其中 23,977 個在修改後的程式上失敗。研究者去查這些失敗測試在原始程式上的表現:
超過 99% 在原始程式上是會通過的,而且它們確實執行到了被修改的區域。
模型被要求為新程式碼寫測試,寫出的 assertion 卻對齊舊行為。研究者稱之為 residual alignment——oracle 的來源不是它眼前那段程式碼,是它記得的那個版本。
還有一個更能說明「它對語法敏感、對語意不敏感」的證據:SPC(改了形狀但完全沒改行為)造成的測試重寫,反而比 SAC 更劇烈——測試匹配率 SPC 只有 18.1%,SAC 有 29.3%。該變的時候不變,不該變的時候大變。
這條機制其實 2024 年就有人指出過(Konstantinou 等人,arXiv:2410.21136,24 個 Java repo):LLM 與傳統測試生成工具共享同一個弱點——傾向生成捕捉實際行為而非期望行為的 oracle。差別在於,2024 年那還是一個學術觀察;2026 年它已經是 932,000 個 PR 的生產現實。
環節四:你的儀表板剛好在這裡瞎掉
如果 oracle 對齊錯了,我們現有的指標能不能察覺?
來源 A:Zhao, Zhou, Cohen(多倫多大學),arXiv:2607.22880(2026-07-24)。11 個 SOTA LLM、超過 100,000 個測試案例、Defects4J v3.0 的 318 個有缺陷的 focal method。
| 情境 | coverage 與真實缺陷偵測的相關性 |
|---|---|
| 程式無缺陷時 | 強(branch coverage r = 0.861, p < 0.0001) |
| 程式有缺陷時 | 全面轉弱 |
論文的原話是 coverage「is not informative of whether generated tests detect that bug」。
這句話值得單獨成段:Coverage 在程式是對的時候有意義,在程式可能是錯的時候沒有意義。而後者是我們需要它的唯一場合。
同一份研究還有一個對「多寫測試」派的壞消息:測試套件的大小與 mutation score 幾乎無關(Pearson r = 0.031–0.098)。多寫不等於多抓。
好消息是 mutation score 撐住了:控制測試數量後,它與真實缺陷偵測仍保有中至強相關(r = 0.533–0.833)。在 LLM 時代,mutation score 與 coverage 的差距不再是「比較嚴格 vs 比較寬鬆」,而是「還有訊號 vs 沒有訊號」。
來源 B:Wang 等人,arXiv:2506.02954(IEEE TSE 已接受),204 個受測 subject,記錄到極端案例:某些測試套件達到 100% coverage,但 mutation score 只有 4%。
來源 C(最新,2026-09-08):Hamidi 等人,arXiv:2609.09315,5 個 LLM、4 個 benchmark、6,000+ 個有缺陷的程式實例。結論:實際缺陷偵測率「remain extremely low, often near zero」,原因明確寫出來是——test oracle 無法捕捉由生成的 test prefix 所觸發的錯誤行為。而且 mutation testing 相較傳統覆蓋率準則「only marginally outperforms」;prompt-aware oracle 能改善,但整體仍有限。
一個補充發現值得警惕:LLM 造成的多數缺陷「relatively trivial to catch」,但困難的缺陷用 coverage-based 或 mutation-based 準則都難以觸發。也就是說,自動化能幫你抓的是本來就好抓的那些。
環節五:交叉驗證 —— 三份不同方法論指向同一結論
SWE-Mutation(arXiv:2605.22175v1,2026-05-21):800 個原始實例衍生 2,636 個突變變體、11 個 repo、7 個 LLM。
| 模型 / 任務 | Pass@1 | VRR(真能重現缺陷) | RDR |
|---|---|---|---|
| Claude-sonnet-4.5 / 測試生成 | 98.00% | 40.40% | 71.71% |
| Claude-sonnet-4.5 / 測試修復 | 99.80% | 59.20% | 81.15% |
| DeepSeek-V3.1 / 測試生成 | — | 10.20% | 36.15% |
98.00% vs 40.40%。 這是我認為全文最有說服力的一組並置。測試幾乎都能跑、幾乎都會綠;但當你真的植入一個缺陷,最強的模型寫的測試只有不到一半能重現它。而多語言情境還會再衰減(Claude-sonnet-4.5 VRR 從 Python 42.60% 掉到 9 語言平均 33.33%)。
Test Coverage Analysis of Agentic Pull Requests(arXiv:2607.18057v1,2026-07-20):4,882 個 agent PR(532 Java / 4,350 Python)、五個 agent。
- 50.4% 的「修改了受測程式碼」的 agent PR 完全沒有動任何測試
- 既有測試對 agent 改動行的覆蓋:Java 61.5%、Python 僅 27.0%
- 64.8% 的 Python PR,改動的行沒有被任何既有測試執行過(Java 中位數覆蓋 71.1%,Python 中位數 0%)
- Agent 有寫測試時確實有效:Java 70.5% → 86.1%(+15.6pp)、Python 24.8% → 34.5%(+9.6pp);但只有 35.9% 的 Java、22.5% 的 Python PR 出現任何覆蓋增益
而最大的破口有名字:錯誤處理。
| 構造 | Java 未覆蓋率 | Python 未覆蓋率 |
|---|---|---|
| try-catch | 86.0% | 81.0% |
| throw | 67.5% | 82.3% |
**** 這個分布一點都不隨機。錯誤處理路徑要測,需要主動製造失敗——網路斷、磁碟滿、下游回 500、輸入畸形。這需要對「什麼會出錯」有模型,而那正是 agent 最缺乏的東西:它沒有值過班。而生產環境的事故,幾乎全部發生在這些路徑上。agent 測試覆蓋最薄的地方,恰好是生產環境最常爆炸的地方。
Over-mocking(Hora, Robbes,arXiv:2602.00409,MSR '26):2025 年 1,254,878 個 commit、2,168 個 repo。
| 指標 | agent | 非 agent |
|---|---|---|
| commit 動到測試 | 23% | 13% |
| 測試 commit 加入 mock | 36% | 26% |
| mock 類型集中度 | mock 型佔 95% | mock 91% / fake 57% / spy 51% |
誠實標註:效果量小(雖然 p < 0.001),而且這份研究沒有量測 mock 是否真的造成漏抓 bug。不能推論因果。它能支撐的主張只有一個:agent 更傾向把真實互動隔離掉,作者的原話是這類測試「easier to generate automatically, but less effective at validating real interactions」。
4. 決策框架:四層防線(約 750 字)
不要從「請大家認真 review」開始。那條路已經被 61.38% 這個數字否決了。從訊號有效性開始。
決策樹
你的 agent PR 有沒有人類逐行讀過?
├─ 有(真的有,不是按 approve)
│ └─ 你的瓶頸是量能,不是訊號。跳到第 3 層,優化你 review 的順序。
└─ 沒有 / 不確定
└─ CI 是你唯一的閘門。問下一題:
你的 CI 裡有沒有任何一項在量「抓蟲能力」而非「執行路徑」?
├─ 沒有(只有 coverage / lint / build)
│ └─ 【第 1 層】立刻做手動 mutation 演練,先取得你自己的數字
└─ 有(有 mutation testing 或等價機制)
└─ 它跑在哪些模組上?
├─ 全 repo → 成本可能失控,改跑差異模組
└─ 只跑核心 → 問:錯誤處理路徑在裡面嗎?
└─ 不在 → 【第 2 層】優先補這塊(未覆蓋率 86%/81%)
第 1 層:診斷(今天就能做,一小時以內)
挑一個 CI 全綠、你最有信心的服務。手動植入 5 個語意突變:
- 把一個比較運算子改反(
>→>=) - 拿掉一個 null / 空值檢查
- 改掉一個預設回傳值
- 讓一個 error path 靜默(把
raise換成return None) - 改一個邊界條件(
n→n-1)
跑完整測試套件,數有幾個被抓到。
| 抓到 | 判讀 |
|---|---|
| 5 / 5 | 你的 oracle 是健康的,本文不適用於你(但請對新加入的 agent 測試重跑) |
| 3–4 | 有訊號但有破口,優先看沒被抓到的那幾類 |
| < 3 | 你的綠燈在量「有沒有爆炸」,不是「對不對」 |
這個演練的價值在於:上面所有數字都不是你的數字,這個演練的結果才是。
第 2 層:把 oracle 變成可執行的規則
不要寫「agent PR 必須附測試」——這條規則在 80.2% 的世界裡只會製造更多 smoke test。改寫成可 lint 的形式:
- 每個新測試至少一個值斷言(比對具體值),不接受只有
not None/no exception/isinstance - 修改了
try/except/raise的 PR,必須附失敗路徑測試 - Mock 數量超過閾值的測試檔進 review 佇列(不是擋,是標記)
- 禁止在同一個 PR 裡「改程式碼 + 改既有測試的期望值」——這是 residual alignment 最常見的落地形式
第 3 層:切斷閉環
核心問題是出題與作答同源。任何能拉開兩者距離的做法都有效:
- Spec-first:先由人寫測試描述(不是測試程式碼),agent 依描述實作與補測試
- 異源出題:讓 A 模型寫實作、B 模型寫測試,並明確告知 B「不要相信實作,依規格判斷」
- 對抗式生成:Test vs Mutant 類做法(arXiv:2602.08146),讓突變體反向逼出強 assertion
- Mutation-guided 生成:MUTGEN(arXiv:2506.02954)已被 IEEE TSE 接受,mutation score 顯著優於 EvoSuite 與 vanilla prompt
第 4 層:選型
強 oracle 率 18% ↔ 67% 的差距,意味著這是一個採購決策,不只是流程決策。把「生成測試的 oracle 強度」納入你的工具評估項目,用第 1 層的演練當驗收方法。
三個場景
| 場景 | 建議 |
|---|---|
| Python 為主、agent 高度介入、無 mutation testing | 風險最高(Python 既有測試覆蓋中位數 0%)。先跑第 1 層,再優先補錯誤路徑規則 |
| Java / 型別嚴格、已有成熟測試文化 | 既有測試覆蓋較好(61.5%)。重點放在第 2 層的值斷言規則與 mock 閾值 |
| 新專案、從第一天就用 agent | 最有機會。直接上 spec-first + 異源出題,成本此時最低 |
5. 實戰最佳實踐(約 500 字)
常見錯誤 → 正確做法
| 常見錯誤 | 為什麼錯 | 正確做法 |
|---|---|---|
| 「coverage 要拉到 85%」 | 只約束 prefix,完全不約束 oracle;有 bug 時無預測力 | 加一條 mutation score 下限(哪怕只跑差異模組) |
| 「agent PR 必須附測試」 | 在 80.2% 的世界裡只會量產 smoke test | 改成「必須附值斷言 + 錯誤路徑測試」 |
| 讓 agent 讀完實作再寫測試 | 直接餵給它 residual alignment 的燃料 | 給它規格/issue 描述,明確要求「不要從實作推期望值」 |
| 測試掛了就叫 agent 修測試 | 這是把守門員改成配合程式碼的形狀 | 先人工判斷是實作錯還是期望錯,再決定改哪一邊 |
| 用 mock 把依賴全隔離 | agent 已經比人類多 10pp 的傾向,再放任會失去驗證意義 | 核心路徑保留至少一條真實整合測試 |
給 agent 的提示詞調整(Tier 2 — 基於機制的推論)
# 不要這樣(這會觸發 residual alignment)
「幫這個函式補單元測試」
# 改成這樣(把 oracle 的來源從實作移到規格)
「依照下面這份行為規格寫測試。不要閱讀實作來推斷期望值——
如果規格沒寫清楚某個情況該怎樣,列出來問我,不要自己假設。
每個測試至少要有一個具體值的斷言。
必須包含至少 2 個失敗路徑(錯誤輸入 / 依賴失敗)。
規格:
- 當 amount 嚴格大於 limit 時,回傳 REJECTED
- 當 amount 等於 limit 時,回傳 APPROVED ← 邊界明確寫出來
- 當下游服務逾時,拋出 PaymentTimeout,且不得重試
」
**** 這個改法的原理很直接:residual alignment 的成因是模型缺乏獨立的正確性來源,於是退回用「眼前程式碼的輸出」當標準。你把規格放進 context,就是給它一個實作以外的來源。這無法完全消除問題——arXiv:2609.09315 已經量到 prompt-aware oracle「effectiveness remains limited」——但它把 oracle 的來源從實作移開了一格。
6. 效能調優:讓 mutation testing 的成本可負擔(約 350 字)
Mutation testing 之所以沒普及,理由一直是慢。但你不需要全 repo 跑。
只對 diff 跑突變(概念示意,適用 mutmut / PIT / Stryker 等):
# 1) 取出本次 PR 改動的檔案(只看原始碼,不含測試)
CHANGED=$(git diff --name-only origin/main...HEAD \
| grep -E '\.(py)$' | grep -v '^tests/')
# 2) 只對這些檔案跑 mutation testing
# --paths-to-mutate 限制範圍是成本可控的關鍵
mutmut run --paths-to-mutate "$CHANGED" --no-progress
# 3) 取出存活的突變體(survived = 你的測試沒抓到)
mutmut results | grep survived
三個讓它落地的原則:
- 只跑差異,不跑全庫。成本與 PR 大小成正比,而不是與 repo 大小成正比。
- 先跑錯誤處理模組。未覆蓋率 86%/81% 意味著這裡的投資報酬率最高。
- 當成訊號,不要當成 gate。第一個月先只回報存活突變體數量、不擋 merge。你需要先知道基線在哪,而且你會發現這個數字本身就足以改變團隊行為。
**** 我會把門檻設在「新增/修改的程式碼」而非全庫的原因是:既有的 legacy 測試債不是這次要解的問題,硬扯進來只會讓這件事推不動。守住新增的部分,債就不會繼續長。
7. 工具與資源推薦(約 250 字)
| 工具 | 語言 | 一句話 |
|---|---|---|
| mutmut | Python | 最容易上手的 Python mutation testing,支援限定路徑 |
| Cosmic Ray | Python | 分散式執行,適合大型 codebase |
| PIT (pitest) | Java | 業界標準,有成熟的增量模式與 Maven/Gradle 整合 |
| Stryker Mutator | JS/TS | 支援 Jest / Vitest,有清楚的 HTML 報告 |
| Defects4J | Java | 本文多份研究的基準資料集,想自己複驗可用 |
| AIDev dataset | — | 本文兩份核心研究共用的 agent PR 資料集 |
8. 總結與展望(約 400 字)
一表看完
| 環節 | 關鍵數字 | 意義 |
|---|---|---|
| 人退場 | 61.38% agent PR 無人類 review | 判斷權移交給 CI |
| 閘門是空的 | 80.2% 測試 patch 無有效 oracle | CI 量的是「沒爆炸」 |
| 機制 | 99%+ 的失敗測試在舊程式上會通過 | oracle 來自先驗而非程式碼 |
| 儀表板瞎了 | coverage 在有 bug 時預測力轉弱 | 你需要它時它沒訊號 |
| 破口位置 | try-catch 未覆蓋 86% / 81% | 最薄的地方最會爆 |
| 槓桿 | 強 oracle 率 18% ↔ 67% | 3.7 倍差距,可操作 |
按角色的建議
- 工程師:今天就跑第 1 層的 5 個突變。不用開會,不用申請預算,一小時。
- 技術主管:把 coverage 從 OKR 拿掉,換成「新增程式碼的存活突變體數」。前者已經不是訊號了。
- 決策者:把 oracle 強度納入 agent 工具的驗收條件。18% ↔ 67% 的差距,比多數人正在比較的那些功能差異都大。
兩個趨勢
- Oracle 生成會成為 coding agent 的獨立能力項,就像今天大家比 SWE-bench 一樣,明年會有人比 VRR。arXiv:2605.22175 已經把這個指標做出來了。
- 異源驗證會變成架構要求。Test vs Mutant 這類對抗式做法現在還是研究題目,但「出題與作答不能同源」這個原則本身,遲早會被寫進工程規範——就像今天沒人接受自己 review 自己的 PR。
結語
我們花了二十年讓「測試通過」這四個字變得值得信任。那份信任的基礎不是測試本身,是寫測試的人在寫的時候,對正確行為做過一次獨立判斷。
那次判斷現在被外包出去了,而接手的東西沒有判斷能力,只有模仿能力。
該換的問題不是「測試有沒有過」,是「這支測試有沒有資格判斷過與不過」。
金句
「Coverage 量的是你的測試去過哪裡,不是它看懂了什麼。過去這兩者高度相關,因為去那裡的是人。」
「出題的、作答的、改考卷的是同一個模型——然後我們管這個叫 CI 通過。」
「Agent 測試覆蓋最薄的地方是錯誤處理,而那恰好是生產環境唯一會爆炸的地方。」
「Pass@1 98%,真能重現缺陷 40%。綠燈從來沒有騙你,是我們一直誤會它在說什麼。」
延伸思考
- 如果現在請你手動植入 5 個語意突變,你會有多少把握你的測試套件抓得到 3 個以上?這個「把握」是根據什麼來的——數據,還是你上次認真讀測試時的印象?
- 你的團隊規範裡「必須附測試」這條,如果被一個只會寫
assert result is not None的 agent 完美遵守了,你有任何機制會發現嗎? - 你最近一次讓 agent 修好一個失敗的測試時,你確認過它修的是實作還是期望值嗎?
FAQ 常見問題
Q1:這是不是在說不要讓 agent 寫測試?
不是。研究顯示 agent 寫測試確實提升覆蓋率(Java +15.6pp、Python +9.6pp)。主張是:別讓同一個 agent 寫的測試同時擔任驗收標準。寫可以,當閘門不行。
Q2:人類寫的測試不也一堆 smoke test 嗎?
是。而且這幾份研究都沒有做人類對照組,我在文中明確標註了。正確的主張不是「AI 比人爛」,而是 AI 把這個老問題的規模與速度放大了,同時把原本能發現它的人工審查抽走。
Q3:Coverage 是不是完全沒用了?
不是。它在程式無缺陷時仍與缺陷偵測強相關(r=0.861)。它失效的是「程式可能有 bug」這個情境——而那正是你需要它的場合。把它當健康度指標可以,當品質閘門不行。
Q4:Mutation testing 太慢,怎麼導入?
只對 PR 的差異檔案跑,成本就與 repo 大小脫鉤。第一個月只回報不擋 merge,先建立基線。
Q5:換一個更強的模型能解決嗎?
部分可以,但不要期待它是解法。強 oracle 率確實從 18%(Codex)到 67%(Claude Code)差 3.7 倍;但最強模型的 VRR 也只有 40.40%。升級模型改善品質,不改變結構——出題與作答同源的問題還在。
Q6:那 LLM 產的 oracle 有沒有比傳統工具好?
有。arXiv:2410.21136 發現 LLM 生成的 oracle 缺陷偵測潛力高於 EvoSuite。相對於自動化基準它是進步的;問題在於它被放在人類 review 的位置上使用。
Q7:為什麼 Python 的情況比 Java 差這麼多?
既有測試對 agent 改動行的覆蓋 Java 61.5% vs Python 27.0%,中位數 71.1% vs 0%。研究也發現 Python 的測試生成需要顯著更多嘗試(Gemini 2.5 Flash:2,155 次 vs Java 323 次),歸因於動態型別與訓練語料中 Python 測試佔比較弱。
Q8:測試失敗時,agent 說「測試寫錯了」我該信嗎?
這是 residual alignment 最常見的落地形式。建議把「同一個 PR 內同時改實作和既有測試的期望值」列為需要人工判斷的情境。
Q9:over-mocking 真的會漏抓 bug 嗎?
研究只證明 agent 加 mock 的傾向較高(36% vs 26%,效果量小),沒有量測是否造成漏抓。不要過度延伸。它支撐的主張只是「更傾向隔離真實互動」。
Q10:我們沒有 QA,這些都要工程師自己做嗎?
第 1 層演練一小時、第 2 層是 lint 規則、第 3 層是 prompt 與流程調整。成本最高的是第 3 層的 spec-first,但那本來就是你在 agent 時代必須付的費用——你省下的是打字,不是思考。
參考資料
核心研究
- Banik, Chowdhury, Shamim. All Smoke, No Alarm: Oracle Signals in Agent-Authored Test Code. arXiv:2606.18168v1, 2026-06-17. https://arxiv.org/abs/2606.18168
- Duma, Wróblewski, Bobińska, Winiarska, Przymus. These Aren't the Reviews You're Looking For: How Humans Review AI-Generated Pull Requests. arXiv:2605.02273, 2026-05-04. https://arxiv.org/abs/2605.02273
- Haroon, Khan, Gulzar. Evaluating LLM-Based Test Generation Under Software Evolution. arXiv:2603.23443v1, 2026-03-24. https://arxiv.org/abs/2603.23443
- Zhao, Zhou, Cohen. Do Coverage and Mutation Scores of LLM-Generated Test Suites Correlate with Their Effectiveness? (Replicability Study). arXiv:2607.22880, 2026-07-24. https://arxiv.org/abs/2607.22880
- Hamidi, Konstantinou, Degiovanni, Papadakis. How effective are traditional test criteria at detecting bugs in LLM generated code? arXiv:2609.09315, 2026-09-08. https://arxiv.org/abs/2609.09315
- Sun et al. SWE-Mutation: Can LLMs Generate Reliable Test Suites in Software Engineering? arXiv:2605.22175v1, 2026-05-21. https://arxiv.org/abs/2605.22175
- Dipongkor, Baral, Lam, Moran. Test Coverage Analysis of Agentic Pull Requests. arXiv:2607.18057v1, 2026-07-20. https://arxiv.org/abs/2607.18057
補充研究
- Hora, Robbes. Are Coding Agents Generating Over-Mocked Tests? An Empirical Study. arXiv:2602.00409, MSR '26. https://arxiv.org/abs/2602.00409
- Wang, Xu, Briand, Liu. Mutation-Guided Unit Test Generation with a Large Language Model. arXiv:2506.02954(IEEE TSE accepted). https://arxiv.org/abs/2506.02954
- Konstantinou, Degiovanni, Papadakis. Do LLMs generate test oracles that capture the actual or the expected program behaviour? arXiv:2410.21136, 2024-10-28. https://arxiv.org/abs/2410.21136
- Tabassum, Intesum, Arefin, Zaman. VibeCheck: Assessing the Quality of LLM-Generated Unit Tests. arXiv:2609.05978, 2026-09-05. https://arxiv.org/abs/2609.05978
- Test vs Mutant: Adversarial LLM Agents for Robust Unit Test Generation. arXiv:2602.08146. https://arxiv.org/abs/2602.08146
文章裡這些把關做法,要在一個團隊裡真的落地、而不是只有你一個人在用,通常卡在流程與共識。我把這部分整理成企業內訓:
coding agent 導入與治理 — 企業內訓與顧問 →


