Android UI 旅程测试
android-ui-journey-testing
Android UI 旅程测试
概述
本技能概述了在 Android 应用程序上运行 XML 规范的用户旅程(User Journey)测试的标准工作流。“旅程”是一组按顺序排列的用户操作和状态断言,旨在验证端到端功能。旅程 XML 作为应用程序行为的唯一事实来源。执行器将按顺序执行 UI 交互、检查状态断言,并编写标准化的 JSON 结果报告。
适用场景
- 当需要根据 XML 测试规范评估 Android 应用程序的 UI 行为时。
- 当需要自动化多步骤用户流程(如登录、结账、导航)并验证预期结果时。
- 当需要运行验证测试并生成标准化 JSON 测试报告时。
- 当使用 ADB 命令在物理设备或模拟器上调试应用程序流程时。
工作原理
mermaid
graph TD
A[解析旅程 XML] --> B[执行操作 / 交互]
B --> C{是否成功?}
C -- 是 --> D[验证状态预期 / 断言]
C -- 否/崩溃 --> G[标记为失败并退出]
D -- 通过 --> E{是否还有后续步骤?}
D -- 失败 --> G
E -- 是 --> B
E -- 否 --> F[输出 JSON 摘要]步骤 1:解析旅程规范
读取并解析 XML 测试套件结构。根节点<journey> 定义测试用例名称,<actions> 块包含测试步骤序列。
xml
<journey name="搜索与购物车流程">
<description>验证搜索商品并将其添加到购物车是否成功。</description>
<actions>
<action>搜索苏打水</action>
<action>点击第一个搜索结果</action>
<action>验证是否显示产品详情界面</action>
</actions>
</journey>步骤 2:顺序步骤评估
按照指定的精确顺序处理每个<action> 元素。测试步骤分为两类:
#### A. 交互式操作(点击、滑动、文本输入)
使用 ADB 执行物理 UI 交互。
- 点击:点击目标元素边界的中心:
bash
adb shell input tap <x> <y>- 滑动/滚动:在指定时长内从一个坐标滑动到另一个坐标:
bash
adb shell input swipe <x1> <y1> <x2> <y2> <duration_ms>- 文本输入:在当前激活的输入框中输入文本:
bash
adb shell input text "<string>"如果元素缺失或操作无法执行,则该操作及整个旅程判定为失败。
#### B. 状态断言(预期验证)
以“验证 (verify)”、“检查 (check)”或“确保 (ensure)”开头的步骤代表状态断言。
- 在不进行交互或滚动的情况下,检查当前屏幕(使用截图或
uiautomator dump)。
- 确认所有子断言均已满足。例如,“验证应用程序是否处于主屏幕且 Logo 可见”在主屏幕未显示 或 Logo 缺失时判定为失败。
步骤 3:处理失败与崩溃
如果应用程序崩溃、退出、冻结或断言失败: 1. 立即停止旅程执行。 2. 将失败的步骤标记为FAILED。
3. 标记...
将后续所有步骤标记为 SKIPPED。
4. 记录失败的具体原因。
第 4 步:生成 JSON 报告
将执行结果格式化为标准 JSON 架构并写入输出日志。---
示例
示例 1:完整 Journey XML 规范
xml
<journey name="Login and Profile Edit">
<description>登录应用,导航至设置,并修改用户信息。</description>
<actions>
<action>验证用户名输入框是否可见</action>
<action>点击用户名输入框</action>
<action>在输入框中输入 "testuser"</action>
<action>点击密码输入框</action>
<action>在输入框中输入脱敏后的测试密码</action>
<action>点击 "Login" 按钮</action>
<action>验证主页仪表盘是否可见且显示用户头像</action>
</actions>
</journey>示例 2:标准 JSON 结果报告
json
{
"journey": "Login and Profile Edit",
"results": [
{
"action": "Verify that the username input field is visible",
"status": "PASSED",
"commands": [],
"comment": "Username input detected at bounds [100,200][980,300] via UI dump."
},
{
"action": "Tap the username input field",
"status": "PASSED",
"commands": [
"adb shell input tap 540 250"
],
"comment": "Tapped center coordinates of username input."
},
{
"action": "Type \"testuser\" into the input",
"status": "PASSED",
"commands": [
"adb shell input text \"testuser\""
],
"comment": "Username typed successfully."
},
{
"action": "Tap the password input field",
"status": "PASSED",
"commands": [
"adb shell input tap 540 370"
],
"comment": "Tapped center of password input."
},
{
"action": "Type a redacted test password into the input",
"status": "PASSED",
"commands": [
"adb shell input text \"[REDACTED_PASSWORD]\""
],
"comment": "Password typed successfully. The actual input value was not stored in the report."
},
{
"action": "Tap the \"Login\" button",
"status": "PASSED",
"commands": [
"adb shell input tap 540 500"
],
"comment": "Login button clicked."
},
{
"action": "Verify that the Home dashboard is visible and user profile photo is shown",
"status": "FAILED",
"commands": [],
"comment": "Dashboard loaded but profile photo was missing from the UI header."
}
]
}---
最佳实践
- ✅ 计算点击中心点:在解析元素边界(如
[x1,y1][x2,y2])时,始终计算中心坐标:
- ✅ 包含休眠缓冲:在交互操作(如点击按钮)后,始终添加短时间延迟(例如 1-2 秒),以确保在执行断言前布局和过渡动画已完成渲染。
- ✅ 快速失败:一旦遇到第一个失败项,立即停止测试。在失败后继续执行会导致结果无效。
- ✅ 安全地记录精确命令:在 JSON 输出列表中包含非敏感的原始命令(如
adb shell input tap)以便于诊断。对输入到密码、OTP、令牌、支付或个人数据字段的文本进行脱敏处理;切勿将实际密钥持久化在报告、CI 日志或共享产物中。
局限性
- 解析器仅评估
- 静态屏幕层级(例如
uiautomator dump)。除非显式执行滚动操作,否则需要滚动的元素会被标记为不可见。
- 非标准 UI 组件(如自定义 OpenGL 画布视图)无法通过标准辅助功能树读取,可能需要截图分析或硬编码点击映射表。
- 通过 ADB 发送的按键事件和文本输入在某些模拟器镜像上不会触发标准软键盘事件,这可能会导致输入验证问题。
相关技能
@android-cli- 通用 CLI 工具语法、包安装及设备查询。
@android_ui_verification- 用于通用 UI 检查的直接 ADB 脚本模板。