"Test"
- 流程測試基礎設施
在 Flutter 專案建立流程測試時碰到的 Dart 實作限制:控制器能不能在 headless 環境立起來、binding 怎麼跟真實網路測試共存、測試輸出雜訊怎麼治理、假後端的回應資料走什麼路徑序列化——限制形成一條建置鏈,前一個的答案決定後一個的形態
- Flaky Test
說明非決定性測試如何降低 CI gate 信任度與治理方式
- Flaky test 治理
說明 CI/CD 如何把 flaky test 從重跑雜訊轉成可分類、可隔離、可修復的 gate 信任度問題
- TestWidgetsFlutterBinding 會擋掉真實網路:真實後端測試與流程測試的檔案級隔離
flutter_test 的 binding 初始化後會把 HttpClient 換成回 400 的假件——需要真實網路的後端驗證測試不可初始化 binding,也因此不可 import 任何會初始化 binding 的 harness。靠測試檔案各自跑在獨立 isolate 的特性,兩種測試在同一個目錄共存。
- 有狀態假後端用真實模型序列化回應:手寫 JSON fixture 會重踩產品已解決的問題
流程測試的假後端持有 freezed 模型物件、以 toJson 序列化回應,讓服務層走完整的反序列化鏈。對照組是手寫 JSON fixture——同一批測試裡的 raw 寫法重踩了一次產品早已內建處理的分頁包裝,證明「回應形狀的知識」應該只存在一份。
- 測試輸出的雜訊治理:預期的環境狀態不該走例外路徑
測試輸出長期印著兩行「已知無害」的錯誤——相機偵測 MissingPluginException、toast 套件的 assert fallback。已知雜訊會訓練人忽略輸出,新警報混在裡面就被過濾掉。修法是把「預期的環境狀態」變成前置判斷(channel mock 回空、無畫面早退),讓例外路徑只剩真正的例外。
- 讓 UI 控制器在 headless 測試立起來:platform channel mock、no-op 子類與 postFrameCallback 的手工補位
流程測試要驅動真實編排,而編排住在 UI 控制器裡——能不能在無畫面的測試環境把控制器立起來,決定整個測試套件的形態。先用 spike 驗證閘門、再逐項中和平台耦合,讓控制器在 headless 環境可建構。
- 寫測試時 sync try-catch 接不到 BotToast 的 async 錯誤:fire-and-forget API 的接管設計
測試裡 sync try-catch 接不到錯誤,或 fire-and-forget API 從 async gap 後拋 `LateInitializationError`。用 runZonedGuarded 同時罩 sync 與 async 失敗路徑,含 fallback 訊息 signature 設計。
- Dart test 的跨檔案 GetX 狀態污染:flaky 真因不是 fail 訊息上的那個 test
`flutter test` 整套跑隨機 fail、單獨跑該 file 卻 100% 過。根因是 dart test runner 同 process 內 GetX state 跨 file 污染,fail 位置看 `+N -1` 累計而非訊息標示的 test。