GUI 重試機制與異常處理

應對全委新系統的延遲策略

Day 10 自動化培訓課程

課程大綱 (Agenda)

  • 系統延遲的痛點分析
  • 拋棄無效的等待:Sleep 的陷阱
  • 核心策略:動態輪詢 (Polling)
  • 容錯處理:重試迴圈 (Retry Loop)
  • 實戰解析:三層式狀態檢查
  • 進階技巧:指數退避算法
  • 異常紀錄與通報機制
  • 最佳實踐總結

為什麼自動化腳本會卡死?

在操作全委新系統時,腳本經常因為找不到按鈕或點擊無效而中斷。這通常不是程式寫錯,而是環境變數造成的。

  • 網路波動: 伺服器響應時間不固定。
  • 資料運算延遲: 報表產出或資料查詢需要較長的時間。
  • 前端渲染過渡: 畫面正在 Loading,按鈕已存在但處於不可點擊 (Disabled) 狀態。

常見延遲情境解析

檔案下載等待

匯出對帳單或結帳報表時,系統準備檔案的時間由 3 秒到 30 秒不等,取決於資料量大小。

複雜查詢過濾

輸入多重條件查詢資產損益時,前端 UI 會短暫凍結,直到後端回傳完整 JSON 資料。

批次確認審核

執行整批匯款或撥轉時,系統需要逐筆檢核,導致「確認」按鈕延遲亮起。

絕對避免:死板的 Sleep

新手工程師最愛用的 Sleep(5000) 是自動化維護的夢魘。

為什麼不好?

  • 浪費時間: 如果系統 1 秒就反應,剩下 4 秒就是純浪費。
  • 依然不穩定: 如果系統今天塞車花了 6 秒,腳本依然會報錯崩潰。
  • 效能黑洞: 大量使用會讓整體流程執行時間成倍增加。

解決方案:動態輪詢與超時

我們應該告訴腳本:「最多等 10 秒,只要條件一滿足,立刻執行下一步。」

Wait For Condition (Time-out 機制)

設定一個最大容忍時間 (Timeout)。
腳本會以極短的頻率 (例如每 0.5 秒) 檢查目標元素。
發現目標 $\rightarrow$ 提早結束等待,繼續執行。
超時未發現 $\rightarrow$ 拋出 TimeoutException,進入異常處理。

容錯架構:重試迴圈

網路請求可能會丟包,點擊動作偶爾會被阻擋。我們需要包裝一層 Try-Catch-Retry 邏輯。

  1. 設定最大重試次數 (例如 3 次)。
  2. 嘗試執行動作 (點擊 / 讀取)。
  3. 成功: 跳出迴圈,繼續流程。
  4. 失敗 (Catch Error):
    • 記錄錯誤日誌。
    • 暫停一小段時間 (Cool-down)。
    • 重新執行步驟 2 (直到達到最大重試次數)。

實戰解析

應對全委新系統的「三層式」狀態檢核

第一層:DOM 元素是否存在?

在操作前,首先確認網頁的 DOM 樹中是否已經載入該按鈕或欄位。

情境探討:

網頁剛跳轉時,DOM 還在構建。此時試圖獲取「查詢餘額」按鈕,會直接引發 NoSuchElementException

應對策略:

使用 Wait.Until(ElementExists)
注意: 元素存在「不代表」可以直接點擊,它可能被隱藏或是透明的。

第二層:狀態是否可點擊?

解決「按鈕在畫面上,但按了沒反應」的靈異現象。

  • IsVisible (可見性): 元素不能被 CSS (display: none) 隱藏。
  • IsEnabled (啟用中): 尚未填完必填欄位前,系統的「送出」按鈕通常帶有 disabled 屬性。
  • 策略: 必須使用 Wait.Until(ElementToBeClickable) 作為點擊前的最後守門員。

第三層:結果驗證 (Validation)

點擊沒有報錯,不代表系統已經處理完畢。重試機制的關鍵在於確認結果

驗證指標 (Indicators of Success):

  • URL 變更: 點擊後是否跳轉到預期的路由網址?
  • 特定元素出現: 畫面上是否彈出「上傳成功」或「資料已儲存」的提示框 (Toast/Modal)?
  • 如果驗證失敗: 觸發 Retry 機制,重新定位元素並再次點擊。

進階:指數退避 (Exponential Backoff)

當系統發生嚴重雍塞時,連續快速地重試只會給伺服器帶來更大壓力,甚至觸發防火牆阻擋 (DDoS 防護)。

聰明的重試間距: 每次失敗後,等待的時間成倍數增長。

  • 第一次失敗:等待 2 秒後重試。
  • 第二次失敗:等待 4 秒後重試。
  • 第三次失敗:等待 8 秒後重試。
  • 超過最大上限 $\rightarrow$ 判定為系統死機,終止自動化並發出警報。

異常紀錄:留下犯罪現場

當所有重試機制都耗盡,自動化腳本必須優雅地結束,並提供足夠的除錯資訊。

  • 全螢幕截圖: 捕捉死機瞬間的畫面。
  • DOM 結構保存: 幫助分析前端是否改版。
  • 即時通報: 透過 Email 或通訊軟體發送錯誤報告給負責人。

綜合案例:自動下載結帳報表

將我們今天學到的機制串聯起來:

[Step 1] 啟動輪詢,等待「報表下載」按鈕 Exist & Clickable (Timeout: 15s)

[Step 2] 執行 Click() 動作

[Step 3] 進入 Validation 迴圈,檢查預設下載資料夾是否有 .xls 新檔案產生。

> 發現 5 秒內無檔案產生,觸發 Catch。

[Step 4] 執行 Retry,退避 2 秒後,重新點擊下載按鈕。

[Step 5] Validation 成功,寫入 Log 並進入下一個自動化環節。

最佳實踐總結 (Best Practices)

  • 丟掉 Sleep: 全面改用動態輪詢 (Polling) 與顯式等待 (Explicit Wait)。
  • 防禦性編程: 永遠假設網路會延遲、按鈕會失效,包裝好 Try-Catch。
  • 溫柔地重試: 導入指數退避,保護系統也提高腳本存活率。
  • 驗證大於點擊: 按下去不重要,確定系統狀態改變才算成功。

Q & A

感謝您的聆聽

請隨時提出您在開發自動化工具時遇到的問題