鸿蒙UI测试框架:UITest
一、功能UITest分为客户端和服务端端说明客户端由测试应用加载运行在应用进程。包含跨语言通信层、IPC模块对外导出API服务端以独立进程运行通过IPC与客户端通信。负责核心逻辑控件树构建、控件匹配查找、操作事件构造、多模事件注入等UITest支持两种方式方式说明ArkTS脚本开发提供简洁易用的API接口支持点击、双击、长按、滑动等操作命令行测试支持截图、获取控件树、录制界面操作、注入UI模拟事件二、使用ArkTS接口进行UI测试2.1 步骤编写被测页面代码如ClickToAfter.ets在ohosTest目录下编写测试代码导入测试依赖kit.TestKit、ohos/hypium2.2 核心流程初始化Driver → 拉起被测应用 → 等待应用空闲 → 查找控件 → 执行操作 → 断言验证2.3 示例import { describe, expect, it, Level } from ohos/hypium; import { abilityDelegatorRegistry, Driver, ON } from kit.TestKit; import { UIAbility, Want } from kit.AbilityKit; const delegator abilityDelegatorRegistry.getAbilityDelegator(); export default function abilityTest() { describe(ActsAbilityTest, () { it(testUiExample, Level.LEVEL3, async (done: Function) { const driver Driver.create(); const bundleName abilityDelegatorRegistry.getArguments().bundleName; // 拉起被测应用 await delegator.startAbility({ bundleName: bundleName, abilityName: EntryAbility }); // 等待应用拉起完成 await driver.waitForIdle(4000, 5000); // 确认当前应用顶部Ability const ability await delegator.getCurrentTopAbility(); expect(ability.context.abilityInfo.name).assertEqual(EntryAbility); // 查找Next控件并点击 const next await driver.findComponent(ON.text(Next)); await next.click(); await driver.waitForIdle(4000, 5000); // 断言验证 await driver.assertComponentExist(ON.text(after click)); await driver.pressBack(); done(); }); }); }三、控件查找与操作3.1 控件匹配器ONUITest支持依据多种属性构造匹配器进行控件查找匹配方式示例按文本ON.text(Next)按类型ON.type(Button)相对位置ON.text(123).within(ON.type(Scroll))按idON.id(button_id)3.2 示例// 查找Button并点击 let button await driver.findComponent(ON.type(Button)); await button.click(); // 查找Scroll中文本为123的控件 let on ON.text(123).within(ON.type(Scroll)); let items await driver.findComponents(on); // 查找Image并进行双指放大 let image await driver.findComponent(ON.type(Image)); await image.pinchOut(1.5);四、模拟触摸屏手指操作4.1 基础操作// 单击 await driver.click(100, 100); // 指定屏幕id单击API 20 await driver.clickAt({ x: 100, y: 100, displayId: 0 }); // 滑动 await driver.swipe(100, 100, 200, 200, 600); // 指定屏幕id滑动API 20 await driver.swipeBetween( { x: 100, y: 100, displayId: 0 }, { x: 1000, y: 1000, displayId: 0 }, 800 ); // 抛滑 await driver.fling({ x: 100, y: 100 }, { x: 200, y: 200 }, 5, 600); // 指定方向抛滑 await driver.fling(UiDirection.DOWN, 10000); // 拖拽 await driver.drag(100, 100, 200, 200, 600);4.2 多指操作// 2根手指每根手指基于2个坐标点滑动 let pointers PointerMatrix.create(2, 2); pointers.setPoint(0, 0, { x: 100, y: 100 }); pointers.setPoint(0, 1, { x: 200, y: 100 }); pointers.setPoint(1, 0, { x: 100, y: 200 }); pointers.setPoint(1, 1, { x: 200, y: 200 }); await driver.injectMultiPointerAction(pointers);五、页面加载等待// 等待指定控件出现超时1000ms let button await driver.waitForComponent(ON.text(StartAbility Success!), 1000); // 等待应用空闲 await driver.waitForIdle(4000, 5000);六、模拟文本输入// 基于控件的文本输入 let input await driver.findComponent(ON.type(TextInput)); await input.inputText(abc); // 指定复制粘贴方式输入API 20 await input.inputText(abc, { paste: true, addition: true }); // 基于坐标的文本输入 let center await input.getBoundsCenter(); await driver.inputText(center, abc); // 包含中文时自动使用复制粘贴方式 await driver.inputText(center, 你好, { paste: false, addition: true });输入方式参数说明paste是否以复制粘贴方式输入默认falseaddition是否以追加方式输入不清空原有内容默认false七、截图// 截取指定区域并保存 let savePath /data/storage/el2/base/cache/1.png; let res await driver.screenCapture(savePath, { left: 0, top: 0, right: 100, bottom: 100 }); // 截取指定屏幕id的全屏API 20 let disPlay display.getDefaultDisplaySync(); await driver.screenCap(savePath, disPlay.id);注意截图路径需为应用沙箱路径el2/user级加密区。八、UI事件监听// 监听Toast控件出现 let observer driver.createUIEventObserver(); observer.once(toastShow, (uiElementInfo) { let bundleName uiElementInfo.bundleName; let text uiElementInfo.text; let type uiElementInfo.type; });九、模拟键鼠/触摸板/手写笔操作9.1 键盘操作import { KeyCode } from kit.InputKit; // 按键输入 await driver.triggerKey(KeyCode.KEYCODE_BACK); // 组合键输入CtrlS await driver.triggerCombineKeys(KeyCode.KEYCODE_CTRL_LEFT, KeyCode.KEYCODE_S);9.2 鼠标操作import { MouseButton } from kit.TestKit; // 鼠标左键单击 await driver.mouseClick({ x: 100, y: 100 }, MouseButton.MOUSE_BUTTON_LEFT); // 鼠标移动 await driver.mouseMoveTo({ x: 100, y: 100 }); // 鼠标拖拽 await driver.mouseDrag({ x: 100, y: 100 }, { x: 200, y: 200 }, 600); // 鼠标滚轮滚动Ctrl滚轮 await driver.mouseScroll({ x: 100, y: 100 }, true, 30, KeyCode.KEYCODE_CTRL_LEFT);9.3 触摸板操作PC/2in1// 三指上滑返回桌面 await driver.touchPadMultiFingerSwipe(3, UiDirection.UP); // 三指下滑恢复窗口 await driver.touchPadMultiFingerSwipe(3, UiDirection.DOWN);9.4 手写笔操作// 手写笔单击 await driver.penClick({ x: 100, y: 100 }); // 手写笔双击 await driver.penDoubleClick({ x: 100, y: 100 }); // 手写笔长按0.5s await driver.penLongClick({ x: 100, y: 100 }, 0.5); // 手写笔滑动 await driver.penSwipe({ x: 100, y: 100 }, { x: 100, y: 500 }, 600, 0.5);十、窗口查找与操作// 查找活跃窗口 let window await driver.findWindow({ active: true }); // 窗口最小化 await window.minimize();十一、基于命令行进行UI测试前提根据hdc命令行工具指导完成环境准备确保设备已连接。命令列表命令说明uitest screenCap截图uitest dumpLayout获取控件树uitest uiRecord record录制界面操作uitest uiRecord read读取录制数据uitest uiInput注入UI模拟操作uitest --version获取版本信息uitest start-daemon拉起UITest测试进程常用命令示例截图# 默认路径 hdc shell uitest screenCap # 指定路径 hdc shell uitest screenCap -p /data/local/tmp/1.png获取控件树hdc shell uitest dumpLayout -p /data/local/tmp/1.json录制界面操作# 开始录制CtrlC结束 hdc shell uitest uiRecord record # 读取录制数据 hdc shell uitest uiRecord read # 仅记录坐标不匹配控件 hdc shell uitest uiRecord record -W false注入模拟操作# 单击 hdc shell uitest uiInput click 100 100 # 快滑 hdc shell uitest uiInput fling 10 10 200 200 500 # 慢滑 hdc shell uitest uiInput swipe 10 10 200 200 500 # 指定方向滑动0左/1右/2上/3下 hdc shell uitest uiInput dircFling 0 500 # 输入文本 hdc shell uitest uiInput inputText 100 100 hello # 按键事件 hdc shell uitest uiInput keyEvent Home hdc shell uitest uiInput keyEvent Back # 组合键CtrlV hdc shell uitest uiInput keyEvent 2072 2038