Mobile App Testing 入門 — Appium vs Detox 怎麼選、跨平台策略、device farm

「網站測試我會、mobile 也差不多吧」是新人最大的誤解。Mobile testing 是另一個物種 — 不同 OS、不同裝置尺寸、不同網路、推播、相機、權限、deep link… 痛點是 web 的 3-5 倍。這篇講 QA 從 web 跨到 mobile 該注意什麼。

三種 App 你要先分清楚

flowchart TD
    App[Mobile App] --> Native[原生 Native]
    App --> Cross[跨平台 Cross-platform]
    App --> Hybrid[Hybrid / WebView]

    Native --> N1[iOS: Swift<br>Android: Kotlin/Java]
    Cross --> C1[React Native<br>Flutter<br>Xamarin]
    Hybrid --> H1[Cordova / Ionic<br>Capacitor<br>WebView 包裝]

    style Native fill:#06b6d4,color:#fff
    style Cross fill:#10b981,color:#fff
    style Hybrid fill:#a855f7,color:#fff
類型 例子 測試難度 自動化選
Native Twitter (early)、Uber、銀行 App 高(要兩套) XCUITest + Espresso 或 Appium
Cross-platform Discord、Bloomberg、Meta Detox(RN)/ Patrol(Flutter)/ Appium
Hybrid 多數中小 App Appium / 通用 web 工具

測試前先問:「我們是哪種 App?」 — 工具選錯後面會吐血。

Mobile vs Web 的 5 大差異

mindmap
  root((Mobile<br>Testing<br>痛點))
    OS 碎片化
      iOS 多版本
      Android 廠商客製
      OEM 修改 UI
    硬體變數
      螢幕尺寸
      解析度
      網路 4G/5G/WiFi
      電量
    系統互動
      推播
      權限
      Deep link
      Universal link
    輸入方式
      Touch gesture
      鍵盤切換
      手寫
      Voice
    平台特性
      iOS Face ID / Touch ID
      Android 多視窗
      Background restriction
      App lifecycle

1. OS / 裝置碎片化

  • iOS:相對單純,但 iOS 16/17/18 + iPad / iPhone SE/15 Pro Max 都要測
  • Android:地獄。Samsung S24、Pixel 8、小米 14 都有自家 ROM 微調。Android 8 ~ 14 都還有人用

對策:選 top 5 機種覆蓋 80% 使用者 → 看你 Firebase Analytics 數據決定。

2. 網路情境

情境 怎麼測
慢速 4G Charles Proxy / Network Link Conditioner
切換 WiFi ↔ 4G 中途切看 reconnect
完全離線 飛航模式
不穩 / 高延遲 Throttling

3. 推播與背景

flowchart LR
    A[App 在前景] --> B[Push 進來]
    B --> C{Foreground<br>handler?}
    C -->|有| Show[顯示自訂通知]
    C -->|無| Default[OS 預設行為]

    A2[App 在背景] --> B2[Push 進來]
    B2 --> D[OS 通知區]
    D --> Tap[使用者點]
    Tap --> Open[開 App + deep link]

    style Show fill:#10b981,color:#fff
    style Default fill:#f59e0b,color:#fff
    style Open fill:#06b6d4,color:#fff

Push notification 必測: - App 開啟時收到 - App 背景時收到 - App 完全 kill 時收到 - 點通知開到正確頁面(deep link) - 通知 payload 含特殊字元 / emoji - 連續多則通知 batching

4. 權限 flow

首次安裝 → 開 App → 觸發功能(拍照/位置/推播)→
彈權限 → 使用者允許 / 拒絕 / 「不要再問」→
不同分支 UX 都要測

權限拒絕後的 fallback path 常被忽略

5. App lifecycle

  • Foreground → Background(按 Home)
  • Background → Foreground 回來
  • Memory pressure 被 kill
  • Cold start vs Warm start
  • 來電中、收到簡訊

測試:跑流程到一半切走 / 切回,看狀態保留嗎?

自動化工具二選一:Appium vs Detox

flowchart TD
    Choose{你的 App<br>類型?} --> RN[React Native]
    Choose --> Native_[Native iOS/Android]
    Choose --> Flutter[Flutter]
    Choose --> Hybrid_[Hybrid]

    RN --> Detox["Detox<br>(灰盒、最快)"]
    Native_ --> XCUI[XCUITest + Espresso]
    Native_ --> Appium_["Appium<br>(跨平台統一)"]
    Flutter --> Patrol[Patrol / Flutter Driver]
    Hybrid_ --> Appium2[Appium]

    style Detox fill:#10b981,color:#fff
    style Appium_ fill:#06b6d4,color:#fff
    style Appium2 fill:#06b6d4,color:#fff
    style Patrol fill:#a855f7,color:#fff

Appium — 通用之王

優點: - 跨平台同一份 code 跑 iOS + Android - 支援 Native / Cross / Hybrid - 業界標準、社群大、工作機會多 - 可寫 Python / Java / JS / Ruby

缺點: - 慢(每步都要過 WebDriver protocol) - Selector 不穩定(要用 Accessibility ID) - iOS 跑特別慢 - 環境配置複雜(Xcode + Android SDK + Node + Java...)

Detox — React Native 神器

優點: - 灰盒測試(跟 app process 同步) - 比 Appium 快 5-10 倍 - Auto-sync — 不用自己 wait - React Native 一等公民

缺點: - 只支援 RN - iOS Simulator + Android Emulator only(不能跑真機) - 學習曲線比 Appium 陡

我的選擇規則

你的情境
RN App + 內部團隊 Detox(速度、穩定)
Native App + 兩位專家分 iOS/Android XCUITest + Espresso
中小團隊、要跨平台共用 Appium
Flutter Patrol 或 Flutter Driver
Hybrid / WebView Appium(其中 webview 部分用 Selenium)

Appium 快速體驗

環境

brew install node android-platform-tools
npm install -g appium
appium driver install xcuitest
appium driver install uiautomator2

第一支 test(Python)

from appium import webdriver
from appium.options.android import UiAutomator2Options
from appium.webdriver.common.appiumby import AppiumBy

options = UiAutomator2Options()
options.platform_name = 'Android'
options.device_name = 'Pixel_8_API_34'
options.app = '/path/to/app.apk'
options.automation_name = 'UiAutomator2'

driver = webdriver.Remote('http://localhost:4723', options=options)

# 選元素優先順序:
# 1. Accessibility ID (跨平台、最穩)
login_btn = driver.find_element(AppiumBy.ACCESSIBILITY_ID, 'login_button')
login_btn.click()

# 2. ID (Android resource-id / iOS name)
email = driver.find_element(AppiumBy.ID, 'email_input')
email.send_keys('[email protected]')

# 3. XPath (最後手段)
# 不要常用 - 慢、脆弱

# 開 Appium server
appium

# 另一個 terminal 跑 test
python tests/test_login.py

Detox 快速體驗(RN)

// e2e/login.test.js
describe('Login', () => {
  beforeEach(async () => {
    await device.reloadReactNative();
  });

  it('logs in successfully', async () => {
    await element(by.id('email-input')).typeText('[email protected]');
    await element(by.id('password-input')).typeText('Pass@123');
    await element(by.id('login-button')).tap();

    await expect(element(by.text('Welcome'))).toBeVisible();
  });
});

跑:

detox build -c ios.sim.debug
detox test -c ios.sim.debug

跨平台 selector 策略

flowchart LR
    Test[Test code] --> Strategy{選 selector}
    Strategy --> AID["accessibilityId<br>(跨平台統一)"]
    Strategy --> IOS[iOS predicate<br>or name]
    Strategy --> AND[Android resource-id<br>or content-desc]

    AID --> Best["⭐ 推薦<br>同一個 ID 跨平台"]
    IOS --> P2[要兩套 selector]
    AND --> P3[要兩套 selector]

    style Best fill:#10b981,color:#fff
    style P2 fill:#f59e0b,color:#fff
    style P3 fill:#f59e0b,color:#fff

團隊規範

  • 跟 dev 約定每個元素加 accessibilityID="meaningful-name"
  • 命名規則:<screen>-<element>-<action>,例如 login-email-input
  • Avoid 用 visible text(i18n 換語言就壞)

Device Farm — 雲端真機

本機跑 Simulator / Emulator 不夠真實。真機很重要

服務 強項 弱項
BrowserStack UI 好、設備多
Sauce Labs 老牌、企業
AWS Device Farm 跟 AWS 整合 UI 差
Firebase Test Lab Android 強、Google 親兒子 iOS 少
LambdaTest 便宜 設備新但社群小
自架(OpenSTF) 完全可控 維護成本

新團隊推薦:BrowserStack 或 Firebase Test Lab。設備數量、穩定度最值得。

環境準備陷阱

iOS

  • Mac 必備(Xcode 只能 Mac 跑)
  • Apple Developer 帳號 ($99/yr) 真機 sign
  • Simulator 跟真機 behavior 不同(Push、Touch ID)
  • 每個 Xcode 升級可能打死 Appium driver

Android

  • Windows / Mac / Linux 都可
  • Emulator 慢、最好真機
  • 不同 OEM 行為不同(華為跟 Samsung 行為差異大)
  • ADB 偶爾掛掉要重啟

CI 整合 — 痛點最深

flowchart LR
    Push[Push code] --> Build[Build App]
    Build --> Lint[Lint / Unit]
    Lint --> SimE2E[Simulator E2E<br>每 PR]
    SimE2E --> Nightly[真機 E2E<br>每晚]
    Nightly --> Bs[BrowserStack<br>多裝置]

    style SimE2E fill:#06b6d4,color:#fff
    style Nightly fill:#a855f7,color:#fff
    style Bs fill:#10b981,color:#fff

節奏: - PR:Simulator/Emulator E2E(10-15 分鐘) - Nightly:真機 device farm(多裝置) - Release:全裝置 + 多 OS 版本

不要 PR 跑真機 — 太慢、會被罵。

反模式

  1. 本機過就 push — 你 Pixel 8 過、別人 Samsung S20 爆
  2. 跑 release build 才測 — Release / Debug 行為不同,提早遇到
  3. 不測權限 fallback — 拒絕後 app crash 上 store 退
  4. 不測 deep link — push / 廣告連進來 crash
  5. 忘了測直 / 橫排 — 旋轉 90 度爆 layout
  6. iOS only / Android only 心態 — 必須兩平台都會
  7. 不測網路差 — 高鐵上一定壞

QA 跨進 Mobile 的學習路線

flowchart TD
    Start[會 Web QA] --> S1["1) 學 Android Studio<br>+ Xcode 基礎"]
    S1 --> S2["2) 學 ADB 指令"]
    S2 --> S3["3) 手動測一個 App<br>找 20 個 bug"]
    S3 --> S4["4) Appium / Detox 二選一"]
    S4 --> S5["5) CI 整合"]
    S5 --> S6["6) Device farm 上雲"]
    S6 --> Pro[Mobile QA 中階]

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

時程:3-6 個月。

工具速查

工具 用途
Appium Inspector 看 UI element tree
Charles Proxy 攔網路流量、改 response
Stetho Android Chrome DevTools
Reactotron React Native debugger
Flipper RN / Native 通用 debugger
adb logcat Android log
Xcode Console iOS log
TestFlight iOS beta 派發
Firebase App Distribution Android beta 派發

最後

Mobile QA 痛苦但薪資 / 職缺都比純 web 多。學完之後你不只是 web QA、是「跨平台 QA 工程師」— 職涯路寬一倍。從手動測一個 App 開始,下一篇進自動化選 Appium 或 Detox。