用途
该技能用于在 Android 应用上运行由 XML 指定的用户旅程(User Journey)测试。一个“旅程”是一组按顺序排列的用户操作与状态断言,用于验证端到端功能。旅程 XML 是应用行为的唯一事实来源。执行器按顺序推进,执行 UI 交互、检查状态断言,并写出标准化的 JSON 结果报告。
何时使用
- 依据 XML 测试规范评估 Android 应用的 UI 行为时。
- 自动化多步骤用户流程(例如登录、结账、导航)并验证预期时。
- 运行验证测试并生成标准化 JSON 测试报告时。
- 使用 ADB 命令在真机或模拟器上调试应用流程时。
工作方式
整体流程为:解析旅程 XML → 执行操作/交互 → 判断是否成功(成功则验证状态预期/断言,失败或崩溃则标记 FAILED 并退出)→ 断言通过则判断是否还有更多步骤(有则回到执行操作,无则输出 JSON 摘要),断言失败则标记 FAILED 并退出。
步骤 1:解析旅程规范
读取并解析 XML 测试套件结构。根节点 <journey> 定义测试用例名称,<actions> 块包含测试步骤序列。
<journey name="Search and Cart Flow">
<description>Verify that searching for an item and adding it to the cart succeeds.</description>
<actions>
<action>Search for soda</action>
<action>Tap the first search result</action>
<action>Verify that the product detail screen is shown</action>
</actions>
</journey>
步骤 2:按顺序评估步骤
按指定顺序处理每个 <action> 元素。测试步骤分为两类:
A. 交互操作(点击、滑动、文本输入)
使用 ADB 执行物理 UI 交互。
- 点击:点击目标元素边界中心:
adb shell input tap <x> <y>
- 滑动/滚动:从坐标到坐标滑动并指定时长:
adb shell input swipe <x1> <y1> <x2> <y2> <duration_ms>
- 文本输入:向当前活动输入框输入文本:
adb shell input text "<string>"
如果元素缺失或操作无法执行,则该操作及整个旅程失败。
B. 状态断言(预期验证)
以 "verify"、"check" 或 "ensure" 开头的步骤表示状态断言。
检查当前屏幕(使用截图或 uiautomator dump),不进行交互或滚动。确认所有子断言均满足。例如,“Verify that the app is on the Home screen and the logo is visible” 若主屏幕未显示或 logo 缺失则失败。
步骤 3:处理失败与崩溃
如果应用崩溃、退出、卡死或断言失败:
- 立即停止旅程执行。
- 将失败步骤标记为 FAILED。
- 将后续步骤标记为 SKIPPED。
- 记录失败的确切原因。
步骤 4:生成 JSON 报告
将执行结果格式化为标准化 JSON schema,并写入输出日志。
示例
示例 1:完整旅程 XML 规范
<journey name="Login and Profile Edit">
<description>Logs into the app, navigates to settings, and changes user profile information.</description>
<actions>
<action>Verify that the username input field is visible</action>
<action>Tap the username input field</action>
<action>Type "testuser" into the input</action>
<action>Tap the password input field</action>
<action>Type a redacted test password into the input</action>
<action>Tap the "Login" button</action>
<action>Verify that the Home dashboard is visible and user profile photo is shown</action>
</actions>
</journey>
示例 2:标准 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] 时,始终计算中间坐标:x_center = (x1 + x2) / 2,y_center = (y1 + y2) / 2。
- ✅ 加入休眠缓冲:在交互操作(如按钮点击)后始终添加短暂延迟(例如 1-2 秒),让布局和过渡渲染完成后再执行断言。
- ✅ 快速失败:遇到第一个失败时立即停止测试。失败后继续会导致无效结果。
- ✅ 安全记录精确命令:在 JSON 输出列表中包含非敏感的原始命令(如 adb shell input tap)用于诊断。对输入到密码、OTP、令牌、支付或个人数据字段的文本进行脱敏;绝不在报告、CI 日志或共享产物中持久化明文机密。
限制
- 解析器仅评估静态屏幕层级(例如 uiautomator dump)。需要滚动的元素除非显式执行滚动操作,否则会被标记为不可见。
- 非标准 UI 组件(如自定义 OpenGL 画布视图)无法通过标准无障碍树读取,可能需要截图分析或硬编码点击映射。
- 通过 ADB 的按键事件和文本输入并非在所有模拟器镜像上都会触发标准软键盘事件,可能导致输入验证问题。
相关技能
- @android-cli - 通用 CLI 工具语法、包安装和设备查询。
- @android_ui_verification - 用于通用 UI 检查的直接 ADB 脚本模板。