摘要:本文系统讲解鸿蒙 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 测试用例?两者定位不同:

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

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


二、前提条件

# 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 dircFlingAPI 9+方向滑动
uitest dumpLayout -a(扩展属性)API 10+颜色/字体等
uitest dumpLayout -w <windowId>API 10+指定窗口
uitest screenCap -d <displayId>API 20+多屏指定
uitest uiRecord record -W falseAPI 20+仅坐标,不存控件
uitest uiRecord record -lAPI 20+每操作存布局快照
uitest uiRecord replayAPI 10+回放录制脚本

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


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

4.1 点击类(坐标)

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 滑动 / 拖拽类

# 慢滑:起点(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 文本输入

# 在指定坐标的输入控件里输入
hdc shell uitest uiInput inputText 100 100 hello

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

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

# 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弹"两套体系"呼应

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 值说明
Home1主屏Enter2054回车
Back2返回Del2055退格
Search9搜索Space2050空格
VolumeUp16音量+Tab2049Tab
VolumeDown17音量-Menu2067菜单
Power18电源Escape2070Esc
Camera19拍照DPAD_CENTER2016确定
字母 A~Z2017~2042如 V=2038数字 0~92000~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、文本、类型,再决定点哪。

# 导出控件树到文件(再 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控件 idbtn_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 片段(脱敏示例)

{
  "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 解析,抗分辨率)

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

# 方法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 就别用坐标。

完整属性定位闭环

# 一行命令拿到控件中心坐标(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 截图

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 流水线建议按用例名+时间戳归档:

$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 录制回放(不会写命令也能自动化)

# 开始录制(手动在设备上操作,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 回放录制脚本

# 回放默认录制文件
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: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):

# 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)
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 后 grepgrep "text":"登录成功"
控件存在grep 控件 idgrep "id":"btn_logout"
控件状态grep enabled/checkedgrep "checked":true
截图对比screenCap + 人工/工具留证供抽检
隐式断言hilog 抓异常关键词hilog -L E | grep -iE "crash|exception"

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

# 操作 + 等待 + 断言 三段式
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弹)确认。


十、实战模板(直接抄)

# === 模板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

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

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 判断上一步成败:

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 断连恢复

# 检测设备是否在线
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 关键操作重试封装

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> 指定:

# 列所有设备 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 最小示例

# 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)

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 清理

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

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 版本要求以设备实际为准。

如果觉得有帮助,欢迎点赞收藏;有问题欢迎评论区交流。

Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐