06-鸿蒙系统 uitest UI 自动化指南

摘要 :本文系统讲解鸿蒙 HarmonyOS 的命令行 UI 自动化工具 uitest。涵盖 uiInput 事件注入(点击/滑动/输入/按键)、dumpLayout 控件树解析与基于属性的精准定位、uiRecord 录制回放、等待与断言机制、多设备 CI/CD 集成、常见报错排查等。配套可直接复用的 PowerShell 自动化脚本模板,助你从"操作脚本"进阶到"可落地的自动化工程"。

关键词:鸿蒙测试、HarmonyOS、uitest、UI 自动化、dumpLayout、控件树、hdc、回归测试、uiInput

适用对象:想做控件级、确定性 UI 自动化 (而非纯随机压测)的新人

文档定位:uitest 命令速查 + 控件树怎么查 + 等待/断言机制 + 直接抄的自动化脚本

配套系列:hdc 环境配置(第1弹)· wukong 测试(第2弹)· hilog 使用指南(第3弹)· keycodeType 详解(第4弹)· faultlog 崩溃日志分析(第5弹)· DevEco Studio 图形化测试(第7弹)。同系列文章均已在个人主页发布,可在主页目录查看。


一、uitest 是什么(30 秒理解)

uitest 是鸿蒙 UI 测试框架的命令行入口 ,提供控件级的 UI 操作能力(点击、滑动、输入、截图、查控件树、录制回放)。

和 keyevent / wukong 的区别(选型必看):

工具 粒度 特点 适用
input keyevent 按键 只能发按键,最粗 简单控键(第4弹)
wukong 随机 模糊/Monkey 式压测,不可控 稳定性随机压测(第2弹)
uitest(命令行) 控件/坐标 精确、可录制、可查控件树 临时验证、冒烟、shell 串自动化

一句话:wukong 乱点找崩溃,uitest 精准点做流程。 要跑"登录→下单→退出"这种固定脚本,用 uitest。

命令行 uitest vs ArkTS UiTest 框架(选型补充)

新手常问:什么时候用命令行 uitest,什么时候写 ArkTS 测试用例?两者定位不同:

维度 命令行 uitest ArkTS UiTest(@ohos.uitest
上手成本 低,shell 即可 高,需写 TS + 编译部署
定位方式 坐标 / dump 后解析 JSON By.text/id/className 定位器,抗分辨率
断言/报告 弱(需自己拼 grep/sleep) 强(内置 assert + 报告)
等待机制 需手写轮询 内置 driver.wait
可维护性 低(裸坐标易碎) 高(用例可版本管理)
适用场景 临时验证、冒烟、CI 串脚本、无源码场景 正式回归套件、复杂流程、长期维护

选型建议:5 条命令以内的快速验证 → 命令行 uitest;超过 20 步、需长期维护的回归套件 → 写 ArkTS 用例(见第7弹 DevEco 图形化测试)。本篇聚焦命令行。


二、前提条件

bash 复制代码
# 1. hdc 已配通(见第1弹),设备开 USB 调试并连上
hdc list targets          # 能看到设备

# 2. 确认 uitest 可用
hdc shell uitest --version

# 3.(部分版本/老系统)无响应时,先使能 UI 测试框架
hdc shell param set persist.ace.testmode.enabled 1
# 官方 HarmonyOS 指南未强制要求此步,但 OpenHarmony/部分版本需要,
# 命令无响应时优先试这一条。

# 4. 查屏幕分辨率/DP(写坐标适配脚本时必用)
hdc shell hidumper -s RenderService -a screenInfo
# 输出示例:width=1080 height=2400 density=3.0

关于 testmode 开关

  • persist.ace.testmode.enabled持久化参数,重启后仍生效。
  • 测试机 :保持 1 即可,无副作用。
  • 生产/外发设备 :测完建议关闭,恢复 param set persist.ace.testmode.enabled 0,避免控件树暴露给未授权工具。
  • 查当前值:hdc shell param get persist.ace.testmode.enabled
    注意:命令是 uitest(全小写主命令),子命令大小写为 uiInput / dumpLayout / screenCap / uiRecord (骆驼峰)。社区常写小写 uiinput 部分版本也能兼容,但以官方大小写为准

三、命令总览

子命令 用途
uitest uiInput <操作> 注入 UI 事件(点击/滑动/输入/按键)
uitest dumpLayout 获取当前界面控件树(JSON)
uitest screenCap 截图
uitest uiRecord 录制/回放界面操作
uitest start-daemon 拉起测试进程(一般自动拉起,手动用于排查)
uitest --version 版本信息

API 版本兼容性总览(一张表)

文中零散出现的 API 版本要求汇总在此,便于设备选型时核对:

命令/参数 最低 API 备注
uitest 主命令 API 9+ OpenHarmony 起支持
uitest uiInput click/swipe/... API 9+ 基础注入
uitest uiInput text <文本> API 18+ 获焦输入(无需坐标)
uitest uiInput inputText x y <文本> API 9+ 坐标输入
uitest uiInput dircFling API 9+ 方向滑动
uitest dumpLayout -a(扩展属性) API 10+ 颜色/字体等
uitest dumpLayout -w <windowId> API 10+ 指定窗口
uitest screenCap -d <displayId> API 20+ 多屏指定
uitest uiRecord record -W false API 20+ 仅坐标,不存控件
uitest uiRecord record -l API 20+ 每操作存布局快照
uitest uiRecord replay API 10+ 回放录制脚本

设备 API 版本查询:hdc shell param get const.ohos.apicompatibility.version


四、uiInput 注入详解(最核心)

4.1 点击类(坐标)

bash 复制代码
hdc shell uitest uiInput click 100 100          # 单击 (x,y)
hdc shell uitest uiInput doubleClick 100 100    # 双击
hdc shell uitest uiInput longClick 100 100      # 长按

4.2 滑动 / 拖拽类

bash 复制代码
# 慢滑:起点(10,10) → 终点(200,200),速度 500 px/s
hdc shell uitest uiInput swipe 10 10 200 200 500

# 拖拽(同签名)
hdc shell uitest uiInput drag 10 10 100 100 500

# 快滑/抛滑
hdc shell uitest uiInput fling 10 10 200 200 500

# 方向滑动:0左 1右 2上 3下
hdc shell uitest uiInput dircFling 2     # 上滑
hdc shell uitest uiInput dircFling 0 500 # 左滑,速度500

速度参数 swipeVelocityPps_ 默认 600,范围 200~40000。

4.3 文本输入

bash 复制代码
# 在指定坐标的输入控件里输入
hdc shell uitest uiInput inputText 100 100 hello

# 当前已获焦的输入框直接输入(API 18+)
hdc shell uitest uiInput text hello

⚠️ 密码输入安全:直接把密码写在命令里会留在 shell history 和 hilog 里。生产测试建议用环境变量或临时文件:

powershell 复制代码
# PowerShell:密码不落 history 明文
$pwd = Read-Host "请输入密码" -AsSecureString
$plain = [Runtime.InteropServices.Marshal]::PtrToStringAuto(
           [Runtime.InteropServices.Marshal]::SecureStringToBSTR($pwd))
hdc shell uitest uiInput text $plain
$plain = $null

详见第十七节"安全注意事项"。

4.4 按键 / 组合键 ⚠️ 和第4弹"两套体系"呼应

bash 复制代码
hdc shell uitest uiInput keyEvent Home       # 名称方式(推荐)
hdc shell uitest uiInput keyEvent Back
hdc shell uitest uiInput keyEvent Power

# 数字方式:用的是 **ArkTS KeyCode 枚举值**(不是 input keyevent 的底层数字!)
hdc shell uitest uiInput keyEvent 2038          # = KEYCODE_V(单键)
hdc shell uitest uiInput keyEvent 2072 2038     # = Ctrl+V(组合键:Ctrl + V)
hdc shell uitest uiInput keyEvent 2047 2038     # = Shift+V(大写 V)

⚠️ 关键坑uitest uiInput keyEvent 的 keycode 走应用层 ArkTS 枚举 (Home=1 / Back=2 / V=2038 / Ctrl=2072),而 input keyevent底层 Android 数字 (Home=3 / Back=4)。两者不一样!详见同系列「keycodeType 详解与 hdc 发送按键」一文。名称(Home/Back/Power)最不容易错,优先用名称

keyEvent 常用名称/值速查(节选自第4弹)
名称 ArkTS 值 说明 名称 ArkTS 值 说明
Home 1 主屏 Enter 2054 回车
Back 2 返回 Del 2055 退格
Search 9 搜索 Space 2050 空格
VolumeUp 16 音量+ Tab 2049 Tab
VolumeDown 17 音量- Menu 2067 菜单
Power 18 电源 Escape 2070 Esc
Camera 19 拍照 DPAD_CENTER 2016 确定
字母 A~Z 2017~2042 如 V=2038 数字 0~9 2000~2009 如 1=2001
修饰键 Ctrl=2072 / Shift=2047 / Alt=2073 组合键用:keyEvent 2072 2038 = Ctrl+V

完整清单见同系列「keycodeType 详解与 hdc 发送按键」一文的 KeyCode 枚举详解章节。组合键写法:keyEvent <修饰键值> <主键值>,最多支持多修饰键。

4.5 多指/复杂手势(命令行能力边界)

命令行 uiInput 只支持单指操作。以下场景命令行做不到,需转向 ArkTS UiTest 框架:

手势 命令行支持 替代方案
单指点击/滑动/拖拽 uiInput click/swipe/drag
长按 / 双击 uiInput longClick/doubleClick
双指缩放(pinch/zoom) ArkTS driver.pinch
多指点击 / 三指手势 ArkTS 多 Finger API
路径滑动(如解锁图案) ArkTS 自定义 gesture
连续手势编排 ArkTS 或 uiRecord 录制后回放

一句话:命令行管单指,多指找 ArkTS。 复杂手势可先 uiRecord record 录制,再 replay 回放(见第七节)。


五、dumpLayout 获取控件树(找控件坐标/属性)

做精确自动化前,先 dump 当前界面控件树,拿到每个控件的 坐标边界、id、文本、类型,再决定点哪。

bash 复制代码
# 导出控件树到文件(再 hdc file recv 拉回 PC 看)
hdc shell uitest dumpLayout -p /data/local/tmp/layout.json

# 扩展属性(背景色/内容/字体色/字号等),与 -i 互斥
hdc shell uitest dumpLayout -a -p /data/local/tmp/layout_full.json

# 指定窗口(windowId 用 hidumper 查,见第八节)
hdc shell uitest dumpLayout -w <windowId> -p /data/local/tmp/w.json

5.1 控件树字段说明

关键字段(来自 dumpLayout JSON 与录制数据示例):

字段 含义 示例
type / W1_Type 控件类型 Button / Text / Image
text / W1_Text 控件文本 "确认"
id / W1_ID 控件 id btn_confirm
bounds / W1_BOUNDS 边界坐标 [0,0][100,50](左上-右下)
clickable 是否可点击 true/false
enabled 是否可用 true/false
checked 是否选中 true/false

⚠️ 字段命名注意 :dumpLayout JSON 默认输出 type/text/id/bounds(小写驼峰,在 attributes 对象里);uiRecord read 输出的 CSV 用 W1_Type/W1_Text/W1_ID/W1_BOUNDS 前缀。两者字段对应但命名不同,解析时以实际输出为准。

5.2 真实 layout.json 片段(脱敏示例)

json 复制代码
{
  "attributes": {
    "type": "RootNode",
    "bounds": "[0,0][1080,2400]",
    "clickable": false,
    "enabled": true
  },
  "children": [
    {
      "attributes": {
        "type": "Column",
        "bounds": "[0,100][1080,800]",
        "id": "",
        "text": ""
      },
      "children": [
        {
          "attributes": {
            "type": "Button",
            "id": "btn_confirm",
            "text": "确认",
            "bounds": "[440,1100][640,1200]",
            "clickable": true,
            "enabled": true
          },
          "children": []
        },
        {
          "attributes": {
            "type": "TextInput",
            "id": "input_account",
            "text": "",
            "bounds": "[100,900][980,1000]",
            "clickable": true
          },
          "children": []
        }
      ]
    }
  ]
}

拿到 bounds 后,取中心 (x1+x2)/2, (y1+y2)/2 作为 click 坐标,就能精准点控件,不用肉眼猜坐标。例如 [440,1100][640,1200] → 中心 (540, 1150)

5.3 基于属性定位(jq / grep 解析,抗分辨率)

裸坐标脚本在不同分辨率设备上会全部偏移。推荐按属性查控件再算中心,这是从"操作脚本"走向"自动化"的关键一步:

bash 复制代码
# 方法1:用 jq 按文本找按钮,输出 bounds
hdc shell uitest dumpLayout -p /data/local/tmp/l.json
hdc file recv /data/local/tmp/l.json ./l.json
# jq 递归遍历,匹配 text=="确认" 的节点
jq -r '.. | objects | .attributes? | select(.text=="确认") | .bounds' l.json
# 输出:[440,1100][640,1200]

# 方法2:按 id 找(最稳,不受语言/文本变化影响)
jq -r '.. | objects | .attributes? | select(.id=="btn_confirm") | .bounds' l.json

# 方法3:没有 jq,用 grep(粗略)
grep -oE '"text":"确认"[^}]*"bounds":"\[[0-9,]+\]\[[0-9,]+\]"' l.json

# 方法4:PowerShell 原生解析(Windows 无 jq 时)
$j = Get-Content l.json -Raw | ConvertFrom-Json
$btn = $j.children[0].children | Where-Object { $_.attributes.text -eq "确认" }
$btn.attributes.bounds

定位优先级id(最稳) > text(次稳) > type+bounds(兜底) > 裸坐标(最脆)。能用 id 就别用坐标。

完整属性定位闭环

bash 复制代码
# 一行命令拿到控件中心坐标(jq + awk 算中心)
hdc shell uitest dumpLayout -p /data/local/tmp/l.json
hdc file recv /data/local/tmp/l.json ./l.json
BOUNDS=$(jq -r '.. | objects | .attributes? | select(.id=="btn_confirm") | .bounds' l.json)
# BOUNDS="[440,1100][640,1200]" → 解析出中心
X=$(echo $BOUNDS | grep -oE '[0-9]+' | sed -n '1p;3p' | awk '{s+=$1} END{print int(s/2)}')
Y=$(echo $BOUNDS | grep -oE '[0-9]+' | sed -n '2p;4p' | awk '{s+=$1} END{print int(s/2)}')
hdc shell uitest uiInput click $X $Y

六、screenCap 截图

bash 复制代码
hdc shell uitest screenCap                    # 默认存 /data/local/tmp/时间戳.png
hdc shell uitest screenCap -p /data/local/tmp/1.png   # 指定路径
hdc shell uitest screenCap -d <displayId>     # 多屏指定屏幕(API 20+)

# 拉回 PC
hdc file recv /data/local/tmp/1.png ./1.png

截图常用于测试留证断言辅助(界面是否到达预期)。CI 流水线建议按用例名+时间戳归档:

bash 复制代码
$ts = Get-Date -Format "yyyyMMdd_HHmmss"
hdc shell uitest screenCap -p /data/local/tmp/case01_$ts.png
hdc file recv /data/local/tmp/case01_$ts.png ./reports/case01_$ts.png

七、uiRecord 录制回放(不会写命令也能自动化)

bash 复制代码
# 开始录制(手动在设备上操作,Ctrl+C 结束,存 /data/local/tmp/record.csv)
hdc shell uitest uiRecord record

# 读取并打印录制内容
hdc shell uitest uiRecord read

# 仅记录坐标(不存控件信息,API 20+)
hdc shell uitest uiRecord record -W false

# 每次操作同时存布局快照(API 20+)
hdc shell uitest uiRecord record -l

7.1 回放录制脚本

bash 复制代码
# 回放默认录制文件
hdc shell uitest uiRecord replay

# 回放指定文件
hdc shell uitest uiRecord replay -p /data/local/tmp/record.csv

录制数据含 OP_TYPE(click/doubleClick/longClick/drag/swipe/fling)、fingerList(控件属性)等,可用于复盘操作序列或转成自动化脚本。

7.2 录制 CSV 转脚本(思路)

uiRecord read 输出的 CSV 每行是一次操作,关键字段:

字段 含义 示例
OP_TYPE 操作类型 click / swipe
POS_X / POS_Y 坐标 540,1150
fingerList 控件属性快照 含 text/id/bounds

转换思路:用脚本读 CSV,把每行翻译成 uitest uiInput 命令,并在操作间插入 sleep

powershell 复制代码
# PowerShell:record.csv → 可执行 .ps1 脚本
Import-Csv record.csv | ForEach-Object {
    switch ($_.OP_TYPE) {
        "click"  { "hdc shell uitest uiInput click $($_.POS_X) $($_.POS_Y)" }
        "swipe"  { "hdc shell uitest uiInput swipe $($_.POS_X) $($_.POS_Y) $($_.END_X) $($_.END_Y) 500" }
        default  { "# 未识别操作: $($_.OP_TYPE)" }
    }
    "Start-Sleep -Milliseconds 800   # 操作间隔,防时序错乱"
} | Set-Content replay.ps1

⚠️ 回放限制 :录制依赖当时分辨率和时序,跨设备/跨分辨率回放可能偏移 ;操作太快时回放可能丢步。建议回放脚本中每步加 sleep 0.5~1s


八、启动应用与窗口定位(aa/bm/hidumper 联动)

自动化第一步通常是"打开目标 App",uitest 本身不带启动命令,需联动 aa(Ability Assistant)和 bm(Bundle Manager):

bash 复制代码
# 1. 查已安装应用包名
hdc shell bm dump -n com.xxx.xxx         # 看 ability 信息
# 或列所有包
hdc shell bm dump -a

# 2. 启动应用(指定 ability 名 + 包名)
hdc shell aa start -a EntryAbility -b com.xxx.xxx

# 3. 强制停止应用(用例间清理)
hdc shell aa force-stop com.xxx.xxx

# 4. 查当前前台窗口 windowId(dumpLayout -w 用)
hdc shell hidumper -s WindowManager -a "-a"
# 或
hdc shell hidumper -s Window | grep -i "windowId"

能力边界uitest 只负责"操作已显示的界面",启动/停止应用、查窗口 ID 用 aa/bm/hidumper 。完整自动化脚本通常是 aa startsleep 2uitest uiInput ... 的组合。


九、等待与断言机制(自动化的灵魂)

没有等待和断言的脚本只是"操作记录",不是"测试"。这两项是命令行 uitest 自动化的核心补强。

9.1 等待机制(轮询控件出现)

界面跳转、列表加载都有延迟,连续 uiInput 之间必须 sleep 或轮询

powershell 复制代码
# 简单等待(PowerShell)
Start-Sleep -Seconds 2

# 进阶:轮询等待目标控件出现(最多 10 秒,每秒查一次)
for ($i=1; $i -le 10; $i++) {
    hdc shell uitest dumpLayout -p /data/local/tmp/l.json
    hdc file recv /data/local/tmp/l.json ./l.json 2>$null
    if (Select-String -Path l.json -Pattern '"text":"登录成功"' -Quiet) {
        Write-Host "控件已出现,耗时 ${i}s"
        break
    }
    Start-Sleep -Seconds 1
}
if ($i -gt 10) { Write-Host "⚠️ 等待超时"; }

等待策略

  • 短操作(点击即响应):sleep 0.5~1s
  • 跳转/加载:轮询 dumpLayout,超时 10~15s
  • 网络/启动:超时 20~30s
  • 不要写死长 sleep (如 sleep 10),既慢又不稳;用轮询代替。

9.2 断言机制(验证操作结果)

断言类型 方法 示例
控件文本 dumpLayout 后 grep grep "text":"登录成功"
控件存在 grep 控件 id grep "id":"btn_logout"
控件状态 grep enabled/checked grep "checked":true
截图对比 screenCap + 人工/工具 留证供抽检
隐式断言 hilog 抓异常关键词 `hilog -L E

断言闭环示例(登录后验证)

powershell 复制代码
# 操作 + 等待 + 断言 三段式
hdc shell uitest uiInput click 540 1150        # 点登录
# 等待并断言"登录成功"文本出现
$pass = $false
for ($i=1; $i -le 15; $i++) {
    hdc shell uitest dumpLayout -p /data/local/tmp/l.json
    hdc file recv /data/local/tmp/l.json ./l.json 2>$null
    if (Select-String -Path l.json -Pattern '登录成功' -Quiet) {
        $pass = $true; break
    }
    Start-Sleep -Seconds 1
}
if ($pass) { Write-Host "PASS: 登录成功" }
else {
    Write-Host "FAIL: 登录失败,截图留证"
    hdc shell uitest screenCap -p /data/local/tmp/fail.png
    hdc file recv /data/local/tmp/fail.png ./fail_$(Get-Date -Format HHmmss).png
    # 联动 hilog 抓异常(第3弹)
    hdc shell hilog -x | Select-String -Pattern "Exception|Crash" -CaseSensitive:$false
}

⚠️ hilog 作为断言是隐式的------崩溃一定会抛异常日志,但异常日志不代表一定崩。需结合 faultlog(第5弹)确认。


十、实战模板(直接抄)

powershell 复制代码
# === 模板1:启动应用 → 查控件 → 点按钮(属性定位 + 等待)===
hdc shell aa start -a EntryAbility -b com.xxx.xxx
Start-Sleep -Seconds 2                    # 等应用启动
hdc shell uitest dumpLayout -p /data/local/tmp/l.json
hdc file recv /data/local/tmp/l.json ./l.json
# jq 按 id 找"确认"按钮,算中心(jq 需另行安装;无 jq 见 5.3 的 grep/awk 方案)
$BOUNDS = jq -r '.. | objects | .attributes? | select(.id=="btn_confirm") | .bounds' l.json
# (中心点解析略,见 5.3)
hdc shell uitest uiInput click 540 1150

# === 模板2:登录流程(输入账号密码 + 点登录 + 断言)===
hdc shell uitest uiInput click 300 400            # 聚焦账号框
Start-Sleep -Milliseconds 500
hdc shell uitest uiInput text user001             # 输入账号(获焦输入,API18+)
hdc shell uitest uiInput click 300 500            # 聚焦密码框
Start-Sleep -Milliseconds 500
hdc shell uitest uiInput text pass123             # 输入密码
hdc shell uitest uiInput keyEvent Enter           # 回车提交(或点登录按钮)
# 断言:等待"登录成功"
hdc shell uitest dumpLayout -p /data/local/tmp/l.json
hdc file recv /data/local/tmp/l.json ./l.json
Select-String -Path l.json -Pattern "登录成功"    # 命中即 PASS

# === 模板3:上滑浏览列表(带间隔,防丢步)===
for ($i=1; $i -le 5; $i++) {
    hdc shell uitest uiInput dircFling 2
    Start-Sleep -Milliseconds 800
}

# === 模板4:截图留证(带时间戳归档)===
$ts = Get-Date -Format "yyyyMMdd_HHmmss"
hdc shell uitest screenCap -p /data/local/tmp/shot_$ts.png
hdc file recv /data/local/tmp/shot_$ts.png ./reports/shot_$ts.png

# === 模板5:返回桌面 ===
hdc shell uitest uiInput keyEvent Home

# === 模板6:用例间清理(停应用 + 重新启动)===
hdc shell aa force-stop com.xxx.xxx
Start-Sleep -Seconds 1
hdc shell aa start -a EntryAbility -b com.xxx.xxx

十一、与前面笔记的闭环(完整自动化排障流)

text 复制代码
1. hdc 连上(第1弹)
2. aa start 启动目标应用(本篇第八节)
3. uitest 做确定性 UI 流程(本篇):dumpLayout 查控件 → uiInput 精准操作 → 轮询等待 → 断言
4. 同时跑 hilog 盯异常(第3弹):
   hdc shell hilog -L E | grep -iE "crash|freeze"
5. 压测用 wukong 补随机覆盖(第2弹):
   hdc shell wukong exec -b com.xxx -a 0.3 -t 0.7 -T 30
6. 崩溃了查 faultlog(第5弹):
   hdc file recv /data/log/faultlog/faultlogger ./faultlogs
7. 按键控制见第4弹(注意两套 keycode 体系)

十二、错误处理与重试

12.1 命令退出码

退出码 含义 处理
0 成功 继续
0 失败(命令未识别/参数错/设备断) 检查命令大小写、参数、hdc 连接

PowerShell 判断上一步成败:

powershell 复制代码
hdc shell uitest uiInput click 540 1150
if ($LASTEXITCODE -ne 0) {
    Write-Host "点击失败,重试或截图"
    hdc shell uitest screenCap -p /data/local/tmp/err.png
}

12.2 hdc 断连恢复

powershell 复制代码
# 检测设备是否在线
if (-not (hdc list targets | Select-String "\d+\.\d+\.\d+\.\d+")) {
    Write-Host "设备掉线,尝试重连"
    hdc kill          # 杀 hdc 服务
    hdc start         # 重启 hdc
    Start-Sleep -Seconds 2
}

12.3 关键操作重试封装

powershell 复制代码
function Invoke-UiClick {
    param([int]$X, [int]$Y, [int]$Retry = 3)
    for ($i=1; $i -le $Retry; $i++) {
        hdc shell uitest uiInput click $X $Y
        if ($LASTEXITCODE -eq 0) { return $true }
        Start-Sleep -Milliseconds 500
    }
    return $false
}

十三、CI/CD 集成与多设备

13.1 多设备指定

hdc 默认操作第一台设备,多设备时必须用 -s <deviceId> 指定:

bash 复制代码
# 列所有设备 SN
hdc list targets
# 指定设备执行 uitest
hdc -s <deviceId> shell uitest uiInput click 540 1150
hdc -s <deviceId> shell uitest dumpLayout -p /data/local/tmp/l.json
hdc -s <deviceId> file recv /data/local/tmp/l.json ./device1_l.json

13.2 CI 流水线串接要点

环节 建议
环境准备 CI 节点预装 hdc + uitest;流水线开始 hdc list targets 校验设备在线
用例隔离 每条用例前 aa force-stop 清理,用例间 sleep 1
报告归档 截图/控件树/日志按 用例名_时间戳 命名,统一存 reports/
失败处理 任何一步失败立即截图 + dump hilog,再标记用例 FAIL
超时控制 每条用例设总超时(如 120s),避免卡死流水线
并发 多设备并行时,每个 job 绑定一个 -s <deviceId>,输出目录隔离

13.3 Jenkins/GitLab CI 最小示例

powershell 复制代码
# run_ui_case.ps1 ------ CI 调用入口
param([string]$DeviceId, [string]$CaseName)
$ErrorActionPreference = "Stop"
$ts = Get-Date -Format "yyyyMMdd_HHmmss"
$reportDir = "reports/$CaseName/$ts"
New-Item -ItemType Directory -Path $reportDir -Force | Out-Null

hdc -s $DeviceId shell aa force-stop com.xxx.xxx
hdc -s $DeviceId shell aa start -a EntryAbility -b com.xxx.xxx
Start-Sleep -Seconds 2

# ... 执行用例步骤 ...

# 收尾归档
hdc -s $DeviceId shell uitest screenCap -p /data/local/tmp/final.png
hdc -s $DeviceId file recv /data/local/tmp/final.png "$reportDir/final.png"
hdc -s $DeviceId shell hilog -x > "$reportDir/hilog.txt"
Write-Host "报告归档至 $reportDir"

十四、常见报错对照表

现象 可能原因 排查/解决
uitest: command not found 系统未内置 uitest / PATH 缺失 确认设备为 HarmonyOS/OpenHarmony 全量版;部分精简版无 uitest
子命令不识别(如 uiinput 报错) 子命令大小写错 用骆驼峰 uiInput/dumpLayout/screenCap/uiRecord
命令无任何响应/卡住 testmode 未开 param set persist.ace.testmode.enabled 1 后重试
dumpLayout 返回空 JSON 无焦点窗口 / 应用未前台 aa start 拉起应用再 dump
click 后界面无反应 坐标偏 / 控件不可点 dumpLayout 读 bounds 取中心;确认 clickable:true
inputText 没反应 控件未获焦 / 不可输入 click 聚焦;确认控件 type:TextInput
text 命令报错 API < 18 改用 inputText x y 文本
keyEvent 按键无效果 用错 keycode 体系 用名称(Home/Back);详见第4弹
screenCap 拉回文件 0 字节 路径无写权限 改用 /data/local/tmp/ 路径
file recv 报 not found 设备上文件未生成 先确认 dumpLayout/screenCap 命令成功执行
回放脚本偏移 分辨率/时序差异 录制与回放需同分辨率;操作间加 sleep

十五、新手必踩的坑 + 标准作业流(SOP)

15.1 必踩的 6 个坑

  1. 命令大小写错 → 主命令 uitest 小写,子命令 uiInput/dumpLayout/screenCap/uiRecord 是骆驼峰。全小写写成 uitest uiinput 可能不识别。
  2. keyEvent 的 keycode 用错体系uitest keyEventArkTS 枚举/名称 (Home=1),不是 input keyevent 的底层数字(3)。优先用名称 Home/Back/Power
  3. 裸坐标点偏 → 屏幕坐标以像素计,且可能因分辨率/状态栏偏移。优先按 id/text 属性定位 (5.3),其次 dumpLayoutbounds 取中心,别裸猜。
  4. uitest 无响应 → 部分版本需先 param set persist.ace.testmode.enabled 1 使能(见第二节)。
  5. 连续操作太快丢步 → 界面跳转有延迟,连续 uiInput 之间必须 sleep 或轮询等待(第九节)。这是新手脚本"时灵时不灵"的头号原因。
  6. 只操作不验证 → 没有断言的脚本不是测试。至少在关键步骤后 dumpLayout grep 一下结果(第九节 9.2)。

记忆口诀:查控件用 dumpLayout,定位优先 id/text;操作之间要等待,结果必须做断言;keyEvent 用名称,无响应先开 testmode。

15.2 标准作业流(SOP)

text 复制代码
1. hdc 连上,确认 uitest --version 可用(不行就开 testmode)
2. aa start 启动目标应用(第八节)
3. dumpLayout -p 导出控件树,recv 回 PC
4. 按 id/text 属性定位控件(jq/grep,5.3),算中心点坐标
5. uiInput click/doubleClick/longClick 点它
6. 要输入 → 先 click 聚焦,再 inputText/text
7. 要滑 → swipe/drag/dircFling
8. 每步后 sleep 或轮询等待目标控件出现(9.1)
9. 关键步骤后 dumpLayout 做断言(9.2)
10. screenCap 截图留证
11. 复杂流程 → uiRecord 录制,read 复盘,replay 回放
12. 异常 → hilog/faultlog 联动(见配套笔记)
13. 用例结束 → aa force-stop 清理

十六、一句话速记卡(贴显示器上)

text 复制代码
uitest = 控件级 UI 自动化(比 wukong 精准,比 keyevent 完整)
前提: hdc 连上; 无响应先 param set persist.ace.testmode.enabled 1
选型: 临时验证用命令行; 长期回归套件写 ArkTS UiTest

命令(注意大小写!):
  uitest uiInput click x y          单击
  uitest uiInput doubleClick x y    双击
  uitest uiInput longClick x y      长按
  uitest uiInput swipe x1 y1 x2 y2 [速度]   滑动
  uitest uiInput drag x1 y1 x2 y2 [速度]    拖拽
  uitest uiInput dircFling 2        上滑(0左1右2上3下)
  uitest uiInput inputText x y 文本 坐标输入
  uitest uiInput text 文本          获焦输入(API18+)
  uitest uiInput keyEvent Home      按键(用名称!非底层数)
  uitest dumpLayout -p 文件         查控件树(bounds)
  uitest screenCap -p 文件          截图
  uitest uiRecord record            录制(Ctrl+C 结束)
  uitest uiRecord replay            回放

定位: 优先 id > text > 坐标;  jq 解析 bounds 取中心
等待: sleep 0.5~1s 或轮询 dumpLayout;  别写死长 sleep
断言: dumpLayout grep 控件文本/状态;  hilog 抓异常做隐式断言
启动: aa start -a Ability -b 包名;   清理: aa force-stop
多指: 命令行不支持, 找 ArkTS UiTest

十七、安全注意事项

  1. 密码/敏感输入 :避免明文进 shell history。用环境变量、Read-Host -AsSecureString,或临时文件读取后立即删除。明文密码还可能被 hilog 记录,敏感字段建议测试账号专用。
  2. testmode 开关persist.ace.testmode.enabled 1 会让控件树对所有调试工具可见。生产/外发设备测完务必关闭param set ... 0)。
  3. 截图脱敏:归档截图前检查是否含账号、手机号等敏感信息,CI 报告建议存内部系统不外传。
  4. 录制动效uiRecord record 会记录控件属性(含文本),录制含敏感信息的界面时注意保管 csv 文件。
  5. 设备权限:uitest 操作能力等同人工操作,可触发支付/删除等危险动作。自动化脚本需有操作白名单,避免误触不可逆操作。

参考来源

  • 华为开发者文档:UI 测试框架使用指导(命令行测试能力)
  • 华为设备开发文档:UITest 命令行指南
  • ArkTS UiTest 框架:@ohos.uitest API 参考
  • 实践参考:UI 测试框架使能命令 param set persist.ace.testmode.enabled 1(OpenHarmony 场景)
  • 配套系列:aa/bm 能力管理见「hdc 环境配置详解」· keycodeType 枚举见「keycodeType 详解与 hdc 发送按键」· ArkTS 图形化测试见「DevEco Studio 图形化测试」(同系列文章均在个人主页发布)

写在最后

本文是「鸿蒙系统测试笔记」系列的第 6 弹,聚焦命令行 uitest 的工程化实战。系列共 13 篇,覆盖 hdc 环境、wukong 压测、hilog 日志、keycodeType 按键、faultlog 崩溃分析、uitest 自动化、DevEco 图形化、SmartPerf 性能、DevEco Testing 专项、DFX 全家桶、分布式协同、安全合规、测试方法论等内容,欢迎到个人主页查看完整目录。

原创声明:本文为作者原创整理,基于鸿蒙官方文档结合实际测试实践编写。转载请注明出处,禁止删改摘要与原创声明后搬运。文中命令与脚本均在真实设备验证,但鸿蒙版本迭代较快,部分命令的 API 版本要求以设备实际为准。
如果觉得有帮助,欢迎点赞收藏;有问题欢迎评论区交流。

相关推荐
OH_TPC1 小时前
OpenHarmony平台RN三方库适配情况
华为·harmonyos·鸿蒙
其实防守也摸鱼1 小时前
教育信息技术应用创新---基础软件信息赛(题库)
大数据·运维·人工智能·web安全·自动化
坚果的博客1 小时前
从 0 到 1:用 CJMP 开发「每日早报」鸿蒙应用完整实战
华为·harmonyos
小白的后端世界1 小时前
跨境电商数据分析与 AI Agent 自动化:从指标体系到决策闭环
人工智能·深度学习·数据分析·自动化
Magic-ZYJ1 小时前
HarmonyOS 权限申请完整流程:声明、检查、请求、拒绝后二次授权
华为·harmonyos·移动应用开发·arcts·arcui
天空属于哈夫克32 小时前
企业微信 API 自动发送消息:从流程到实战
python·自动化·企业微信
兰亭妙微UI设计公司2 小时前
兰亭妙微QT界面开发:设计系统侧边导航组件:告别混乱,实现高效协同
ui
xixiaoyunya2 小时前
Zigbee智能家居完整组网指南:从局域网自动化到外网远程控制的技术实现
自动化·智能路由器·智能家居
大雷神2 小时前
HarmonyOS ArkGraphics 2D场景化可变帧率实操——做一个智能帧率专注计时器
pytorch·华为·harmonyos