GStack 加入 test-audit:AI 寫了更多測試,團隊怎麼知道它們真的有用?
GStack 加入測試稽核。從保護行為、重複檢查與回歸證據,判斷哪些測試應保留、調整或合併。
AI 很容易替一段程式增加十幾個測試,檢查畫面也很快變成一整排通過。但測試數量增加,不代表每個測試都能抓到新的問題。有些只重複已有檢查,有些跟著實作寫答案,甚至在程式正常改寫後就全部失敗,讓維護者花很多時間更新測試。
Garry Tan 在 2026 年 9 月的 X 貼文中,宣佈把 OpenClaw 的 test-audit 做法整合進 GStack。貼文查核時已有超過三萬次瀏覽。公開文件的重點,是找出低價值或重複測試,以及它們為測試而維持的額外程式,先提出有證據的稽核結果,再處理具體範圍。
我的判斷是:測試稽核應從「這個測試保護什麼行為」開始。測試慢、檔案多或內容舊,都不足以單獨成為刪除理由。團隊需要知道它能抓到哪種錯誤、其他檢查是否已覆蓋,以及移除後會失去什麼證據。這樣才有機會減少負擔,同時保留真正需要的防線。
測試的價值,在於能發現什麼錯誤
自動測試會執行程式,並用斷言檢查結果。斷言就是明確說明什麼條件應成立,例如空白名稱應被拒絕。若程式偏離預期,測試應失敗。只有成功執行而沒有檢查結果的測試,可能顯示程式能跑,卻沒有證明重要行為仍正確。
可以先問一個實際問題:如果刪掉必要的檢查,這個測試會不會失敗?若答案不清楚,測試可能沒有對準風險。例如原本要驗證錯誤輸入被擋住,測試卻只確認函式有回傳物件,就無法證明防護條件仍在。
這是理解測試的假想例子,本文沒有對讀者專案執行稽核。真正檢查時,應閱讀完整測試與相關程式,不能只根據名稱判斷。有些看起來簡單的測試,可能保護重要預設值。也有些名稱很專業,實際只重複同一個成功情境。
團隊可以為關鍵測試寫一行價值說明,包含保護的行為與會抓到的錯誤。說明不必很長,重點是後續維護者能理解為何存在。如果多年後仍只能說因為當時加了,就值得追查歷史與產品需求,避免用記憶模糊的理由決定去留。

通過很多測試,仍可能漏掉真正需求
測試常有一個盲點:只檢查容易寫的部分。頁面能開啟、按鈕有出現,並不一定證明使用者能完成表單。若真正問題是資料沒有保存,測試就應對準保存後的結果。需求到斷言之間的關係,決定綠色通過訊號的意義。
覆蓋率是程式哪些部分被執行到的指標,可以協助找缺口,但不能單獨代表品質。某行程式被執行過,不等於結果有被正確檢查。若測試只追求百分比,可能增加大量沒有獨立判斷力的案例,讓數字提高,卻沒有減少真正風險。
因此,稽核應同時看需求和檢查方式。某個核心流程即使代碼很短,錯誤後果也可能很大。另一段長程式若只是資料格式整理,可能已有適當的共同檢查。測試資源應依行為重要性與變更影響安排,不必平均分配到每一行。
失敗路徑也要納入。正常輸入成功只是其中一種條件,缺少欄位、服務回傳錯誤或重複操作,也可能影響使用者。哪些情況值得測,由產品行為與實際錯誤決定。避免為了補數量,機械式增加與需求無關的排列組合。
重複測試,先確認是否真的保護同一件事
兩個測試都叫登入成功,不代表一定重複。一個可能確認程式邏輯,另一個確認瀏覽器與服務串接。它們位於不同邊界,可能抓到不同錯誤。稽核應比較輸入、執行路徑與實際斷言,而非只用名稱相似度找出刪除名單。
但如果多個測試使用相同輸入、相同模擬資料與相同判斷,新增價值就值得檢查。可以考慮合併成共同案例,或在既有測試中增加真正不同的條件。這樣減少重複設定,也讓後續修改只要調整一個清楚的檢查位置。
共同工具函式尤其容易被重複測試。每個呼叫者都重新驗證工具內部細節,可能讓同一個改動造成很多檔案失敗。呼叫者應關注它自己的行為契約,工具本身則有對應檢查。清楚分工能減少重疊,也讓失敗更容易定位。
合併之前,仍應確認沒有遺漏獨特條件。某個案例可能使用不同權限、平臺或資料型態,看起來相似卻有不同風險。保留差異說明,讓審核者知道哪些內容被合併、哪些仍獨立檢查。清理的成果應能解釋,而非只呈現減少多少行。
測試太依賴實作,正常重構也會造成負擔
實作是程式內部如何完成工作,行為則是使用者或其他程式能觀察到的結果。若測試只檢查某個私有函式被呼叫幾次,正常調整內部結構也可能失敗。此時產品沒有壞,維護者卻需要同時修改很多測試,形成額外負擔。
可以改在真正的使用邊界檢查結果。例如確認提交後資料被正確保存,而非指定必須經過某個內部函數。邊界就是外部使用者或組件接觸系統的位置。選擇合適邊界,能讓測試保護需求,同時允許內部實現有合理變化。
但精確輸出有時就是契約。資料交換格式、公開程式介面或固定生成文件,可能需要逐字或結構一致。不能把所有細節檢查都視為過度耦合。先確認細節是否對外可觀察、是否屬於明確要求,再決定是否調整。
測試文件讀取原始碼也未必無價值。某些架構限制或發佈配置,可以用靜態檢查低成本保護。重點是它能獨立驗證什麼契約,以及有沒有更適合的方式。慢、靜態或不常變化,都不是單獨刪除依據。
為測試新增的程式,也需要追查真正用途
有些專案為了測試,額外導出內部函數、增加開關或包裝層。這些安排可能有必要,也可能在需求消失後繼續存在。GStack 公開稽核文件特別關注這種測試專用負擔,要求查清實際調用與替代證據,避免只刪測試卻留下沒有用途的程式。
然而,簡單搜尋沒有找到呼叫者,不足以證明程式無用。公開導出、動態調用與生成程式,都可能讓用途不容易被文字搜尋發現。稽核應結合套件入口、建置與型別檢查等證據,不能看到零筆搜尋結果就直接刪除。
對初學者,可以把問題理解成一張依賴圖。誰使用這個函數,它對外提供什麼,測試為何需要它?圖中若有生產用途,就應保留該契約。若只有測試使用,再研究是否能改在真實邊界驗證,減少額外接口。
這類清理應限定具體範圍。發現一個測試專用包裝,不代表可以順便重寫整個模塊。先提出小批候選與理由,修改後執行相關檢查。範圍清楚,審核者才能判斷結果,也較容易在出現問題時回到之前狀態。
回歸測試,要證明原本的錯誤能被抓到
迴歸測試是為防止已修好的錯誤再次出現而保留的檢查。它應能在原本有問題的條件下失敗,再在修復後通過。如果新增測試從一開始就通過,可能沒有真正重現錯誤,只是檢查另一個與修復無關的行為。
失敗也要看原因。測試因為依賴沒安裝、環境沒啟動或資料準備錯誤而失敗,不能證明它抓到原始缺陷。應確認失敗發生在預期斷言,並與用戶問題對應。這個區分讓測試成為修復證據,而非只留下一次紅色執行紀錄。
修復後的成功同樣要檢查。測試可能被放寬,或直接照新實現寫答案,因而不再能獨立保護行為。審核時應回到原始需求,確認預期結果沒有被偷偷改變。測試與程式同時修改很常見,也更需要明確說明各自調整理由。
好的迴歸案例通常具體而小。保留必要輸入與觸發條件,就能說明問題。若把大量無關步驟都放進來,失敗會更難定位,執行也更慢。減少無關內容與減少必要覆蓋不同,前者應讓錯誤證據更清楚,後者可能讓問題再度漏掉。
稽核報告,應讓保留與移除都可審閱
GStack 的公開做法以報告為起點,列出候選、證據與後續驗證。讀者可以借用這類思路:每個候選說明目前保護什麼、是否已有更強檢查、修改影響與必要驗證。報告應包含保留理由,不只列出可刪除清單。
保留理由很重要,因為稽核可能遇到誤判。一個看起來重複的測試,可能保護特定平臺。一個很慢的測試,可能驗證完整發布流程。把這些案例留下,能讓團隊形成更準確的標準,避免下一輪重複提出相同清理建議。
修改順序也應小範圍進行。先處理證據完整的一批,執行受影響的檢查,再看是否有新問題。沒有必要因為做稽核,就把所有模塊重新整理。清楚的範圍與結果能讓團隊知道本次減少什麼負擔,以及哪些風險仍保留防護。
報告最後應列出實際運行的檢查與結果。僅說測試都通過,可能不知道執行哪些範圍。若某項環境無法運行,應明確留下限制,不能把未執行當成成功。可審閱的證據,比整齊但模糊的總結更有維護價值。
常見問題
測試很多,就代表專案品質很好嗎?
數量只能說明有多少案例。品質還要看它們保護什麼行為、能抓到哪些錯誤,以及是否重複。獨立而具體的檢查,比大量跟隨實作的測試更容易形成可靠證據。
執行很慢的測試應該刪掉嗎?
先看它保護的契約與替代方式。有些完整流程測試耗時較長,卻提供其他檢查無法代替的證據。可以改善執行或安排時機,但不能只憑速度決定去留。
AI 可以直接替團隊刪除低價值測試嗎?
應先提出具體候選與證據,再依團隊授權範圍修改。搜尋結果和名稱相似都不足以獨立證明無用。修改後應完成受影響檢查,並保留無法驗證的部分。
讓每個測試都有能說清楚的責任
GStack 的 test-audit 方向,提醒團隊把注意力從新增數量轉向保護行為。AI 可以更快準備測試,也可以協助閱讀與整理證據。最終是否有價值,仍取決於測試與真實風險之間的關係。
下一步可以挑一個經常維護的模塊,列出關鍵行為,再把現有測試對應上去。查看哪些行為缺少檢查,哪些案例重複保護同一件事。先整理一份小報告,就能開始減少負擔,而不用第一輪就改動整個專案。