Appium
对于 iOS 开发者来说,理解 Appium的原理其实非常直观,因为它本质上是把 Xcode 的测试框架 包装成了一个 RESTful API 服务。其核心架构可以拆解为三个主要部分:Appium Client、Appium Server 和 WebDriverAgent (WDA)。
一、 Appium原理
1.1 链路通信和关键组件讲解
整个通信链路如下:
Appium Client(你的代码):发送一个 HTTP 请求(例如:点击按钮)。Appium Server(Mac 电脑):接收请求,将其翻译为 WDA 能听懂的指令。WebDriverAgent(手机端):由Appium Server通过xcodebuild启动,并在手机上运行。它接收指令,调用iOS系统的XCTest框架执行具体动作。
关键组件详解:
WebDriverAgent(WDA) —— 真正的“执行者”这是 Facebook 开发的一个开源项目。- 角色:它是一个运行在 iOS 真机上的 HTTP 服务器。
- 原理:它利用了 iOS 系统的 XCTest.framework。作为开发者你一定知道,XCTest 拥有控制 UI 元素的最高权限。WDA 就像是一个“代理人”,它常驻在手机后台,等待来自 Mac 的命令,然后调用 XCTest 的私有 API(如 XCUIApplication)来模拟点击、滑动或输入。
Appium Server—— “翻译官”- 角色:它是一个 Node.js 编写的服务。
- 原理:它实现了 WebDriver 协议(标准的浏览器自动化协议)。当你调用 driver.click() 时,Appium 会把这个动作封装成一个 JSON 格式的 POST 请求发送给 WDA。
通信桥梁:iproxy / usbmuxd。 由于 iPhone 真机运行在 USB 隔离环境,Mac 无法直接通过 IP 访问手机上的 WDA。
- 原理:
Appium会调用libimobiledevice中的工具,通过 USB 端口转发,将手机端的 8100 端口映射到 Mac 的某个端口(如 8101)。这样 Appium Server 就能像访问本地服务一样操作手机了。
- 原理:
1.2 真机运行的完整生命周期
当你点击“Start Session”时,后台发生了这些事:
- 环境检查:检查你的
xcode-select路径、UDID 是否存在、签名是否合规。 - 启动 WDA:执行类似
xcodebuild test的命令。这时你会看到手机上闪过一个白屏(WebDriverAgentRunner),然后回到主屏幕。 - 端口映射:通过
usbmuxd建立 USB 隧道。 - 注入与握手:
Appium确认能连上手机里的WDA后,会根据你提供的bundleId拉起你的目标 App。 - 保持心跳:只要你的
Session没关,WDA 就会一直以测试模式在后台运行。
二、 Appium安装文档
2.1 准备工作
# 安装appium
npm install -g appium
# 安装uiautomator2
appium driver install uiautomator2
# 安装xcuitest
appium driver install xcuitest2
3
4
5
6
2.2 配置 WebDriverAgent (核心步骤)
- 找到 WDA 路径:通常在:
~/.appium/node_modules/appium-xcuitest-driver/node_modules/appium-webdriveragent
- 找到 WDA 路径:通常在:
- 用 Xcode 打开项目: 在终端输入:
open .打开该目录,双击WebDriverAgent.xcodeproj。
- 用 Xcode 打开项目: 在终端输入:
- 配置签名 (Signing):
- 3.1 在
Xcode中选择WebDriverAgentRunner这个 Target。 - 3.2 在
Signing & Capabilities中选择你的开发者账号 (Team)。 - 3.3 修改
Bundle Identifier(加点后缀,保证全局唯一)。 - 3.4 同样对
WebDriverAgentLib重复此操作。
- 手动安装测试:
- 4.1 选择你的真机作为运行目标。
- 4.2 在
Xcode菜单栏:Product -> Test。 - 4.3 如果手机上出现了
WebDriverAgentRunner-Runner且没有崩溃,并在控制台看到ServerURLHere->http://[IP]:8100<-ServerURLHere,说明成功。 - 4.4 手机开启UI自动化,路径是: 测试手机->设置->通用->开发者->启动UI自动化 或者直接编译通用的WDA,方便测试时直接安装,这种方式比较未定,在编译前仍需要修改开发者和项目包名保持唯一。
xcodebuild clean build-for-testing -project ~/.appium/node_modules/appium-xcuitest-driver/node_modules/appium-webdriveragent/WebDriverAgent.xcodeproj -derivedDataPath ~/Downloads/appium_wda_ios -scheme WebDriverAgentRunner -destination generic/platform=iOS -allowProvisioningUpdates2.3 安装必要的辅助工具
Appium 需要一些底层的通信工具来和 iOS 协议打交道:
# 用于通过 USB 转发端口
brew install libimobiledevice
# 用于查看真机界面结构和元素定位 (非常推荐)
brew install --cask appium-inspector2
3
4
2.4. 编写/配置 Appium 启动参数 (Capabilities)
你不需要写复杂的代码,先用 Appium Inspector 连通真机,Appium Inspector下载地址:
- 启动
Appium Server:在终端输入appium。
- 启动
- 打开
Appium Inspector,在JSON Representation区域输入以下配置:
- 打开
# 使用Appium自动管理WDA
{
"platformName": "平台名称,如 Android 或 iOS",
"appium:automationName": "自动化引擎,Android 建议使用 UiAutomator2,iOS 使用 XCUITest",
"appium:deviceName": "你的iPhone名称,模拟器使用这个",
"appium:udid": "你的设备UDID",
"appium:bundleId": "你要测试的App的BundleID"
}
# 使用预编译的WDA(没有使用预安装的wDA稳定)
{
"platformName": "平台名称,如 Android 或 iOS",
"appium:platformVersion": "手机系统版本,如 26.2",
"appium:automationName": "自动化引擎,Android 建议使用 UiAutomator2,iOS 使用 XCUITest",
"appium:deviceName": "你的iPhone名称",
"appium:udid": "你的设备UDID",
"appium:bundleId": "你要测试的App的BundleID",
"appium:noReset": true,
"appium:showXcodeLog": true,
"appium:usePrebuiltWDA": true,
"appium:derivedDataPath": "xcodebuild编译的EDA路径,比如~/Downloads/appium_wda_ios",
}
# 使用预安装的WDA(适用于已经手动编译并安装WDA的情况)
{
"platformName": "平台名称,如 Android 或 iOS",
"appium:automationName": "自动化引擎,Android 建议使用 UiAutomator2,iOS 使用 XCUITest",
"appium:deviceName": "你的iPhone名称,模拟器使用这个",
"appium:udid": "你的设备UDID",
"appium:bundleId": "你要测试的App的BundleID",
"appium:usePreinstalledWDA": true,
"appium:updatedWDABundleId": "com.facebook.WebDriverAgentRunner.hz"
}
# 附加到已启动的WDA(适用于已经手动编译、安装并启动WDA的情况)
# 需要手动进行端口转发:iproxy 8100 8100 -u <DEVICE ID>
{
"platformName": "平台名称,如 Android 或 iOS",
"appium:automationName": "自动化引擎,Android 建议使用 UiAutomator2,iOS 使用 XCUITest",
"appium:deviceName": "你的iPhone名称,模拟器使用这个",
"appium:udid": "你的设备UDID",
"appium:bundleId": "你要测试的App的BundleID",
"appium:webDriverAgentUrl": "http://localhost:8100",
"appium:wdaRemotePort": 8100 #保险起见最好提供手机上WDA监听的端口号,默认是8100
}2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
⚠️ WDA 更新:每次
Xcode大版本升级,记得去appium-xcuitest-driver目录下执行git pull或重新安装driver
运行时报错WebDriverError: Could not determine Xcode version: '/Library/Developer/CommandLineTools' is not a valid Xcode path. Consider running: sudo xcode-select -s "/Applications/Xcode.app/Contents/Developer" to address this issue. when running "http://127.0.0.1:4723/session" with method "POST" 解决方案在命令行输入sudo xcode-select -s /Applications/Xcode.app/Contents/Developer即可。
2.5 重连
在测试过程中我们可能会经常重连一下手机,手机启动WDA后再Mac端通过http://localhost:8100/status接口可以查看相关的信息,sessionId 不为空表示现在正在连接着某个任务。使用Appium Inspector工具重新连接时经常能调起应用,界面没有显示连接成功,并且报设置错误的时候。解决方案:
- 在命令行运行
curl -X DELETE http://localhost:8100/session/sessionId切断连接的session - 将手机中的
WebDriverAgentRunner删除,重新启动Appium Inspector工具进行新的会话就可以了。
还有一种重连是Appium Inspector工具关闭了会话,手机还保持着WDA打开的状态,这个时候如果想重新使用Appium Inspector工具连接到手机
- 需要先通过
iproxy 8100 8100 -u <DEVICE ID>转发本地端口到手机端口,网址打开http://localhost:8100/status确认一下有没有转发成功 Appium Inspector的使用以下JSON,点击启动会话
{
"platformName": "平台名称,如 Android 或 iOS",
"appium:automationName": "自动化引擎,Android 建议使用 UiAutomator2,iOS 使用 XCUITest",
"appium:udid": "你的设备UDID",
"appium:bundleId": "你要测试的App的BundleID",
"appium:webDriverAgentUrl": "http://localhost:8100",
"appium:wdaRemotePort": 8100
}2
3
4
5
6
7
8
如果
http://localhost:8100/status打开后能看到sessionID,直接在Appium Inspector工具中选择Attach to running session,输入正确的Session ID就可以连接到手机了。