QA 自動化不是寫更多測試,是建閉環

很多團隊衡量自動化成熟度的方式是「我們寫了幾個測試」。這個數字幾乎沒有意義

真正決定價值的是跑完之後發生什麼:測試結果透明嗎?失敗會不會自己重跑?季末講得出成效數字嗎?票務進來會不會自動變成測試?如果這些都是「人工」或「不知道」,那你寫再多測試,都只是一堆黑箱。

自動化的天花板不在「寫得多」,在「有沒有形成閉環」。這篇是一條跑真交易所(帳戶/出入金/訂單簿/餘額,錯了會出事)的完整閉環怎麼組起來的。

全景:一條四層閉環

flowchart LR
    T[票務系統<br>AC + MR] --> E[AI 引擎層<br>codegen]
    E --> B[BDD 場景庫<br>單一真相源<br>12,293 場景]
    B --> R[Robot 執行層<br>1,620 測試]
    R --> J[CI 平行跑<br>只重跑失敗]
    J --> S[(結果 Sheet)]
    S --> D[儀表板<br>自動化指標]
    D -.閘門觸發.-> J

    style E fill:#f59e0b,color:#fff
    style B fill:#06b6d4,color:#fff
    style R fill:#10b981,color:#fff
    style D fill:#7c3aed,color:#fff

四層各司其職:AI 引擎產碼、BDD 場景庫是唯一真相源、Robot 執行層跑真環境、儀表板收指標並反過來觸發重跑。重點不是任何單層多聰明,是四層串成一條會自己轉的環


一、單一真相源:WHAT vs HOW 分離

閉環的地基,是把測試案例從無版控的 Excel(動輒幾 MB、沒人敢動)搬進 git。搬進來之後做一件關鍵的事——WHAT 跟 HOW 分兩層

flowchart TB
    subgraph WHAT[場景庫 · 測什麼]
        W1["Given/When/Then<br>測試意圖 + 預期"]
        W2["user level 矩陣"]
    end
    subgraph HOW[Robot · 怎麼測]
        H1["自動化實作碼"]
    end
    WHAT -->|只靠案例名字對映| HOW

    style WHAT fill:#06b6d4,color:#fff
    style HOW fill:#10b981,color:#fff
  • 場景庫存「測什麼」:意圖、預期、user level 矩陣,用業務語言寫成 Given/When/Then。QA/PM 看得懂、能 review。
  • Robot 層存「怎麼測」:自動化程式碼。
  • 兩層只靠測試案例的名字對映,各自獨立演進。

這樣 QA/PM 不用讀一行自動化 code 就能 review 測試意圖,而自動化實作可以重構、可以換 driver,完全不動到 spec。這 12,293 個場景(App + Web 合計、近百個模組)就是這樣變成可 diff、可 MR review、可 branch-per-ticket 的。

level 參數化是另一個放大器:一個「人類場景」用 level 矩陣展開成 N 個 Robot 測試(例如同一個提領流程,對 L0/L1/L2/未綁銀行各有不同預期)。這就是為什麼「12k 場景」對映到的自動化面比 12k 大得多。


二、票務驅動:票進來,自動變成測試骨架

閉環的入口是票務。一張功能票有驗收條件(AC)和對應的 MR,這些就是產測試的原料:

票(AC + MR)AI 產 Python 測試骨架 + harness寫進測試分支merge

單元測試要行級細節、整合測試只要邊界,所以餵 context 時主票給完整 diff、聚合子票只給檔名(省約 95% token)。產出的不是「能跑就好」的碼,而是符合團隊慣例的碼——因為慣例本身被寫成了機器可檢查的規範(見下一節)。


三、data-driven 預期:別把「會過期的真相」寫死

跑真交易所最容易犯的錯,是把費率、提領上下限、上架幣種寫死在測試裡。這些東西天天在變,寫死的測試明天就是紅的(而且是假紅)。

正解:對平台自己的真相源驗證。每次跑之前先抓一份即時的交易所 metadata 快照(幣別確認數、提領上下限、維護狀態、下市對、VIP 費率……),在 runtime 導出預期值。

測試斷言的不是「手續費應該是 0.1%」,而是「手續費應該等於平台此刻宣告的值」。真相源變了,測試自動跟上,不用改一行 code。


四、把 flaky 夜跑變確定性:三訊號就緒閘門

夜跑 App 測試最惱人的是 flaky——早上來看一片紅,重跑又全綠。多數 flaky 的根因是「還沒真的 ready 就開始測」

以 Android 冷開機為例,別用盲目的 sleep 30,改用三訊號就緒閘門

flowchart LR
    C[冷開 emulator] --> S1{sys.boot_completed?}
    S1 -->|是| S2{settings service<br>有回應?}
    S2 -->|是| S3{IME 輸入法<br>綁定完成?}
    S3 -->|是| GO[開始測試 ✅]
    S1 -->|否| S1
    S2 -->|否| S2
    S3 -->|否| S3

    style GO fill:#10b981,color:#fff

三個訊號都過才開跑。搭配:殺乾淨舊的 emulator / session(別讓上一輪殘留污染)、調冷開參數(不載入 snapshot、指定 GPU 模式、加大 partition 防 APK 累積爆磁碟)。這樣就能把「flaky 夜跑」變成「確定性夜跑」。


五、閉環收尾:只重跑失敗 + 自動回流

最後一段,也是「閉環」真正閉起來的地方:

flowchart LR
    F[完整跑一輪] --> S[(寫結果 Sheet)]
    S --> G{通過率 > 85%?}
    G -->|是, 進閘門| RR[CI 只重跑<br>失敗的]
    RR --> M[rebot 合併結果]
    M --> S2[(回填 Sheet)]
    S2 --> D[儀表板消費]
    D --> N[Slack 通知]

    style G fill:#f59e0b,color:#fff
    style RR fill:#10b981,color:#fff
    style D fill:#7c3aed,color:#fff
  • 完整跑一輪,結果寫進 Sheet。
  • 儀表板讀失敗標記,過通過率閘門(例如 >85%)才觸發重跑——用 <tag> 對 Sheet,不是用 test name(名字會改、tag 穩定)。
  • CI 只重跑失敗的、再用 rebot 合併,不重跑全套。
  • 結果回填 Sheet → 儀表板消費 → Slack 通知。

按 user level 分組平行跑、只重跑失敗、合併——這幾步讓「一個 flaky 失敗」不用賠掉整輪的時間。


別忘了:慣例即程式碼 + 誠實計量

慣例即程式碼:AI codegen 需要一個「機器可檢查的目標契約」。把團隊慣例(keyword 命名、xpath 大小寫、「≥2 個斷言要用 continue-on-failure」等)寫成幾百行規範,再配一個 linter skill 對分支 diff 報 🔴🟡🟢——這就是 AI 產碼的驗收閘門。沒有這層,AI 產的碼會慢慢腐化成各寫各的。

誠實計量(管理層最在意的一條):

  • 自動化數量兩來源對帳——從執行結果 Sheet 讀,再用季末 commit 快照數(數 Robot 的 *** Test Cases ***、JS 的 test())交叉驗,對得上才報。
  • AI 測試輔助 = 按規格手刻加速 + 人把關絕不寫成「全自動、不耗人力」。取材分界也要明確:哪些算「QA 用 AI」、哪些屬另一個專案,不能混報。

浮誇一次,就賠掉整個儀表板的公信力。閉環的最後一塊,是讓數字誠實到主管敢拿去對 keynote。


一句話

自動化的價值不在「寫了幾個測試」,在「跑完之後這條路會不會自己轉」——從票務進來、產碼、跑真環境、只重跑失敗、回流儀表板。你建的不是測試,是一條會自我修復的閉環。