---
title: Mobile App Testing 入門 — Appium vs Detox 怎麼選、跨平台策略、device farm
description: Mobile QA 完整入門。原生 / 跨平台 / hybrid 三種 app 差異、Appium vs Detox 取捨、跟 Web testing 不同的坑、雲端 device farm 選擇。
category: automation
tags: [mobile, appium, detox, ios, android, device-farm]
date: 2026-06-11
---

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

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

## 三種 App 你要先分清楚

```mermaid
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 大差異

```mermaid
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. 推播與背景

```mermaid
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

```mermaid
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 快速體驗

### 環境

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

### 第一支 test（Python）

```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('test@example.com')

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

### 跑

```bash
# 開 Appium server
appium

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

## Detox 快速體驗（RN）

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

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

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

跑：

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

## 跨平台 selector 策略

```mermaid
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 整合 — 痛點最深

```mermaid
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 的學習路線

```mermaid
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。
