Appium 移动端自动化测试:一套脚本跑通 iOS 和 Android_千锋教育

来源:千锋教育
发布时间:2026-06-05 06:12:16

千锋教育品牌logo

01 Appium 的核心架构:为什么它能跨平台

理解 Appium 之前,先搞清楚一个根本问题:为什么移动端自动化比 Web 端难?

Web 端有统一的 DOM 结构,Selenium 通过 WebDriver 协议操控浏览器。但 iOS 和 Android 是两套完全不同的系统:不同的渲染引擎、不同的控件体系、不同的交互方式。

Appium 的解决方案:不直接操控设备,而是翻译指令。

text
你的测试脚本
    ↓(WebDriver 协议)
Appium Server
    ↓(翻译为平台原生命令)
├── iOS:XCUITest(Apple 官方测试框架)
└── Android:UiAutomator2 / Espresso(Google 官方测试框架)

Before:用 Xcode Instruments 测 iOS,用 Espresso 测 Android,两套代码,两套维护。

After:用 Appium 写一套脚本,Server 自动翻译为各平台的原生命令。

Appium 2.0 的架构改进:

特性Appium 1.xAppium 2.0
驱动安装内置插件化,按需安装
扩展性有限支持自定义插件
多会话麻烦原生支持
维护整体升级驱动独立升级

Appium 不是另一套测试框架,是翻译官。你用一种语言表达,它翻译成两种系统都能听懂的指令。

---

02 环境搭建:2026年最省心的配置方案

Appium 环境搭建历来是新手噩梦。Appium 2.0 大幅简化了流程。

Android 端准备:

bash
<div style="margin:24px 0;border:1px solid #E3F2FD;border-radius:8px;background:#FAFAFA;overflow:hidden;"><div style="display:flex;align-items:center;gap:12px;padding:12px 20px;background:linear-gradient(135deg,#E3F2FD,#BBDEFB);"><span style="width:36px;height:36px;background:#2196F3;color:#fff;border-radius:50%;display:inline-flex;align-items:center;justify-content:center;font-weight:bold;font-size:16px;flex-shrink:0;">1. </span><span style="font-size:17px;font-weight:700;color:#1565C0;">安装 JDK 17</span></div><div style="padding:16px 20px;"></div></div>
<div style="margin:24px 0;border:1px solid #E3F2FD;border-radius:8px;background:#FAFAFA;overflow:hidden;"><div style="display:flex;align-items:center;gap:12px;padding:12px 20px;background:linear-gradient(135deg,#E3F2FD,#BBDEFB);"><span style="width:36px;height:36px;background:#2196F3;color:#fff;border-radius:50%;display:inline-flex;align-items:center;justify-content:center;font-weight:bold;font-size:16px;flex-shrink:0;">2. </span><span style="font-size:17px;font-weight:700;color:#1565C0;">安装 Android SDK(通过 Android Studio)</span></div><div style="padding:16px 20px;"></div></div>
<div style="margin:24px 0;border:1px solid #E3F2FD;border-radius:8px;background:#FAFAFA;overflow:hidden;"><div style="display:flex;align-items:center;gap:12px;padding:12px 20px;background:linear-gradient(135deg,#E3F2FD,#BBDEFB);"><span style="width:36px;height:36px;background:#2196F3;color:#fff;border-radius:50%;display:inline-flex;align-items:center;justify-content:center;font-weight:bold;font-size:16px;flex-shrink:0;">3. </span><span style="font-size:17px;font-weight:700;color:#1565C0;">安装 Appium Doctor 检查环境</span></div><div style="padding:16px 20px;"><p>npm install -g appium-doctor</p>
<p>appium-doctor --android</p>
<div style="margin:16px 0;border-radius:8px;overflow:hidden;border:1px solid #E0E0E0;"><div style="background:#263238;color:#B0BEC5;padding:6px 16px;font-size:12px;font-family:Consolas,monospace;"><span style="text-transform:uppercase;letter-spacing:1px;">text</span></div><pre style="background:#1E272E;color:#E0E0E0;padding:16px 20px;margin:0;overflow-x:auto;font-size:14px;line-height:1.7;font-family:Consolas,"Courier New",monospace;"><code>
**iOS 端准备**(需要 Mac):</code></pre></div></div></div>
<div style="margin:24px 0;border:1px solid #E3F2FD;border-radius:8px;background:#FAFAFA;overflow:hidden;"><div style="display:flex;align-items:center;gap:12px;padding:12px 20px;background:linear-gradient(135deg,#E3F2FD,#BBDEFB);"><span style="width:36px;height:36px;background:#2196F3;color:#fff;border-radius:50%;display:inline-flex;align-items:center;justify-content:center;font-weight:bold;font-size:16px;flex-shrink:0;">1. </span><span style="font-size:17px;font-weight:700;color:#1565C0;">安装 Xcode</span></div><div style="padding:16px 20px;"></div></div>
<div style="margin:24px 0;border:1px solid #E3F2FD;border-radius:8px;background:#FAFAFA;overflow:hidden;"><div style="display:flex;align-items:center;gap:12px;padding:12px 20px;background:linear-gradient(135deg,#E3F2FD,#BBDEFB);"><span style="width:36px;height:36px;background:#2196F3;color:#fff;border-radius:50%;display:inline-flex;align-items:center;justify-content:center;font-weight:bold;font-size:16px;flex-shrink:0;">2. </span><span style="font-size:17px;font-weight:700;color:#1565C0;">安装 XCUITest 驱动</span></div><div style="padding:16px 20px;"><p>appium driver install xcuitest</p></div></div>
<div style="margin:24px 0;border:1px solid #E3F2FD;border-radius:8px;background:#FAFAFA;overflow:hidden;"><div style="display:flex;align-items:center;gap:12px;padding:12px 20px;background:linear-gradient(135deg,#E3F2FD,#BBDEFB);"><span style="width:36px;height:36px;background:#2196F3;color:#fff;border-radius:50%;display:inline-flex;align-items:center;justify-content:center;font-weight:bold;font-size:16px;flex-shrink:0;">3. </span><span style="font-size:17px;font-weight:700;color:#1565C0;">检查环境</span></div><div style="padding:16px 20px;"><p>appium-doctor --ios</p>
<div style="margin:16px 0;border-radius:8px;overflow:hidden;border:1px solid #E0E0E0;"><div style="background:#263238;color:#B0BEC5;padding:6px 16px;font-size:12px;font-family:Consolas,monospace;"><span style="text-transform:uppercase;letter-spacing:1px;">text</span></div><pre style="background:#1E272E;color:#E0E0E0;padding:16px 20px;margin:0;overflow-x:auto;font-size:14px;line-height:1.7;font-family:Consolas,"Courier New",monospace;"><code>
**安装 Appium 2.0 Server**:</code></pre></div>
<p>npm install -g appium</p>
<p>appium driver install uiautomator2  # Android 驱动</p>
<p>appium driver install xcuitest       # iOS 驱动</p>
<p>appium server                        # 启动服务</p>
<div style="margin:16px 0;border-radius:8px;overflow:hidden;border:1px solid #E0E0E0;"><div style="background:#263238;color:#B0BEC5;padding:6px 16px;font-size:12px;font-family:Consolas,monospace;"><span style="text-transform:uppercase;letter-spacing:1px;">text</span></div><pre style="background:#1E272E;color:#E0E0E0;padding:16px 20px;margin:0;overflow-x:auto;font-size:14px;line-height:1.7;font-family:Consolas,"Courier New",monospace;"><code>
**Python 客户端安装**:</code></pre></div>
<p>pip install Appium-Python-Client</p>
<div style="margin:16px 0;border-radius:8px;overflow:hidden;border:1px solid #E0E0E0;"><div style="background:#263238;color:#B0BEC5;padding:6px 16px;font-size:12px;font-family:Consolas,monospace;"><span style="text-transform:uppercase;letter-spacing:1px;">text</span></div><pre style="background:#1E272E;color:#E0E0E0;padding:16px 20px;margin:0;overflow-x:auto;font-size:14px;line-height:1.7;font-family:Consolas,"Courier New",monospace;"><code>
**验证环境**:</code></pre></div>
<p>from appium import webdriver</p></div></div>
# Android 配置
android_caps = {
    "platformName": "Android",
    "appium:deviceName": "Pixel 7",
    "appium:platformVersion": "14",
    "appium:automationName": "UiAutomator2",
    "appium:app": "/path/to/app.apk"
}

# iOS 配置(Mac 上运行)
ios_caps = {
    "platformName": "iOS",
    "appium:deviceName": "iPhone 15",
    "appium:platformVersion": "17.0",
    "appium:automationName": "XCUITest",
    "appium:app": "/path/to/app.ipa"
}

# 切换平台只需要改配置
driver = webdriver.Remote("http://127.0.0.1:4723", android_caps)

Before:搭环境花3天,报错50个,查 StackOverflow 查到崩溃。

After:Appium 2.0 + Appium Doctor,30分钟搞定环境,哪里有问题 Doctor 直接告诉你。

环境问题不值得研究。工具能自动解决的,就不要手动折腾。

---

03 元素定位:移动端与 Web 端的核心差异

Web 端用 ID、CSS Selector、XPath 定位元素。移动端的定位方式有所不同,但也有规律可循。

移动端常用定位方式:

定位方式说明AndroidiOS
Accessibility ID无障碍标识(推荐)content-descaccessibility-id
ID原生资源 IDresource-idname
XPath路径定位支持支持(较慢)
Class Name控件类名UI 组件类XCUIElementType
iOS PredicateiOS 专属谓词不支持支持
iOS Class ChainiOS 专属链式不支持支持
python
from appium.webdriver.common.appiumby import AppiumBy

<div style="margin:24px 0;border:1px solid #E3F2FD;border-radius:8px;background:#FAFAFA;overflow:hidden;"><div style="display:flex;align-items:center;gap:12px;padding:12px 20px;background:linear-gradient(135deg,#E3F2FD,#BBDEFB);"><span style="width:36px;height:36px;background:#2196F3;color:#fff;border-radius:50%;display:inline-flex;align-items:center;justify-content:center;font-weight:bold;font-size:16px;flex-shrink:0;">1. </span><span style="font-size:17px;font-weight:700;color:#1565C0;">Accessibility ID(跨平台推荐)</span></div><div style="padding:16px 20px;"><p>element = driver.find_element(AppiumBy.ACCESSIBILITY_ID, "login_button")</p></div></div>
<div style="margin:24px 0;border:1px solid #E3F2FD;border-radius:8px;background:#FAFAFA;overflow:hidden;"><div style="display:flex;align-items:center;gap:12px;padding:12px 20px;background:linear-gradient(135deg,#E3F2FD,#BBDEFB);"><span style="width:36px;height:36px;background:#2196F3;color:#fff;border-radius:50%;display:inline-flex;align-items:center;justify-content:center;font-weight:bold;font-size:16px;flex-shrink:0;">2. </span><span style="font-size:17px;font-weight:700;color:#1565C0;">Android 专用:resource-id</span></div><div style="padding:16px 20px;"><p>element = driver.find_element(AppiumBy.ID, "com.example.app:id/username")</p></div></div>
<div style="margin:24px 0;border:1px solid #E3F2FD;border-radius:8px;background:#FAFAFA;overflow:hidden;"><div style="display:flex;align-items:center;gap:12px;padding:12px 20px;background:linear-gradient(135deg,#E3F2FD,#BBDEFB);"><span style="width:36px;height:36px;background:#2196F3;color:#fff;border-radius:50%;display:inline-flex;align-items:center;justify-content:center;font-weight:bold;font-size:16px;flex-shrink:0;">3. </span><span style="font-size:17px;font-weight:700;color:#1565C0;">XPath(跨平台,但慢)</span></div><div style="padding:16px 20px;"><p>element = driver.find_element(AppiumBy.XPATH, '//android.widget.EditText[@text="用户名"]')</p></div></div>
<div style="margin:24px 0;border:1px solid #E3F2FD;border-radius:8px;background:#FAFAFA;overflow:hidden;"><div style="display:flex;align-items:center;gap:12px;padding:12px 20px;background:linear-gradient(135deg,#E3F2FD,#BBDEFB);"><span style="width:36px;height:36px;background:#2196F3;color:#fff;border-radius:50%;display:inline-flex;align-items:center;justify-content:center;font-weight:bold;font-size:16px;flex-shrink:0;">4. </span><span style="font-size:17px;font-weight:700;color:#1565C0;">iOS 专用:Predicate</span></div><div style="padding:16px 20px;"><p>element = driver.find_element(AppiumBy.IOS_PREDICATE, "label == '登录' AND type == 'XCUIElementTypeButton'")</p></div></div>
<div style="margin:24px 0;border:1px solid #E3F2FD;border-radius:8px;background:#FAFAFA;overflow:hidden;"><div style="display:flex;align-items:center;gap:12px;padding:12px 20px;background:linear-gradient(135deg,#E3F2FD,#BBDEFB);"><span style="width:36px;height:36px;background:#2196F3;color:#fff;border-radius:50%;display:inline-flex;align-items:center;justify-content:center;font-weight:bold;font-size:16px;flex-shrink:0;">5. </span><span style="font-size:17px;font-weight:700;color:#1565C0;">iOS 专用:Class Chain</span></div><div style="padding:16px 20px;"><p>element = driver.find_element(AppiumBy.IOS_CLASS_CHAIN, "**/XCUIElementTypeButton[<code style="background:#F3E5F5;color:#6A1B9A;padding:1px 6px;border-radius:3px;font-size:0.9em;font-family:Consolas,monospace;">label == '登录'</code>]")</p></div></div>
## 04 跨平台测试策略:写一次跑两次

真正的跨平台不是"一套代码硬跑两个平台",而是**合理的抽象层设计**。

**Page Object Model(页面对象模式)**:

base_page.py - 跨平台基类

class BasePage:

def __init__(self, driver):

self.driver = driver

def find(self, locator):

return self.driver.find_element(*locator)

def click(self, locator):

self.find(locator).click()

def type_text(self, locator, text):

self.find(locator).clear()

self.find(locator).send_keys(text)

login_page.py - 登录页(平台差异在这里处理)

class LoginPage(BasePage):

Android 定位器

ANDROID = {

"username": (AppiumBy.ID, "com.example.app:id/username"),

"password": (AppiumBy.ID, "com.example.app:id/password"),

"login_btn": (AppiumBy.ID, "com.example.app:id/login"),

}

iOS 定位器

IOS = {

"username": (AppiumBy.ACCESSIBILITY_ID, "username_field"),

"password": (AppiumBy.ACCESSIBILITY_ID, "password_field"),

"login_btn": (AppiumBy.ACCESSIBILITY_ID, "login_button"),

}

def __init__(self, driver, platform):

super().__init__(driver)

self.locators = self.ANDROID if platform == "android" else self.IOS

def login(self, username, password):

self.type_text(self.locators["username"], username)

self.type_text(self.locators["password"], password)

self.click(self.locators["login_btn"])

text

**测试用例**:

import pytest

@pytest.fixture(params=["android", "ios"])

def login_page(request):

platform = request.param

caps = ANDROID_CAPS if platform == "android" else IOS_CAPS

driver = webdriver.Remote(SERVER_URL, caps)

yield LoginPage(driver, platform)

driver.quit()

def test_login_success(login_page):

login_page.login("testuser", "password123")

验证登录成功(跨平台断言)

assert is_logged_in(login_page.driver)

text

**Before**:Android 和 iOS 各写一套测试用例,改业务逻辑要改两遍。

**After**:业务逻辑写一遍,定位器分开管理。改逻辑一处搞定,改定位器互不影响。

<blockquote style="margin:16px 0;padding:12px 20px;background:#F5F5F5;border-left:4px solid #9E9E9E;color:#616161;font-style:italic;border-radius:0 6px 6px 0;">跨平台测试的核心不是技术,是抽象。把"变的部分"和"不变的部分"分开,维护成本降一半。</blockquote>

---

## 05 实战避坑:Appium 最常见的6个坑

**坑1**:元素定位不到 → 用 Appium Inspector 检查元素属性

Appium 2.0 Inspector

appium inspector

text

**坑2**:隐式等待不够导致不稳定 → 用显式等待

from appium.webdriver.common.appiumby import AppiumBy

from selenium.webdriver.support.ui import WebDriverWait

from selenium.webdriver.support import expected_conditions as EC

element = WebDriverWait(driver, 10).until(

EC.presence_of_element_located((AppiumBy.ACCESSIBILITY_ID, "submit"))

)

text

**坑3**:真机连接不稳定 → 检查 adb devices / idevice list

Android

adb devices

iOS

xcrun xctrace list devices

text

**坑4**:键盘弹不出来 → 使用 `send_keys` 前 `click` 输入框

input_field.click() # 先点击获取焦点

input_field.send_keys("文本")

text

**坑5**:上下文切换(WebView 混合应用)

获取所有上下文

contexts = driver.contexts

切换到 WebView

driver.switch_to.context("WEBVIEW_com.example.app")

切回原生

driver.switch_to.context("NATIVE_APP")

text

**坑6**:手势操作(滑动、长按)

from appium.webdriver.common.touch_action import TouchAction

向上滑动

TouchAction(driver).press(x=500, y=1500).move_to(x=500, y=500).release().perform()

长按

TouchAction(driver).long_press(element).release().perform()

声明:本站部分稿件版权来源于网络,如有侵犯版权,请及时联系我们。

相关推荐

  • Appium 移动端自动化测试:一套脚本跑通 iOS 和 Android_千锋教育
  • 测试行业10年变迁:从点点点到测试开发_千锋教育
  • 软件测试工程师职业幸福感提升:从“背锅侠”到“价值创造者”_千锋教育
  • 千锋教育课程更新机制:3个月内淘汰30%旧内容,福州学员为什么能半年入行?_千锋教育
  • 移动端性能测试:Android Profiler与Instruments实战,数据造假让Bug无处遁形_千锋教育
  • 软件测试工程师职业目标设定方法_千锋教育