工程筆記

在雲端 Mac 建立 iOS 無障礙回歸把關流程

在雲端 Mac 建立 iOS 無障礙回歸把關流程

一次普通的按鈕改名、圖示替換或約束調整,都可能讓 iOS 畫面失去可讀標籤、縮小點按區域,或導致文字在大字體下遭到截斷。人工巡查很難涵蓋每次提交。更可靠的做法,是在雲端 Mac 上固定模擬器與 App 狀態,使用 XCTest 執行無障礙稽核,再將失敗項目轉化為可重現的合併把關機制。

先定義把關範圍

不要一開始就遍歷整個產品。先選擇登入後首頁、核心編輯頁與提交確認頁等高頻路徑,且每個測試案例只驗證一種穩定狀態。動畫、隨機推薦、目前時間與網路回傳值都會改變元素樹,因此應在測試模式下停用,或注入固定資料。

第一輪建議檢查四類問題:

檢查項目 常見缺陷 把關處理
元素描述 圖示按鈕沒有可讀名稱 直接失敗
點按區域 控制項可見但難以點按 直接失敗
對比度 前景與背景難以區分 與設計核對後修正
文字版面 大字體下截斷或重疊 直接失敗

自動稽核負責找出機器能夠穩定判斷的問題,不能用來證明整套互動已經易於使用。閱讀順序、提示是否清楚,以及複雜手勢等項目,仍須保留人工檢查。

為測試建立確定的畫面

UI 測試最怕「相同入口,卻出現不同畫面」。App 應識別僅供測試使用的啟動參數,在啟動時清除暫存狀態、載入固定資料,並停用非必要動畫。這些參數只能改變測試環境,不得進入正式業務邏輯。

let app = XCUIApplication()
app.launchArguments = [
    "-ui-testing",
    "-reset-demo-state",
    "-disable-animations"
]
app.launchEnvironment["TEST_LOCALE"] = "zh-Hans"
app.launch()

測試資料應在 App 行程內準備,不應讓 UI 測試依賴即時 API。若需要涵蓋載入中、無資料、錯誤與正常結果,請為每種狀態建立獨立參數。如此一來,發生失敗後只需複製命令即可重現,不必等待某個遠端條件再次出現。

固定元素定位方式

不要使用按鈕標題或座標定位關鍵控制項。標題會隨本地化而改變,座標則會受視窗與字體大小影響。請為可互動元素設定語意穩定的 accessibilityIdentifier

checkoutButton.accessibilityIdentifier = "checkout.submit"
cartSummary.accessibilityIdentifier = "checkout.summary"

識別碼應描述元素職責,而不是視覺位置。footer.orangeButton 這類名稱會在版面改版後失去意義;checkout.submit 則能跨版面持續使用。

執行具針對性的 XCTest 稽核

當系統版本支援相關 API 時,可以針對已進入穩定狀態的畫面執行稽核。應先等待關鍵元素出現,再開始檢查,以免將載入期間的暫時版面誤判為缺陷。

func testCheckoutAccessibility() throws {
    let app = XCUIApplication()
    app.launchArguments = ["-ui-testing", "-reset-demo-state"]
    app.launch()

    let submit = app.buttons["checkout.submit"]
    XCTAssertTrue(submit.waitForExistence(timeout: 10))

    if #available(iOS 17.0, *) {
        try app.performAccessibilityAudit(for: [
            .sufficientElementDescription,
            .hitRegion,
            .contrast,
            .textClipped
        ])
    }
}

不要隨意建立全域忽略清單。如果確實需要暫時排除問題,應將範圍限制在明確的畫面、元素識別碼與問題類型,並在程式碼審查中註明移除條件。否則,忽略項目會逐漸演變成永久盲區。

在雲端 Mac 上固定執行條件

先檢視目前可用的模擬器裝置與執行環境,再由流水線傳入明確的 destination。不要假設每個節點都已經存在同名裝置。

xcrun simctl list devices available
xcrun simctl list runtimes

export SIM_DESTINATION='platform=iOS Simulator,name=iPhone 15,OS=17.5'

set -o pipefail
xcodebuild test \
  -project ExampleApp.xcodeproj \
  -scheme ExampleAppUITests \
  -destination "$SIM_DESTINATION" \
  -only-testing:ExampleAppUITests/AccessibilityTests \
  -resultBundlePath "$PWD/TestResults/Accessibility.xcresult"

實際執行時,應將裝置名稱與系統版本設為流水線變數,並與節點已安裝的執行環境保持一致。執行前可建立全新的模擬器;若要重複使用既有裝置,則應先關閉 App 並清除測試狀態。平行任務不得共用同一個模擬器,否則語言、權限提示與上一個測試案例留下的狀態會互相污染。

雲端 Mac 的機型與節點選擇不會改變測試設計原則。需要新增執行環境時,請在控制台確認目前可選的配置,並記錄 Xcode 版本、執行環境版本、語言與 destination,確保失敗能在相同條件下重新執行。

分層執行並處理常見誤報

每次合併請求只執行核心畫面、預設語言與一種標準字體大小,將回饋時間控制在團隊可接受的範圍內。主分支再擴充至多語言、橫向與直向、深色外觀及動態字體。不要把所有組合塞進同一個測試方法;依畫面與狀態拆分後,失敗名稱本身就能指出影響範圍。

遇到不穩定的失敗時,請依下列順序檢查:

  1. 確認關鍵元素是否已完成載入,而非只是存在於元素樹中。
  2. 比對語言、地區、字體大小、方向與外觀設定。
  3. 檢查測試資料是否曾被上一次執行修改。
  4. 單獨重新執行失敗的方法,確認問題能否穩定重現。
  5. 保存測試結果套件、執行命令與環境欄位,再判斷是產品缺陷,還是測試隔離不足。

把關規則也應分級處理。缺少描述、無法點按與文字重疊適合直接阻止合併;尚未完成設計確認的對比度問題可以先記錄,但必須指定負責人與處理期限。最終目標不是取得一份永遠全綠的報告,而是讓每次失敗都能定位到具體的畫面、狀態、元素與環境條件。

常見問題

無障礙自動稽核能完全取代人工檢查嗎?

不能。自動稽核適合找出描述缺漏、點擊區域過小、對比不足與文字截斷,但閱讀順序、操作語意及實際體驗仍需人工驗證。

為什麼本機通過,到了雲端 Mac 卻失敗?

應先比對模擬器執行環境、語言、地區、動態字級、畫面方向及測試資料。把這些條件固定為啟動參數,才能降低環境差異。

完整無障礙稽核應該在什麼時候執行?

核心畫面的快速稽核適合每次合併請求執行;包含多語言與多種字級的完整矩陣,可安排在主要分支或排程工作中執行。

獨享實體節點

讓下一次建置在雲端 Mac 上執行。

比較三種 Apple Silicon 設定,從五個海外節點中選擇適合目前工作流程的區域。

選擇租用方案