跨平台 UI 自动化框架,当前聚焦 HarmonyOS
Project description
devhelmkit
跨平台 UI 自动化框架,当前聚焦 HarmonyOS。
概述
devhelmkit 为 HarmonyOS 设备提供 UI 自动化测试能力。通过 hdc 直连设备,无需任何测试框架运行时。
核心目标:
- 简洁 API:
d(text="登录").click()、d.app_start()、d.dump_hierarchy() - 直连设备:仅通过
hdc通信,不依赖测试框架 - 跨平台抽象:
BaseDriver契约 + 平台实现(HarmonyOS 已全功能可用,Android 预留) - 高级能力:鼠标、触控笔、指关节、触控板、多指手势
功能特性
- 选择器链:
d(text="xx")/d(id="xx")/d.xpath("//Text") - 控件操作:点击、长按、输入、拖拽、滑动、属性查询
- 设备控制:亮屏/熄屏、解锁、按键、旋转、截图
- 应用管理:启动、停止、安装、卸载
- 高级手势:完整鼠标操作、触控笔(带压力)、指关节敲击、多指
- 触控板:多指滑动、滑动停顿
- 事件监听:Toast 监听、UI 事件(对话框/窗口/组件)
- WebView 自动化:通过 chromedriver + selenium 测试应用内网页
- 图像匹配:模板匹配(多尺度 + 颜色校验)和特征匹配(SIFT/ORB)
- OCR:通过 RapidOCR(ONNX Runtime)识别屏幕文本
- 双查找后端:uitest(设备端 RPC)+ uitree(本地布局解析)
- 屏幕录制:JPEG 帧捕获与 MP4 编码
- 资源管理:自动清理 socket/端口转发,可选停止守护进程
- 网页版 UIViewer:本地双端口 Web 服务,实时投屏查看控件
- 跨平台:Windows / Linux / macOS,可配置 hdc 路径
UIViewer 网页版控件查看器
UIViewer 提供本地 Web 界面,支持实时投屏、控件树查看和触控操作。
启动
devhelmkit-uiviewer
无需参数,启动后自动打开浏览器。每次启动使用系统分配的空闲端口,互不冲突。
开启性能排查日志(采集帧率、推流帧率、触控 RPC 耗时):
devhelmkit-uiviewer --perf
两种采集模式
| 模式 | 截图来源 | 控件树来源 | 触控 | 说明 |
|---|---|---|---|---|
| 单次 (snapshot) | hdc snapshot_display | hdc dumpLayout 文件导出 | 禁用 | 不启动 RPC 和截图推流 |
| 实时 (live) | uitest startCaptureScreen | dump_hierarchy rpc | 启用 down/move/up | 实时投屏 + 触控 |
功能
- 页面内选择/切换手机
- 模式切换:单次 (HDC) / 实时 (UITest)
- 截图上叠加控件 bounds,高亮 hover/selected 节点
- 右侧控件树和属性面板,属性值一键复制
- 实时模式支持鼠标 down/move/up 映射为设备 touch
- 实时模式设备导航键:返回 / 主页 / 多任务
- 实时模式锁定画面后检视控件(锁定时重新抓取控件树,与锁定瞬间画面对应)
- 画面刷新:实时投屏为变化驱动,画面静止时可点击画面内刷新按钮唤醒一帧
- 关闭时清理 uitest 可选(默认保留)
- 单次模式手动刷新时,截图帧与控件树来自同一次刷新链路
端口
启动时自动分配两个系统空闲端口:
- control_port:页面、API、配置、touch 控制
- jpeg_port:JPEG/MJPEG 图片流
运行时端点按职责隔离:
| 端口 | 端点 | 职责 |
|---|---|---|
| control_port | GET /、GET /index.html、GET /static/app.js |
页面与静态资源 |
| control_port | GET /api/runtime、GET /api/devices、GET /api/session?serial=... |
运行时端口、设备列表、会话状态 |
| control_port | POST /api/session/select、POST /api/session/mode、POST /api/session/cleanup、POST /api/session/close |
设备选择、模式切换、清理策略、关闭会话 |
| control_port | POST /api/refresh、GET /api/hierarchy?serial=...、POST /api/touch |
刷新帧与控件树、实时控件树、live 触控 |
| control_port | POST /api/key、POST /api/live/refresh |
live 设备导航键、强制刷新一帧画面 |
| jpeg_port | GET /snapshot.jpg?serial=...&frame=... |
snapshot 单帧 JPEG;网页刷新链路读取 /api/refresh 缓存帧 |
| jpeg_port | GET /stream.mjpeg?serial=... |
live MJPEG 图片流 |
浏览器不直连裸 TCP;图片只从 jpeg_port 拉取,控制 API 只走 control_port。
进程退出时只释放本次实例创建的端口和资源。
安装
前置条件
- Python 3.8+(Windows / Linux / macOS)
- HarmonyOS 设备,已开启开发者模式和 USB 调试
- hdc(HarmonyOS Device Connector)— 用于设备通信
安装 hdc
hdc 随 HarmonyOS SDK 一起提供:
- 下载 HarmonyOS SDK(选择 Command Line Tools)
- 解压后,hdc 位于
sdk/<版本>/toolchains/目录 - 将该目录添加到系统
PATH - 验证:
hdc -v
# HarmonyOS Device Connector vX.X.X
验证设备连接:
hdc list targets
# ABCD1234567890
安装 devhelmkit
方式一:pip(推荐)
pip install devhelmkit
方式二:源码安装
git clone https://github.com/yabi-zzh/devhelmkit.git
cd devhelmkit
pip install -e .
依赖
核心依赖(自动安装):
| 包 | 用途 |
|---|---|
Pillow>=9.0.0 |
截图处理 |
基础安装即包含原生自动化能力:控件查找/操作、设备控制、手势、事件监听、屏幕录制等核心功能无需任何额外依赖。
可选依赖(按需安装):
| Extra | 安装命令 | 额外引入的包 | 功能范围 |
|---|---|---|---|
cv |
pip install devhelmkit[cv] |
opencv-python-headless, numpy |
图像匹配(模板 + 特征) |
ocr |
pip install devhelmkit[ocr] |
rapidocr-onnxruntime, opencv-python-headless, numpy |
OCR 文本识别(含图像匹配能力) |
webview |
pip install devhelmkit[webview] |
selenium |
WebView / 应用内浏览器自动化 |
all |
pip install devhelmkit[all] |
以上全部 | 全部能力(cv + ocr + webview) |
dev |
pip install devhelmkit[dev] |
pytest, pytest-cov, build, twine |
开发 / 测试 / 发布工具链 |
依赖关系:
ocr已包含cv的全部依赖(opencv + numpy),安装[ocr]后无需再装[cv]。[all]是cv+ocr+webview的超集。
快速开始
import devhelmkit
# 自动发现并连接设备
d = devhelmkit.connect()
# 启动应用
d.app_start("com.huawei.hmos.settings")
# 查找并操作控件
d(text="搜索").click()
d(className="TextInput").input_text("devhelmkit")
# 截图
d.screenshot().save("screen.png")
# 导出控件树
hierarchy = d.dump_hierarchy()
# 关闭连接,释放 socket 和端口转发
d.close()
资源清理
使用 with 语句或 try/finally 确保资源释放:
import devhelmkit
with devhelmkit.connect() as d:
d.app_start("com.huawei.hmos.settings")
d(text="搜索").click()
# 退出时自动调用 close()
关闭时同时停止设备端 uitest 守护进程(默认:保留以便复用):
# 方式一:运行时指定
d.close(stop_daemon=True)
# 方式二:通过配置
from devhelmkit.harmony.config import HarmonyDriverConfig
config = HarmonyDriverConfig(stop_daemon_on_close=True)
d = devhelmkit.connect(config=config)
指定设备
# 多设备时指定序列号
d = devhelmkit.connect(serial="1234567890ABCDEF")
# 显式指定平台
d = devhelmkit.connect(platform="harmony")
配置 hdc 路径
当 hdc 不在 PATH 中,或需要使用特定版本时:
import devhelmkit
from devhelmkit.harmony.device.hdc import HdcDevice
# 全局设置(影响后续所有连接)
HdcDevice.set_hdc_path("/path/to/hdc")
d = devhelmkit.connect()
或通过配置:
from devhelmkit.harmony.config import HarmonyDriverConfig
config = HarmonyDriverConfig(hdc_path="/path/to/hdc")
d = devhelmkit.connect(config=config)
API 示例
控件操作
# 等待控件出现
d(text="登录").wait(timeout=10)
# 输入文本
d(id="username").input_text("admin")
# 清空文本
d(id="username").clear_text()
# 长按
d(text="条目").long_click()
# 拖拽到另一控件
d(text="A").drag_to_component(d(text="B"))
# 获取属性
print(d(text="标题").info)
print(d(text="标题").bounds)
图像匹配
需要安装:
pip install devhelmkit[cv]
# 模板匹配(默认,快速)
rect = d.vision.find_image("icon.png")
if rect:
print(f"找到,位置: {rect}")
# 特征匹配(抗缩放/旋转)
rect = d.vision.find_image("icon.png", mode="feature", threshold=0.7)
# 查找并点击
d.vision.touch_image("button.png")
# 检查是否存在
if d.vision.exists_image("logo.png"):
print("Logo 已找到")
# 等待图像出现
d.vision.wait_image("loading_done.png", timeout=15)
OCR
需要安装:
pip install devhelmkit[ocr]
# 查找并点击文本
d.vision.click_text("设置")
# 模糊匹配(忽略大小写的子串匹配)
d.vision.click_text("设置", fuzzy=True)
# 获取 OCR 结果含坐标
result = d.vision.find_text("登录")
if result:
print(f"找到: {result.text} 位置: {result.bounds} 置信度: {result.confidence}")
# 识别区域内所有文本
results = d.vision.ocr(region=(100, 200, 500, 400))
for r in results:
print(f"{r.text} @ {r.bounds} (置信度={r.confidence:.2f})")
手势
# 滑动
d.swipe(100, 500, 100, 100)
# 双指滑动
d.two_finger_swipe((0, 400), (200, 400), (880, 400), (680, 400))
# 自定义手势
from devhelmkit.model.input import GestureAction
g = GestureAction()
g.add_step("move", 100, 200)
g.add_step("move", 200, 300)
d.inject_gesture(g, speed=1000)
鼠标
# 左键点击
d.mouse_click((500, 500))
# 右键点击
d.mouse_click((500, 500), button_id=1)
# 滚轮
d.mouse_scroll((500, 500), "down", steps=3)
# 拖拽
d.mouse_drag((100, 100), (300, 300))
触控笔
# 点击
d.pen_click((500, 500))
# 带压力长按
d.pen_long_click((500, 500), pressure=0.8)
# 方向滑动
d.pen_swipe("UP", distance=60)
事件监听
# Toast 监听
d.start_listen_toast()
d(text="提交").click()
print("Toast:", d.get_latest_toast(timeout=3))
# 检查 Toast
if d.check_toast("保存成功", fuzzy="contains"):
print("操作成功")
屏幕录制
方式一:手动控制
# 开始录制
d.start_recording("/tmp/recording")
# ... 执行操作 ...
# 停止并编码为 MP4
video_path = d.stop_recording("/tmp/recording/output.mp4")
print(f"视频已保存: {video_path}")
方式二:上下文管理器(推荐)
# 异常时自动停止录屏,资源必定释放
with d.record("/tmp/output.mp4") as rec:
d(text="登录").click()
d(text="密码").input_text("xxx")
# 退出 with 块时自动合成视频
print(f"视频已保存: {rec.video_path}")
设备控制
# 亮屏/熄屏
d.wake_up_display()
d.close_display()
# 按键
from devhelmkit.model.keys import KeyCode
d.press_keycode(KeyCode.ENTER) # 确认键
# 截图
img = d.screenshot()
img.save("capture.png")
# 安装应用
d.app_install("/path/to/app.hap")
应用管理
# 启动应用(自动探测 main ability,无需手动指定 Ability 名)
d.app_start("com.example.app")
# 指定 Ability 启动
d.app_start("com.example.app", "EntryAbility")
# 强制重启(回桌面 → 停止 → 启动)
d.force_start_app("com.example.app")
# 强制重启并清除数据
d.force_start_app("com.example.app", clear_data=True)
# 停止 / 卸载 / 清除数据
d.app_stop("com.example.app")
d.app_uninstall("com.example.app")
d.clear_app_data("com.example.app")
# 查询应用信息
d.app_list() # 已安装应用列表
d.has_app("com.example.app") # 是否已安装
d.app_current() # 当前前台应用 (package, ability)
d.get_app_info("com.example.app") # 完整应用信息 dict
深链 / Schema
# 网页 URL(自动用系统浏览器打开)
d.open_url("https://www.example.com")
# 应用深链(由系统选择处理方,如 kwai:// 触发快手App)
d.open_url("kwai://myprofile")
# 强制指定是否用系统浏览器
d.open_url("https://www.example.com", system_browser=False)
WebView 自动化
需要安装:
pip install devhelmkit[webview]
需下载与设备 WebView 版本匹配的 chromedriver:
# 方式一:使用内置下载脚本(推荐)
# 自动探测设备 WebView 版本并下载
python scripts/download_chromedriver.py --auto
# 指定版本号下载
python scripts/download_chromedriver.py 114 -o ./chromedriver
# 查看可用版本
python scripts/download_chromedriver.py --list
或手动下载后按以下结构放置:
chromedriver_search_path/
├── chromedriver_114/
│ ├── chromedriver.exe # Windows
│ ├── chromedriver # Linux
│ └── chromedriver.mac # macOS
└── chromedriver_132/
├── chromedriver.exe
├── chromedriver
└── chromedriver.mac
# 连接应用 WebView
wv = d.webview(
"com.huawei.hmos.browser",
chromedriver_search_path="/path/to/chromedriver_search_path"
)
# 通过 selenium webdriver 操作
wv.driver.get("https://www.example.com")
wv.driver.find_element("id", "search").send_keys("devhelmkit")
# 释放资源
wv.close()
架构
devhelmkit/ # 仓库根
├── src/devhelmkit/ # 包源码(src layout)
│ ├── core/ # 跨平台契约
│ │ ├── base_driver.py # BaseDriver:设备驱动契约
│ │ ├── base_component.py # BaseComponent:控件契约
│ │ ├── base_window.py # BaseWindow:窗口契约
│ │ ├── selector_spec.py # SelectorSpec:纯数据选择器
│ │ └── vision/ # 图像匹配 + OCR(平台无关)
│ │ ├── image_matcher.py # OpenCV 模板 + 特征匹配
│ │ ├── ocr_engine.py # RapidOCR 封装
│ │ └── vision_extension.py # d.vision 命名空间
│ ├── model/ # 纯数据类型(Rect / KeyCode / GestureAction / ...)
│ ├── harmony/ # HarmonyOS 平台实现
│ │ ├── driver.py # 平台驱动门面
│ │ ├── config.py # HarmonyDriverConfig
│ │ ├── device/ # hdc 命令封装 + RPC 通道
│ │ ├── rpc/ # 二进制 RPC 协议 + 远程对象管理
│ │ ├── finder/ # 控件查找(uitest + uitree 双后端)
│ │ ├── agent/ # 设备端 uitest 守护进程管理
│ │ └── webview/ # WebView 自动化(chromedriver + selenium)
│ ├── uiviewer/ # 网页版控件查看器(双端口 Web 服务)
│ ├── android/ # Android 平台(预留)
│ ├── utils/ # 工具(日志 / 重试 / 超时)
│ └── assets/so/ # 设备端 agent.so 二进制
└── scripts/ # 辅助脚本(chromedriver 下载工具)
完整 API 参考见 api_reference.md。
开发
代码结构约定
core/不得依赖平台实现model/无内部依赖,可跨平台复用- 平台实现按
device/、rpc/、finder/组织 - RPC 层不感知 UI 对象;设备通道不理解控件定位
贡献
欢迎提交 Issue 和 Pull Request。
- 提交 Issue:请使用对应模板(Bug 报告 / 功能请求),提交前先搜索已有 Issue避免重复。安全问题请勿公开提交,参见 SECURITY.md。
- 提交 Pull Request:请阅读贡献指南,遵循代码分层约束与注释规范,并填写 PR 模板。
参与本项目请遵守行为准则。版本变更记录见 CHANGELOG.md。
许可证
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file devhelmkit-0.3.1.tar.gz.
File metadata
- Download URL: devhelmkit-0.3.1.tar.gz
- Upload date:
- Size: 1.1 MB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
737bad6b8eaf7e946ced8151d8049e41b2a982b7136c7cd385b39f7fcf553b38
|
|
| MD5 |
1c7f01d5b63dd09c399c40155fcc1901
|
|
| BLAKE2b-256 |
84c133dccf6ec1155a8eebb66131c87ca20484a27f57283f42b236c774ef4c5e
|
Provenance
The following attestation bundles were made for devhelmkit-0.3.1.tar.gz:
Publisher:
publish.yml on yabi-zzh/devhelmkit
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
devhelmkit-0.3.1.tar.gz -
Subject digest:
737bad6b8eaf7e946ced8151d8049e41b2a982b7136c7cd385b39f7fcf553b38 - Sigstore transparency entry: 2046316369
- Sigstore integration time:
-
Permalink:
yabi-zzh/devhelmkit@89b06c97806b3e09ab405db9a37d5dc81a83e230 -
Branch / Tag:
refs/tags/v0.3.1 - Owner: https://github.com/yabi-zzh
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@89b06c97806b3e09ab405db9a37d5dc81a83e230 -
Trigger Event:
push
-
Statement type:
File details
Details for the file devhelmkit-0.3.1-py3-none-any.whl.
File metadata
- Download URL: devhelmkit-0.3.1-py3-none-any.whl
- Upload date:
- Size: 1.1 MB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5ebf70c8973028c677c28db5e7b5f3c8d31e7eaacc30e381018f748a3ef8af8e
|
|
| MD5 |
6fd90ac211ec0bf7d2af23b7daa8dd8f
|
|
| BLAKE2b-256 |
1dfb214fedcdf4e44c9a3c39403c9dfaa6aa88e17f1c91f49dea439e97d482b3
|
Provenance
The following attestation bundles were made for devhelmkit-0.3.1-py3-none-any.whl:
Publisher:
publish.yml on yabi-zzh/devhelmkit
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
devhelmkit-0.3.1-py3-none-any.whl -
Subject digest:
5ebf70c8973028c677c28db5e7b5f3c8d31e7eaacc30e381018f748a3ef8af8e - Sigstore transparency entry: 2046316908
- Sigstore integration time:
-
Permalink:
yabi-zzh/devhelmkit@89b06c97806b3e09ab405db9a37d5dc81a83e230 -
Branch / Tag:
refs/tags/v0.3.1 - Owner: https://github.com/yabi-zzh
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@89b06c97806b3e09ab405db9a37d5dc81a83e230 -
Trigger Event:
push
-
Statement type: