自動化測試策略:從冰淇淋到金字塔

#測試策略 #自動化測試 #CI/CD #測試金字塔 #QA 思維

自動化測試策略:從冰淇淋到金字塔 我第一份工作的測試套件,大概 95% 都是 UI E2E 測試。 每次跑完要四十分鐘,失敗率大概 30%,而且你永遠不知道失敗是真的 bug 還是又是那個抖動的 dialog。久了以後,大家就開始忽略紅燈——反正隨便跑一次可能就綠了。 這個現象有個名字,書上叫它「冰淇淋甜筒反模式(Ice Cream Cone Anti Pattern)」。這篇文章想聊的,就是怎麼從冰淇淋爬回金字塔。 文章的底本來自 CI/CD 2.0 的第 10 章自動化測試策略,加上我自己的一些工作觀察和想法。 測試到底在做什麼? 先把問題拉高一層看。 Brian Marick 的 測試四象限 把測試活動分成兩個維度: 業務導向 vs 技術導向 支持開發 vs 評估產品 四個象限: | | 支持開發 | 評估產品 | | | | | | 業務導向 | ② 功能驗收測試(自動化) | ① 探索性測試、用戶演示(手動) | | 技術導向 | ③ 單元、整合、元件測試(自動化) | ④ 效能、可靠性測試(混合) | 第二象限 :驗收測試,從使用者角度確認功能正確。 第三象限 :單元和整合測試,從系統角度確認技術實作。 第四象限 :非功能性測試,效能、容量、可靠性。 這個框架讓我想到一件事:自動化最有價值的地方,是第二和第三象限。但很多人做自動化,預設就是「幫手動測試自動化」——也就是第一象限的探索性測試,去模擬使用者點界面。這是最貴、最脆弱的一層。 探索性測試的核心是人的判斷力 ,自動化做不到「看到奇怪的地方就多試試看」。把探索性測試搬進自動化,你得到的是一個很貴、而且只能回答你事先知道的問題的工具。 為什麼會出現冰淇淋反模式? 傳統的自動化測試流程大概是這樣: 測試分析師 → 手動執行驗收 → 找 bug → 修復 → 重跑 → 挑重要案例 → 自動化工程師寫腳本 → 放進回歸庫 這個流程產出的測試,天然就是「上層為主」——模擬使用者操作界面的黑盒測試。久了就變成冰淇淋:又重又貴的 E2E 在最上面,輕量的單元測試很少甚至沒有。 書上列了六個傳統自動化測試的問題,我一個一個對照過,幾乎都踩過: 1. 執行成本高 :流程太長,每個測試要準備的環境和資料很多。我見過一個 E2E 套件光是「登入並建立測試帳號」就要 2 分鐘。 2. 執行頻率低 :因為太重,不可能每次 commit 都跑。一天跑一次都算勤快。 3. 回饋太慢 :等到 CI 跑完才知道壞了,那時候 developer 已經在做下一張票了,context 切換成本很高。 4. 環境準備貴 :需要完整的測試環境、資料、有時還要人工準備。我們曾經有個環境,要先 call 一個 API 建立 10 筆假資料,建立失敗測試就整批跳過。 5. 結果不可信 :隨機失敗(flaky test)是最毒的。一旦大家開始說「那個應該是 flaky,不管他」,整個 CI 的可信度就崩了。 6. 依賴特定人員 :只有一個人會寫自動化,那個人離職就是災難。 衡量好自動化測試的四個標準:快、捷、時、信 書裡提了一個我覺得很實用的框架,稱為「快、捷、時、信」: 快(Fast) :目標是 10 分鐘內跑完,最多 15 分鐘。 這不是隨便定的數字。人的注意力能維持大約 15 分鐘,超過這個時間,開發者會切去做別的事,回饋就不是「即時」了。 捷(Convenient) :任何工程師都能輕鬆跑,不影響別人。 這有一個很現實的意義:如果只有某個人的電腦能跑測試,那當那個人去跑測試時,整個 CI 的作用就大打折扣。測試必須是團隊共有的,跑在共享環境上。 時(Timely) :每次改 code 都立刻知道影響。 這意味著:新功能必須同步有對應的測試。「之後再補」幾乎等於「永遠不補」,因為功能上線後沒人願意回去補舊代碼的測試。 信(Reliable) :不能有隨機失敗。 這是四個裡我覺得最關鍵、也最常被忽略的一個。Flaky test 的危害不只是「浪費一次 CI 時間」,而是它會慢慢腐蝕整個團隊對測試結果的信任。一旦開始忽視紅燈,CI 就只剩形式。 書上提到「破窗效應」:環境的失序會邀請更多失序。如果有幾個測試一直紅著沒人修,其他人也會開始容忍更多紅燈。這個效應在我工作的地方非常真實。 測試金字塔:微服務版本 傳統的測試金字塔分三層:Unit → Integration → E2E。但現代系統大多是微服務架構,這個分層需要細化。 書上的微服務測試金字塔(從下到上): 其中有一層是我覺得業界嚴重低估的: 契約測試(Contract Testing) 。 契約測試:被低估的中間層 在微服務架構裡,服務 A 依賴服務 B 的 API。常見的問題是:B 改了回傳格式,A 的測試在自己的 mock 環境下還是綠的,但真的呼叫 B 的時候就炸了。 傳統解法是跑 E2E 測試——但 E2E 很慢、很脆弱。 契約測試的思路是: 消費端(A)定義「我需要什麼格式」,提供端(B)確認「我能給你這個」 ,並把這個確認自動化。 這樣 A 不需要真的呼叫 B 就能驗證,B 也不需要啟動完整的服務環境就能確認自己符合契約。快、穩定、精準。 Pact 是這個領域最主流的工具。 我的觀察是:很多後端微服務團隊把測試分成「unit test」和「E2E test」兩種,中間那一層完全空白。契約測試可以填補這個空缺,而且成本比 E2E 低很多。 從哪裡開始增加自動化測試? 書上提了四個切入點,我覺得第三個最被忽略: 1. 熱點代碼(Code Hotspots) :改動頻率高、容易出問題的區域。從這裡補測試,效益最高。 2. 新功能開發 :新功能同步寫測試,在最了解這段 code 的時候寫,成本最低。 3. 從金字塔中間層開始 :不是從 E2E 往下做,而是從 component/API/contract 這層開始,往上往下都比較容易延伸。 4. 重質不重量 :這句話我在書裡看到,覺得說出了很多 QA 不敢說的話—— 「用最低成本的測試層實現特定業務邏輯的驗證,測試案例的數量以合適為準,切忌多多益善。」 測試不是越多越好。重複的、沒有驗證價值的測試只是增加維護成本。一個精準的整合測試,可能比十個互相覆蓋的 E2E 測試更有價值。 覆蓋率是目標,還是工具? 關於 code coverage,書裡的態度很務實,我很認同: Google 的建議是 85% 的 unit test 覆蓋率,但不是強制要求 Facebook 完全沒有統一的覆蓋率標準 覆蓋率能告訴你「哪些 code 沒被測到」,但無法證明「被測到的 code 是被正確測到的」 覆蓋率是個指標,不是目標。 我見過有團隊為了達到 80% 的覆蓋率指標,把 getter/setter 全部都測了,但核心的業務邏輯邊界案例沒有任何測試。這種覆蓋率數字看起來好看,但對品質沒有幫助。 更好的問法不是「我的覆蓋率是多少」,而是「我的測試有沒有涵蓋最重要的業務邏輯和邊界條件」。 自動化測試是代碼,需要維護 書裡特別強調一點,我覺得值得單獨說出來: 自動化測試是軟體,需要維護。 這句話聽起來很平凡,但很多人在實作自動化測試的時候,把它當成「一次性投資」——寫好了就有了,之後自動跑就好。 事實是:產品功能改了,測試要跟著改。不跟著改就會慢慢積累「因為產品更新而失敗的測試」,然後選擇是:花時間修,或是把測試設為 skip 假裝不存在。 「破窗效應」在這裡再次出現:第一個被 skip 的測試,是第一扇破窗。 我的綜合觀點 讀完這章,我整理出幾個對我影響比較大的觀念轉變: 自動化測試不是「幫手動測試員省事」,而是開發流程的一部分。 最好的自動化測試是開發者自己寫的、自己跑的、自己負責維護的。QA 的角色是策略設計、測試分層的建議、以及那些確實需要人類判斷力的探索性測試。 E2E 測試應該是稀缺資源,不是主力。 每個 E2E 測試都是高維護成本的投資,應該只用在「核心業務流程的驗收」,而不是「所有功能的全量驗證」。細節驗證推到下層做。 Flaky test 是 CI 的腐蝕劑。 寧可暫時沒有測試,也不要有一個大家都不相信的測試。維持測試的可信度,比維持覆蓋率數字更重要。 好的測試策略要先問「快、捷、時、信」四個問題。 如果你的測試套件不夠快、不夠方便、不夠及時、不夠可靠,那即使覆蓋率很高,實際效果也很有限。 延伸閱讀 :本文底本來自 CI/CD 2.0 Chapter 10,有興趣深入的讀者可以直接看原文,包含更多架構圖和實作細節。 常見問題 Q:自動化測試覆蓋率要達到多少才夠? A:沒有通用標準。Google 建議 85% 的 unit test 覆蓋率但不強制,Facebook 完全沒有統一標準。覆蓋率是工具不是目標——重點是核心業務邏輯和邊界條件有沒有被涵蓋,而不是數字好不好看。為了衝高數字而測 getter/setter,對品質沒有幫助。 Q:什麼是冰淇淋反模式?怎麼解決? A:冰淇淋反模式指測試套件以大量 E2E 為主、單元測試極少的結構——和理想的測試金字塔上下顛倒。E2E 執行慢、失敗率高,長期下來大家開始忽略紅燈,CI 失去意義。解法是從金字塔中間層(component/API/契約測試)開始補,把驗證邏輯推到更低層。 Q:Flaky test 怎麼處理? A:優先修復,無法短期修復就移除或隔離到獨立 suite,不要讓它混在主要 CI 流程裡。Flaky test 最大的危害不是浪費一次 CI 時間,而是它會慢慢腐蝕整個團隊對測試結果的信任——一旦大家開始忽視紅燈,CI 就只剩形式。 Q:什麼是契約測試(Contract Testing)?什麼時候需要用? A:契約測試用於微服務架構,由消費端定義「我需要什麼 API 格式」,提供端自動驗證「我能給你這個」。不需要啟動完整環境、執行快、精準定位問題。當服務間 API 互相依賴、靠 mock 驗證又不放心時,是導入的時機。主流工具是 Pact。 Q:新專案沒有任何自動化測試,應該從哪裡開始? A:從「熱點代碼」開始:改動頻率高、容易出問題的區域效益最高。同時,新功能同步寫測試,在最熟悉這段 code 的當下寫,成本最低。從金字塔中間層(component/API 層)而不是 E2E 開始,往上往下都比較容易延伸。 參考資料 Martin Fowler — Test Pyramid — 測試金字塔概念原始定義 Martin Fowler — Practical Test Pyramid — 金字塔的完整實作指南 Mike Cohn — Succeeding with Agile — 測試金字塔的提出者 Mike Cohn 的相關著作 Google Testing Blog — Just Say No to More End to End Tests — Google 對 E2E 測試過多的看法 Capgemini — World Quality Report 2024 25 — 全球自動化測試比例與趨勢