Appium 移动端 UI 自动化测试入门

FreeGuideOnline 最新 2026-07-08

mermaid flowchart LR A[测试脚本 (Python/Java...)] --> B[Appium Server] B --> C[UiAutomator2 服务器 (Android)] B --> D[XCUITest 服务器 (iOS)]


1. **测试脚本**:通过 Appium 客户端发送 HTTP 请求到 Appium 服务器,请求遵循 JSON Wire Protocol。
2. **Appium 服务器**:基于 Node.js 实现的 HTTP 服务器,翻译并转发命令给目标设备的自动化引擎。
3. **设备端引擎**:
    - Android:在设备上运行 **UiAutomator2** 服务,执行具体的点击、滑动等操作。
    - iOS:通过 **XCUITest** 框架与设备上的应用交互。

这种架构使得一台 Appium 服务器可以远程控制多台真机或模拟器,非常适合分布式测试执行。

## 环境准备(适用于 Android)

### 安装 Appium 环境

选择 **Appium Desktop**(图形化界面)或命令行工具 `appium`。推荐初学者从桌面版开始。

1. **下载 Appium Desktop**  
   访问 [GitHub Releases](https://github.com/appium/appium-desktop/releases) 页面,下载适合你操作系统的安装包并安装。

2. **(可选) 安装 Node.js 及 Appium 命令行**  
   如果你希望使用 CLI 方式启动服务器:
   ```bash
   npm install -g appium
   appium driver install uiautomator2  # 安装 Android 驱动

Android 测试环境配置

  1. 安装 JDK 8 或以上版本,并配置 JAVA_HOME 环境变量。
  2. 安装 Android Studio,确保包含 Android SDK Platform-Tools 和至少一个系统镜像。
  3. 设置 ANDROID_HOME 环境变量,指向 SDK 路径(如 ~/Android/Sdk),并将 $ANDROID_HOME/platform-tools$ANDROID_HOME/tools 加入 PATH
  4. 创建 Android 模拟器(AVD)或准备一台开启了 USB 调试的真机。连接后运行 adb devices 确认设备已识别。

iOS 测试环境配置(仅针对 macOS)

  • 安装 Xcode 及命令行工具,配置开发者证书。
  • Appium 需要 Carthage 依赖管理工具:brew install carthage
  • 对于真机测试,还需要安装 ios-deploynpm install -g ios-deploy
  • 模拟器可直接使用,无需额外配置。

第一个测试脚本(Python + 计算器 App)

以下示例使用 Python 调用 Appium 来自动化 Android 原生计算器,执行简单的加法并验证结果。

安装 Python 客户端

pip install Appium-Python-Client

准备待测应用

使用 Android 系统自带的计算器应用(不同系统包名稍有差异,本示例使用原生 Android 计算器 com.android.calculator2)。确保模拟器或真机上计算器 App 已存在。

启动 Appium 服务器

打开 Appium Desktop,点击「Start Server」使用默认参数启动服务器(http://127.0.0.1:4723)。
如果使用 CLI,直接执行 appium 命令。

编写测试脚本

from appium import webdriver
from appium.webdriver.common.appiumby import AppiumBy
import time

# 配置 Desired Capabilities
desired_caps = {
    'platformName': 'Android',
    'deviceName': 'emulator-5554',          # 可通过 adb devices 获取
    'platformVersion': '13.0',
    'appPackage': 'com.android.calculator2',
    'appActivity': '.Calculator',
    'automationName': 'UiAutomator2',
    'noReset': True                         # 不重置应用数据
}

# 创建会话
driver = webdriver.Remote('http://localhost:4723', desired_caps)
time.sleep(3)  # 等待界面加载

# 定位元素并执行加法:5 + 3 = 8
digit_5 = driver.find_element(AppiumBy.ID, "com.android.calculator2:id/digit_5")
digit_5.click()

plus_btn = driver.find_element(AppiumBy.ACCESSIBILITY_ID, "plus")
plus_btn.click()

digit_3 = driver.find_element(AppiumBy.ID, "com.android.calculator2:id/digit_3")
digit_3.click()

equal_btn = driver.find_element(AppiumBy.ACCESSIBILITY_ID, "equals")
equal_btn.click()

# 获取结果并断言
result = driver.find_element(AppiumBy.ID, "com.android.calculator2:id/result")
assert result.text == "8", f"Expect 8, but got {result.text}"

print("测试通过!")

driver.quit()

代码解读

  • Desired Capabilities:告诉 Appium 服务器要连接的设备、平台以及应用入口信息。
  • 会话创建:webdriver.Remote 返回一个客户端对象,后续所有操作都由它代理。
  • 元素定位:使用 IDACCESSIBILITY_ID(推荐)唯一定位控件。Accessibility ID 相当于元素的 content-desc 属性,比 ID 更稳定。
  • 操作:click() 点击,text 获取文本。
  • 断言:验证结果是否符合预期。

元素定位与 Appium Inspector

元素定位是 UI 自动化的基石,Appium 提供了强大的 Inspector 工具来简化定位过程。

使用 Appium Inspector

  1. 确保 Appium 服务器正在运行。
  2. 打开 Inspector,填入与测试脚本相同的 Desired Capabilities。
  3. 点击「Start Session」启动检查器。应用界面截图会显示在左侧,右侧是元素树和属性面板。
  4. 点击界面上的任何元素,即可看到它的所有属性:resource-idcontent-descclassxpath 等。

常用定位策略

策略 使用方法 推荐程度 说明
Accessibility ID AppiumBy.ACCESSIBILITY_ID, "plus" ⭐⭐⭐⭐⭐ 对应 content-desc,最稳定,跨平台通用
ID AppiumBy.ID, "..digit_5" ⭐⭐⭐⭐ 利用 resource-id,唯一性较好
Class Name AppiumBy.CLASS_NAME, "android.widget.Button" ⭐⭐ 多个同类元素时需进一步过滤
XPath AppiumBy.XPATH, "//android.widget.Button[1]" ⭐⭐ 灵活但性能稍差,结构变动易失效
Android UIAutomator new UiSelector().text("5") ⭐⭐⭐ 仅限 Android,功能强大
iOS Predicate String name == "plus" ⭐⭐⭐⭐ 仅限 iOS,类似于查询语句

最佳实践:优先让开发人员在控件上添加有意义的 content-descaccessibilityIdentifier,然后用 Accessibility ID 定位。

常用操作与等待机制

基础手势

# 点击
element.click()

# 输入文本
element.send_keys("hello")

# 滑动(屏幕坐标滑动)
driver.swipe(start_x, start_y, end_x, end_y, duration=800)

# 将元素滑动到可见区域 (仅Android)
driver.execute_script("mobile: scroll", {"element": element.id})

# 后退
driver.back()

获取属性与状态

text = element.text
enabled = element.is_enabled()
displayed = element.is_displayed()
location = element.location   # {'x': x, 'y': y}
size = element.size           # {'width': w, 'height': h}

显式等待(推荐)

避免使用固定的 time.sleep(),引入 WebDriverWait 等待特定条件成立。

from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

wait = WebDriverWait(driver, 10)
result_element = wait.until(EC.presence_of_element_located((AppiumBy.ID, "result")))

常用的预期条件:visibility_of_element_locatedelement_to_be_clickabletext_to_be_present_in_element 等。

隐式等待

设置一个全局等待时间,当查找元素时如果找不到,会轮询等待直到超时。

driver.implicitly_wait(5)   # 单位秒

注意:隐式等待和显式等待一般不要混用,以免造成不可预期的等待时间。

进阶话题

处理混合应用与 WebView

如果应用内嵌了 WebView(网页内容),需要切换上下文才能控制页面中的元素。

  1. 获取所有可用上下文:
    contexts = driver.contexts
    # 通常包括:NATIVE_APP, WEBVIEW_xxx
    
  2. 切换到 WebView 上下文:
    driver.switch_to.context('WEBVIEW_com.example')
    
  3. 此时你可以使用标准的 WebDriver 方法定位网页元素(如 idcss selector)。
  4. 操作完成后切回原生:
    driver.switch_to.context('NATIVE_APP')
    

集成测试框架(pytest)

将 Appium 测试融入测试框架,方便管理和报告。

import pytest
from appium import webdriver

@pytest.fixture(scope="module")
def driver():
    caps = { ... }
    d = webdriver.Remote('http://localhost:4723', caps)
    yield d
    d.quit()

def test_add(driver):
    driver.find_element(AppiumBy.ID, "digit_2").click()
    # ... 执行操作与断言

并发测试

Appium 本身支持多会话,你可以用 Selenium Grid 或者 Appium Grid 来管理多个设备并行执行测试。结合 pytest-xdist 等插件,可以显著缩短测试执行时间。

常见问题与调试技巧

  1. 连接报错:Could not find a connected Android device

    • 检查 adb devices 是否列出设备。
    • 确认 USB 调试已开启,授权了该计算机。
  2. 元素定位失败(NoSuchElementException)

    • 使用 Inspector 确认元素是否在当前页面。
    • 增加显式等待,确保元素已渲染完毕。
    • 尝试不同的定位策略,如从 ID 改为 Accessibility ID。
  3. 操作无效(点击没反应)

    • 元素可能被其他图层遮挡,尝试先滑动屏幕使其可见。
    • 有些控件需要先获得焦点,尝试 element.click() 前执行 element.send_keys("")(仅 Android 某些场景)。
  4. 调试利器:截图与日志

    driver.save_screenshot("error.png")  # 保存当前屏幕截图