# 应用UI测试（基于Python）

## 框架概述

DevEco Testing Hypium （以下简称Hypium）是HarmonyOS平台的UI自动化测试框架，支持用户使用Python语言为应用编写UI自动化测试脚本，主要包含以下特性：

1. Hypium提供了控件、图像和比例坐标等**多种控件定位能力** ，支持多窗口操作以及触摸屏/鼠标/键盘等**多种模拟输入功能** ，支持**多设备**并行操作，能够覆盖各类场景和多种形态设备上的自动化用例编写需求，可支持鸿蒙手机、平板、PC等设备。
2. Hypium提供了在PyCharm中使用的**用例编写辅助插件**，支持控件查看/投屏操作等多种用例开发辅助功能，提升用例开发体验和效率。
3. Hypium能够为执行的用例生成详细的**用例执行报告**，并且自动记录设备日志以及执行步骤截图，为用户提供高效和专业的测试用例执行和结果分析体验。

## 安装向导

**1.安装Python**

推荐从[Python官网](https://www.python.org/)安装Python3.10版本。

**2.安装PyCharm**

推荐从[PyCharm官网](https://www.jetbrains.com.cn/en-us/pycharm/)安装2024.2以后的社区版本。
> 说明
>
> 项目创建功能只支持2024.2至2026.2的PyCharm版本。2024.3版本由于pycharm自身原因，只能选择单设备模板进行创建。

**3.安装hdc**

请参考[调试工具-hdc](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/hdc)中环境准备章节来安装和配置hdc环境。

**4.安装** **Hypium**

* **方式一：** **PyPI在线安装(推荐)**

在命令行中执行以下命令安装最新版本hypium

```screen
pip install hypium -U --trusted-host mirrors.huaweicloud.com -i https://mirrors.huaweicloud.com/repository/pypi/simple
```

* **方式二：安装包离线安装**

访问华为开发者联盟官网[下载DevEco Testing Hypium安装包](https://developer.huawei.com/consumer/cn/download/deveco-testing-hypium)。下载后解压该安装包，找到其中的hypium-6.1.0.210.zip（此版本仅作为示例，请以实际版本号为准）。再次解压hypium-6.1.0.210.zip，进入解压后的文件目录执行以下命令进行安装。

**自动安装**

```screen
python install.py -g hypium_basic   #安装基础包，通过-g执行安装组合模式
```

> 注意
>
> 仅6.1及之后版本支持离线自动安装。

**手动安装**

```screen
python -m pip install xdevice-6.1.0.210-py3-none-any.whl
python -m pip install xdevice_devicetest-6.1.0.210-py3-none-any.whl
python -m pip install xdevice_ohos-6.1.0.210-py3-none-any.whl
python -m pip install hypium-6.1.0.210-py3-none-any.whl

# 此版本仅作为示例，实际请根据项目使用的版本选择
```

**5.DevEco Testing Hypium插件安装及使用方法**
> 注意
>
> Mac系统使用UiViewer功能时，需在设置面板中手动指定hdc路径，详情可见 **本小节中 · 插件功能 Ⅳ.设置面板区域-hdc路径**。
>
> 若设备ROM版本和hypium都为6.1及以上版本，则UiViewer版本也需要升级至6.1及以上版本，否则在用例执行过程中，UiViewer会出现断连现象。

* **插件安装**

Ⅰ. 访问华为开发者联盟官网[下载页面](https://developer.huawei.com/consumer/cn/download/deveco-testing-hypium)下载DevEco Testing Hypium安装包，下载后解压该安装包，找到其中的hypium-pycharm-plugin-6.1.0.210.zip（该版本号仅做示例，请以实际版本号为准），此文件为插件的安装包，无需再进行解压。

![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/28/v3/yLjEA6gOT-a8iNz21ltECg/zh-cn_image_0000002633533148.jpg?HW-CC-KV=V1&HW-CC-Date=20261030T062830Z&HW-CC-Expire=31536000000&HW-CC-Sign=41B9727AA1D59EBB7C2BDCA063DBC42CD7863BD6813F5BBE1509594EADD1F21D "点击放大")

Ⅱ. 打开PyCharm后，点击File -> Settings -> Plugin -> 齿轮图标 -> Install Plugin from Disk。在弹出的文件选择器中，选择第一步下载的hypium-pycharm-plugin-6.1.0.210.zip（该版本号仅做示例，请以实际版本号为准）离线安装包，完成安装。安装完成后，重启PyCharm即可使用新安装的Deveco Testing Hypium插件。
> 说明
>
> 在6.0及以后的版本中，DevEco Testing Hypium插件在下载包中的名称由"DevEcoTesting-Hypium"修改为"hypium-pycharm-plugin"。

![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/ad/v3/YotWukS9Sku5eJqpwtqeFQ/zh-cn_image_0000002633533186.png?HW-CC-KV=V1&HW-CC-Date=20261030T062830Z&HW-CC-Expire=31536000000&HW-CC-Sign=AD8DDCD09203B07669C418B2DCC33DBD371D89A015C6102CB4F3D043FB30ABA5 "点击放大")

安装完成后在Plugins界面可以看到DevEcoTesting-Hypium插件。

![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/df/v3/8z3XfDoPROKmCw5syMNXWA/zh-cn_image_0000002633693104.png?HW-CC-KV=V1&HW-CC-Date=20261030T062830Z&HW-CC-Expire=31536000000&HW-CC-Sign=253BB233D1643B6E561C7372553F460202B428929384C08AA5FE15D84C790986)

* **插件功能**

PyCharm有三个主要的开发功能区，如下图所示。DevEco Testing Hypium插件在不同的开发功能区提供了对应的用例开发辅助功能，在PyCharm的设置面板中提供了插件的设置功能，在PyCharm的工程新建面板中提供了用例工程模板创建功能，下文分区域介绍这些功能。

![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/b2/v3/YAPD1ubxQImQ6cEpFOTj8A/zh-cn_image_0000002633693072.png?HW-CC-KV=V1&HW-CC-Date=20261030T062830Z&HW-CC-Expire=31536000000&HW-CC-Sign=A386BFD2869200BC2B84844385EE8623C106A35803E2A52DF34C7D74ED60A817 "点击放大")

**Ⅰ. 项目文件区域**

在项目文件区域右键点击项目目录或者文件，选择 DevEco Testing Hypium，弹出对应的功能菜单。

![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/a5/v3/YaqyU_BXTXWwcXoq2khzXg/zh-cn_image_0000002633533204.png?HW-CC-KV=V1&HW-CC-Date=20261030T062830Z&HW-CC-Expire=31536000000&HW-CC-Sign=BC32CA51037D2496388C8D981E6584EA566A1635F9327EC7C5733CA0009E6397)

功能菜单根据选择的目录和文件不同存在区别，详细参见下表：

|序号|功能|图片|说明|注意|
|:-|:------------|:-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|:------------------------------------------------------------------|:-----------------------------------------------------------------------------------------------------------------------------------------|
|1|执行当前目录|![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/b3/v3/xPCnVrGfTdqWRkNDUrOONA/zh-cn_image_0000002633693078.jpg?HW-CC-KV=V1&HW-CC-Date=20261030T062830Z&HW-CC-Expire=31536000000&HW-CC-Sign=ACACC6BB9D203ABFDB932908D7956D57DD4225AEF44FD7C925BFB0FF33A6395A "点击放大")|执行当前目录中的所有测试用例。|此功能仅右键选中文件夹时可用。|
|2|一键执行当前用例|![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/ad/v3/-PN8h_iyThKUAgS1e6OJvA/zh-cn_image_0000002633693086.jpg?HW-CC-KV=V1&HW-CC-Date=20261030T062830Z&HW-CC-Expire=31536000000&HW-CC-Sign=864FCD0495499E4C2B639F1579ABC5F28DA30EFC224DB9EAFAB1EDCAB43EC59F "点击放大")|执行当前选中的测试用例文件。|此功能仅右键选中测试用例对应Python或JSON文件时可用。|
|3|生成Hypium模板用例|![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/b8/v3/Qv01GZUFQ8m7PuGMm5oKIw/zh-cn_image_0000002663932259.jpg?HW-CC-KV=V1&HW-CC-Date=20261030T062830Z&HW-CC-Expire=31536000000&HW-CC-Sign=DF971F690D44F888154438891E44E5F27326CEA3D06B561007F13487A35FB0E4 "点击放大")|在当前选中的目录下生成测试用例模板文件。|  |
|4|生成Hypium模板测试套|![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/b8/v3/Qv01GZUFQ8m7PuGMm5oKIw/zh-cn_image_0000002663932259.jpg?HW-CC-KV=V1&HW-CC-Date=20261030T062830Z&HW-CC-Expire=31536000000&HW-CC-Sign=DF971F690D44F888154438891E44E5F27326CEA3D06B561007F13487A35FB0E4 "点击放大")|在当前选中的目录下生成测试套模板文件。|  |
|5|生成测试服务包|![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/c4/v3/gcC4id5zTjuHLV2YfmE9Uw/zh-cn_image_0000002664012329.png?HW-CC-KV=V1&HW-CC-Date=20261030T062830Z&HW-CC-Expire=31536000000&HW-CC-Sign=91EE9EFA04E424A88670F294D98C3F3B7A9BC9CEF2F59DD4C8BFCB70CD3FB138 "点击放大")|该功能支持生成"回归测试"和"场景化性能"两种类型的测试服务包模板，用户可根据实际需求填写配置项，完成设置后即可生成对应的测试服务包。|1. 该功能仅在右键点击项目根目录时可用，选中其他目录无法触发此功能。 2. 项目根目录下需要包含 testcases 文件夹。 3. 项目根目录下需存在 setup-sceneperf.py 或 setup-regression.py 文件之一，以支持相应测试服务包的生成。|

**Ⅱ. 代码编辑区域**

|序号|功能|图片|说明|注意|
|:-|:-----------|:-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|:--------------------|:------------------------------------------------------------------------------------------|
|1|一键执行当前用例|![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/c7/v3/A1zJiuzQRzGx_NdClNnOMg/zh-cn_image_0000002633533150.jpg?HW-CC-KV=V1&HW-CC-Date=20261030T062830Z&HW-CC-Expire=31536000000&HW-CC-Sign=AD9902A298FC874581E21BF0E7E92C0243DE52CACFC2C63A19C6072EB2CBBBBD "点击放大")|执行当前文件对应的测试用例。|此功能仅在当前项目根目录下存在config文件夹时可用。|
|2|一键调试当前用例|![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/c7/v3/A1zJiuzQRzGx_NdClNnOMg/zh-cn_image_0000002633533150.jpg?HW-CC-KV=V1&HW-CC-Date=20261030T062830Z&HW-CC-Expire=31536000000&HW-CC-Sign=AD9902A298FC874581E21BF0E7E92C0243DE52CACFC2C63A19C6072EB2CBBBBD "点击放大")|以调试模式执行当前文件对应的测试用例|此功能仅在当前项目根目录下存在config文件夹时可用。|
|3|选区快速执行|![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/c7/v3/A1zJiuzQRzGx_NdClNnOMg/zh-cn_image_0000002633533150.jpg?HW-CC-KV=V1&HW-CC-Date=20261030T062830Z&HW-CC-Expire=31536000000&HW-CC-Sign=AD9902A298FC874581E21BF0E7E92C0243DE52CACFC2C63A19C6072EB2CBBBBD "点击放大")|快速执行选中的代码片段，无需运行整个用例。|1. 此功能仅在正常连接被测设备时可用。 2. 此功能仅在当前项目根目录下存在config文件夹时可用。|
|4|选区快速调试|![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/c7/v3/A1zJiuzQRzGx_NdClNnOMg/zh-cn_image_0000002633533150.jpg?HW-CC-KV=V1&HW-CC-Date=20261030T062830Z&HW-CC-Expire=31536000000&HW-CC-Sign=AD9902A298FC874581E21BF0E7E92C0243DE52CACFC2C63A19C6072EB2CBBBBD "点击放大")|以调试模式快速执行选中的代码片段。|1. 此功能仅在正常连接被测设备时可用。 2. 此功能仅在当前项目根目录下存在config文件夹时可用。|
|5|生成Hypium模板代码|![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/ec/v3/9OoVWg7BTqOBJcdppwsRHA/zh-cn_image_0000002664012297.png?HW-CC-KV=V1&HW-CC-Date=20261030T062830Z&HW-CC-Expire=31536000000&HW-CC-Sign=791322F0516123A96E575D6CCA618CA37FFB82F00E89FE385FBF9E9947D1CC98 "点击放大")|快速生成内置的模板操作代码。|  |
|6|函数快速执行|![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/0a/v3/0Se9zhDETtOf5xf8RgbwSA/zh-cn_image_0000002633693114.jpg?HW-CC-KV=V1&HW-CC-Date=20261030T062830Z&HW-CC-Expire=31536000000&HW-CC-Sign=7B14A8BFC319CFB8760B5234C76CD8F0D2C2C68CAC01FFCF702EF08AAD63969B "点击放大")|快速执行测试用例中的指定生命周期函数。|1. 此功能仅在正常连接被测设备时可用。 2. 此功能仅在当前项目根目录下存在config文件夹时可用。 3. 此功能仅在当前编辑的文件为Hypium测试用例Python文件时可用。|

**Ⅲ. ToolWindow区域**

**UiViewer功能**

DevEco Testing Hypium插件会在PyCharm界面右边缘的ToolWindow区域生成UiViewer标签，点击后会展开UiViewer功能面板。UiViewer功能目前分为4个界面：设备选择界面 、单设备控件查看界面 、单设备投屏界面 、双设备投屏界面。
> 注意
>
> UiViewer插件当前仅支持USB连接本地设备调测和本地模拟器进行调测，但是由于模拟器性能资源管理策略，当模拟器处于后台或被其他页面遮挡时，将不会进行画面渲染绘制。此时在投屏时会出现黑屏闪烁现象，如需规避，需要使模拟器处于前台显示。

**设备选择界面**

设备选择界面如下图所示， 若首次进入该界面，或设备状态发生变化，需点击"刷新"按钮以更新设备列表。

![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/b7/v3/BRp86enMRHiRMx8l2VHYyw/zh-cn_image_0000002663932235.png?HW-CC-KV=V1&HW-CC-Date=20261030T062830Z&HW-CC-Expire=31536000000&HW-CC-Sign=88AC38A47F4DBCC19F3BC213E8B63ED9B9A54C036F9E57FD1A58976365A07C0C)

设备信息说明见下表：

|序号|参数名称|说明|图片|
|:-|:-----------------|:-------------------------------------------------------------------------------------------|:-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|1|SN（Serial Number）号|该参数为已连接设备的序列号（SN号），用于区分不同设备。|  |
|2|设备类型|该参数为设备连接通道类型，仅支持hdc连接，对应设备类型显示为HDC。|  |
|3|设备状态|该参数显示当前设备是否支持使用 UiViewer 工具："OK" 表示该设备可用；"NOT_SUPPORT" 表示设备不可用。|  |
|4|设备编号|该参数用于在多设备同时投屏时配置各设备的显示位置，用户可手动进行调整。 在双设备投屏界面中，默认情况下，设备编号为 dev1 的设备显示在左侧，设备编号为 dev2 的设备显示在右侧。|  |
|5|添加远程设备|点击后会弹出远程设备IP添加面板，可以在此填入远程设备所在电脑的IP和hdc端口，以此来发现远程电脑上所连接的hdc设备。|![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/d1/v3/o4i3z8f7QsKcfIM4J06pHw/zh-cn_image_0000002633693108.png?HW-CC-KV=V1&HW-CC-Date=20261030T062830Z&HW-CC-Expire=31536000000&HW-CC-Sign=32B22E9120E81806001562D419B549FA3F8123DBFE4134971988C9457C0F0233 "点击放大")|
|6|删除远程设备|在管理远程设备面板中，可以在之前添加的远程IP对象上右键，点击删除按钮进行删除|![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/18/v3/ZDADMB4fRBOEGpzzwuLPTg/zh-cn_image_0000002663932251.png?HW-CC-KV=V1&HW-CC-Date=20261030T062830Z&HW-CC-Expire=31536000000&HW-CC-Sign=B78F4B2D247ED5DE6922360FBBACA509478E62D563A450E4EAE6F656BFB0185E "点击放大")|

设备选择界面最多支持同时选择两个设备进行投屏。

* 若仅勾选一个设备并点击"确定"按钮，则进入单设备投屏界面。
* 若勾选了两个设备并点击"确定"按钮，将进入双设备投屏界面；其中，设备编号为 "dev1" 的设备显示在左侧，设备编号为 "dev2"的设备显示在右侧，用户可以通过设备编号的下拉选项框自定义配置设备编号，控制双设备投屏。

**单设备投屏界面**

![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/ae/v3/-7OsigItSf2CvUjcbzOqVw/zh-cn_image_0000002633533184.png?HW-CC-KV=V1&HW-CC-Date=20261030T062830Z&HW-CC-Expire=31536000000&HW-CC-Sign=9E1CB35AEC6F3DD9FCD85C25C455FFC6929583E2FEBFCCF4737815791F8941EB "点击放大")

**功能说明：**

* **设备切换按钮：**点击后返回设备选择界面，可重新选择要投屏的设备。
* **设备屏幕显示区域：**显示当前设备的实时屏幕画面。在投屏模式下，可通过鼠标点击或滑动该界面来操作设备。
* **工具区：**位于设备屏幕显示区域右侧，从上至下分为以下三个子工具区。

**工具区1：**

该工具区提供控件查看功能。进入控件查看模式后，设备画面将保持静止，不再实时更新。若需获取当前页面的最新控件信息，需手动点击"控件刷新"按钮以重新抓取页面结构和控件数据。

|序号|图标|功能|说明|
|:-|:----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|:-------------|:-------------------------------------------------------------------------------------------------------------------------------|
|1|![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/31/v3/F18mXZcFThqDoC1x9g8LOw/zh-cn_image_0000002664012305.jpg?HW-CC-KV=V1&HW-CC-Date=20261030T062830Z&HW-CC-Expire=31536000000&HW-CC-Sign=5C5F4EB1608029B5E82BB55C993A564F9DD7AB593FC0A22AABF81750F22F3F00)|查看控件|点击该按钮进入控件查看模式，插件会读取设备当前的控件树和屏幕截图，并显示到界面上（此过程需要一定时间，在鼠标光标处于转圈状态时，请勿点击其他按钮，以免操作冲突或导致异常）。在控件查看模式下再次点击该按钮，可退出当前模式，返回实时投屏模式。|
|2|![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/ea/v3/wk5bAK5WQBqCpenjv2ZhrQ/zh-cn_image_0000002633533166.jpg?HW-CC-KV=V1&HW-CC-Date=20261030T062830Z&HW-CC-Expire=31536000000&HW-CC-Sign=100154FB4EF18F96D6CA6C2582E94A9FDAF147A65DC379FF5363F138C6E7388C)|进入高级控件查看模式|点击该按钮进入高级控件查看模式，系统会根据鼠标移动实时高亮对应控件，并持续展示其控件信息。点击某一控件信息后，将自动切换到普通控件查看模式，并定位显示该控件在控件树中的详细信息。 处于高级控件查看模式时，再次点击该按钮，可退出当前模式，则返回实时投屏模式。|
|3|![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/6c/v3/ewlB5xdGTc-hHQSJBDrOLA/zh-cn_image_0000002633533194.png?HW-CC-KV=V1&HW-CC-Date=20261030T062830Z&HW-CC-Expire=31536000000&HW-CC-Sign=11EC67C7DDBAFB165E348A92EBAF8BA0AD52CDD98F475A0090160C97B4540D22)|录制Hypium测试用例脚本|点击该按钮进入操作录制模式，在此模式下，用户点击或操作投屏画面中的控件时，系统将自动识别操作行为，并在编辑器当前光标位置生成对应的 Hypium 自动化测试脚本代码。 处于操作录制模式时，再次点击该按钮可退出当前模式，返回实时投屏模式。|
|4|![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/5/v3/3OLAtMgmTECgMAjPC3XnWw/zh-cn_image_0000002633693112.jpg?HW-CC-KV=V1&HW-CC-Date=20261030T062830Z&HW-CC-Expire=31536000000&HW-CC-Sign=57FCEF735C1DCA514DC555149AAF54A550EE977EFD22EDE7F7DE834C254EED0D)|刷新控件|如果设备界面发生变动，可点击此按钮重新获取当前页面的最新控件信息。|

**工具区2：**

此工具区提供一系列常用的设备操作功能，便于在投屏过程中快速执行基本控制与调试操作，当前支持的功能见下表：

|序号|图标|功能|说明|
|:-|:----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|:-------|:-------------|
|1|![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/61/v3/3GNX6_LAQJSMMLuoOCW16A/zh-cn_image_0000002664012315.jpg?HW-CC-KV=V1&HW-CC-Date=20261030T062830Z&HW-CC-Expire=31536000000&HW-CC-Sign=23BAE15BB183712729263B2FF33570BFE92A01D5E33C8A4FF5EF66A1863314FF)|提高音量|点击后对设备进行音量加操作。|
|2|![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/44/v3/fFLGSb-ZSCm1aopsKCaMsw/zh-cn_image_0000002633693096.jpg?HW-CC-KV=V1&HW-CC-Date=20261030T062830Z&HW-CC-Expire=31536000000&HW-CC-Sign=639E15A4094803A85C525E03C8E0F5907C8DB998361F4BA1B22F95C6E0E293B3)|降低音量|点击后对设备进行音量减操作。|
|3|![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/fb/v3/7Kefi4qbTCimud1hldA85w/zh-cn_image_0000002664012311.jpg?HW-CC-KV=V1&HW-CC-Date=20261030T062830Z&HW-CC-Expire=31536000000&HW-CC-Sign=7D0C87A4DEE649F97E1C9348DFEB8D7E2787C31CB3911EC44A9C48E87E01F5B3)|触发电源键|点击后模拟按下设备电源键。|
|4|![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/bc/v3/74c3GsFcRLG9MKmGooUycA/zh-cn_image_0000002633693106.jpg?HW-CC-KV=V1&HW-CC-Date=20261030T062830Z&HW-CC-Expire=31536000000&HW-CC-Sign=E47216392BEB55F788E9658802FAD973AE03FBDA765703FCE6C5C1AB52567610)|执行重启操作|点击后重启设备。|
|5|![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/dd/v3/c4zaFjaIQQ6m1kI04T1TYw/zh-cn_image_0000002663932273.jpg?HW-CC-KV=V1&HW-CC-Date=20261030T062830Z&HW-CC-Expire=31536000000&HW-CC-Sign=759A831EC56182987C9F15E10FEB30403DA8B649AD0FAFAC4819941E110C791B)|触发返回键|点击后模拟返回键操作。|
|6|![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/95/v3/ZtKcfv89TjO3H13czkA1ig/zh-cn_image_0000002633533202.jpg?HW-CC-KV=V1&HW-CC-Date=20261030T062830Z&HW-CC-Expire=31536000000&HW-CC-Sign=6400DC8DDC5DBE9D98A6264792EA12187A92F20A17DB911D14C83A28A66FFF76)|触发返回桌面操作|点击后模拟返回桌面操作。|

**工具区3：**

此工具区提供系统管理相关功能，当前支持的功能见下表：

|序号|图标|功能|说明|
|:-|:----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|:-----|:----------------------------------------------------------------------------------------------------------------------------|
|1|![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/29/v3/Ep7OmH2AQ3Wu3wfMHdbk5A/zh-cn_image_0000002664012285.jpg?HW-CC-KV=V1&HW-CC-Date=20261030T062830Z&HW-CC-Expire=31536000000&HW-CC-Sign=1C35BC5BA8576A2DB43F13F991EE0B06433CF2D1AE228842983559B1ED4B1402)|查看设备信息|点击后在"设备信息展示区"显示当前设备的信息。|
|2|![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/76/v3/4d_rebETTxWxoy0tL-hC_w/zh-cn_image_0000002664012309.jpg?HW-CC-KV=V1&HW-CC-Date=20261030T062830Z&HW-CC-Expire=31536000000&HW-CC-Sign=DA7F10F859EA10A232949272997847C3B655D2D180E8608A81421FB2830EC201)|执行全屏截图|点击后会将当前屏幕画面保存至当前项目的"resource"文件夹下的"Hypium"目录下。|
|3|![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/d8/v3/JfQvFkeHQyOP7fvkdxQ_AA/zh-cn_image_0000002633533156.jpg?HW-CC-KV=V1&HW-CC-Date=20261030T062830Z&HW-CC-Expire=31536000000&HW-CC-Sign=9B369AC673BE3399E4C30E467E97E57C680BCAB0ED96C7E25CB0AD5D43930E0C)|执行区域截图|点击该按钮后，设备显示界面将进入区域截图状态。此时，在设备画面中按住鼠标左键并拖动，可自由框选需要截图的区域。松开鼠标后，系统将对选定区域进行截图，并自动保存至当前项目的 resource/Hypium/ 目录下。|
|4|![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/92/v3/Mjg8ubUGSsieRFP-b6hqlg/zh-cn_image_0000002663932227.jpg?HW-CC-KV=V1&HW-CC-Date=20261030T062830Z&HW-CC-Expire=31536000000&HW-CC-Sign=53881401C22FFBCE5ECE2A9FA2E1FAC606DB9AD830C3CF863019EB7CFAA16396)|切换竖屏|将设备屏幕方向设置为竖屏（Portrait）状态。点击该按钮后，设备将旋转显示方向至竖屏模式。此操作会向设备发送系统指令，实际效果取决于当前应用是否支持方向控制。|
|5|![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/52/v3/Z7j47TKMRIe8NWXPeT98Dw/zh-cn_image_0000002633533196.jpg?HW-CC-KV=V1&HW-CC-Date=20261030T062830Z&HW-CC-Expire=31536000000&HW-CC-Sign=65297848106D7DF16379964D507659CAE247D7807DCF164E0846F24E62AD3E0E)|切换横屏|将设备屏幕方向设置为横屏（Landscape）状态。点击该按钮后，设备将旋转显示方向至横屏模式。此操作会向设备发送系统指令，实际效果取决于当前应用是否支持方向控制。|
|6|![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/7d/v3/XETBSC46RYCUH_IKaL-ZkQ/zh-cn_image_0000002633693068.jpg?HW-CC-KV=V1&HW-CC-Date=20261030T062830Z&HW-CC-Expire=31536000000&HW-CC-Sign=EF942F7DB713FDE11C660FC98917BD09EB7D2A411536279D79D68AA8E2C6A2AF)|安装应用|点击该按钮后，用户可以从本地计算机选择一个HAP文件安装到连接的设备中。|
|7|![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/fa/v3/l3zRsZQlQ9GRPdBD8LOukA/zh-cn_image_0000002633533188.jpg?HW-CC-KV=V1&HW-CC-Date=20261030T062830Z&HW-CC-Expire=31536000000&HW-CC-Sign=2BA2B09D8F8E6D5B868CC5CF8D57CA7F2BF1B212B31F29158C81E6E9283C039D)|卸载应用|用户可对当前连接设备上已安装的应用程序进行卸载操作。点击该按钮后，系统将获取设备上已安装应用列表，用户可从中选择目标应用并执行卸载。|
|8|![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/6f/v3/SxmGyLbBSGe2o6clOXa4qA/zh-cn_image_0000002663932245.jpg?HW-CC-KV=V1&HW-CC-Date=20261030T062830Z&HW-CC-Expire=31536000000&HW-CC-Sign=5F5D8B61273A0B2E3705D34A6E623E9BD30671C1DCC10DA21934C62DCF08FF06)|发送文件|用户可以从电脑本地选择单个文件或整个目录，通过此功能将其发送至设备端指定的存储路径。|
|9|![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/e4/v3/PcniUC9iSfKoPyI1SjpOgA/zh-cn_image_0000002633693100.jpg?HW-CC-KV=V1&HW-CC-Date=20261030T062830Z&HW-CC-Expire=31536000000&HW-CC-Sign=90EEACDC491CFED7E8FD4B120C65483ED04FCD275DEB11CC2C27B8FBFCF9F491)|管理应用|点击该按钮后将打开一个独立的应用管理界面，用户可以在应用管理界面安装和卸载应用。|
|10|![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/b3/v3/pri5cy-GR9S6bJFoPjGQqg/zh-cn_image_0000002664012291.png?HW-CC-KV=V1&HW-CC-Date=20261030T062830Z&HW-CC-Expire=31536000000&HW-CC-Sign=86E1E52E5D429B904A476634FDAE0449822AF7B601481CCFA54324CECCF13A8B)|录制文本输入|此按钮在进入录制状态后才能够使用。点击此按钮后将进入录制输入状态，此时点击界面上要进行输入的文本框控件后，会弹出一个输出框；用户在输入框中输入要插入的文本后点击确定，此时工具便会在代码编辑区光标处生成录制出的文本输入语句，同时设备侧也会自动输入文本。|

**双设备投屏界面**

该界面支持同时对两个设备进行投屏与操作，双设备投屏时，每个设备的显示区域功能与单设备投屏一致，支持独立触摸控制、截图、旋转等操作。

当需要对某一设备进行控件查看时，插件将自动退出双设备投屏模式，切换至单设备控件查看界面，以确保控件信息的准确展示与操作体验。完成控件查看后，用户可手动返回双设备投屏视图。

![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/fb/v3/i2PhkpEhSn6vlVxR5k4eUA/zh-cn_image_0000002633533192.png?HW-CC-KV=V1&HW-CC-Date=20261030T062830Z&HW-CC-Expire=31536000000&HW-CC-Sign=24FDE663A7608123B8382BA7E46C414DA4ADF4CD3B6804A529F16965184E6188 "点击放大")

**执行结果报告展示功能**

使用"一键执行当前用例"功能完成测试用例执行后，插件将在控制台旁边自动生成执行结果标签。点击该标签，即可查看本次用例执行过程中各步骤的截图。

![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/f3/v3/ef26cbruToyRy1Wxq9CURw/zh-cn_image_0000002663932253.png?HW-CC-KV=V1&HW-CC-Date=20261030T062830Z&HW-CC-Expire=31536000000&HW-CC-Sign=97D4436FEB836026BB854F31EFCBEACBFE4CCB4D1A2741699E7787DC75B6A860 "点击放大")

**Ⅳ. 设置面板区**

打开PyCharm设置面板，选中左侧的DevEco Testing Hypium选项，可以进入DevEco Testing Hypium的设置面板，如下图所示。

![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/ad/v3/TciMEt8bRhuXVW-N93ytfw/zh-cn_image_0000002633533200.png?HW-CC-KV=V1&HW-CC-Date=20261030T062830Z&HW-CC-Expire=31536000000&HW-CC-Sign=49419455722AF7123AD5C78DF9191C649B12B60D4B2E8FB538D37523BC63CA29)

各个配置项的详细说明见下表：

|序号|功能|说明|注意|
|:-|:-------------|:---------------------------------------------------------------------------------------------------|:----------------------------------------------------------------------|
|1|配置文件路径|配置一键执行/调试功能所使用的配置文件路径，如不设置，默认使用当前项目下的config文件夹作为配置文件路径。|-|
|2|测试用例路径|配置一键执行/调试功能所使用的测试文件路径，如不设置，则默认使用当前项目下的testcases文件夹作为测试用例路径。|-|
|3|额外执行参数|配置运行用例一键执行/调试功能时，额外传递给Hypium测试框架的命令行参数。例如用户需要开启Hypium框架的用例单步骤截图功能，可以将额外执行参数设置为"-ta screenshot:true"。|-|
|4|是否以bin模式执行|配置是否以bin模式执行用例时，通过该模式执行时，可避免投屏和用例执行冲突。|**正常使用时该选项无需配置。** 该设置项在DevEco Testing Hypium 6.0.5.200以及更新的版本中不再需要，已移除。|
|5|Hdc路径|配置UiViewer所使用的hdc路径。|-|
|6|Hdc端口|配置UiViewer所使用的hdc端口，默认为8710|**正常使用时该选项无需进行配置。**|
|7|高级控件查看模式自动刷新间隔|配置UiViewer功能中的高级控件查看模式的刷新间隔，默认60秒自动重新获取一次界面的布局，最小时间可以设为30秒，最大时间300秒。|-|
|8|录制步骤是否生成性能脚本|操作录制模式默认生成功能测试脚本，通过该选项可以配置生成性能测试步骤脚本。注意执行性能测试脚本需要首先安装hypium-perf性能测试插件。|该功能仅DevEco Testing Hypium 6.0.5.200以及更新的版本支持。|
|9|是否使用视频流投屏模式|配置是否使用视频流模式投屏。当投屏异常时，可尝试将此选项改为否，切换投屏方式，注意此时的投屏帧率大幅降低，|**正常使用时该选项无需进行配置。**|
|10|依赖下载参数|配置生成测试服务包下载PyPI依赖包是传递给pip命令的额外参数。例如出现依赖下载慢或失败的情况时，可设置"-i <PyPI Source>"参数，配置可正常访问的PyPI源。|-|
|11|本地依赖文件存放文件夹|设置该文件夹后，在生成测试服务包时，插件将优先使用该目录中已下载的依赖文件，避免重复在线下载，有效应对因网络问题导致的PyPI依赖包安装失败等场景。|-|

**Ⅴ. 工程创建区域**

在PyCharm顶部点击File -> New Project 进入模板工程创建面板。

![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/34/v3/oW36F76KS8-YhQPN0ZNuwQ/zh-cn_image_0000002664012293.png?HW-CC-KV=V1&HW-CC-Date=20261030T062830Z&HW-CC-Expire=31536000000&HW-CC-Sign=0D88A8B23E0F9330744259F3D429ED5896F964E58D641B255A4A1FB9C06338AA)

点击左侧的DevEco Testing Hypium，可以创建Hypium用例模板工程。共有两种类型的Hypium模板工程，分别对应单设备和双设备的测试场景。

![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/a3/v3/HTC-XYcWTqCSFg2ziZRcww/zh-cn_image_0000002664012327.jpg?HW-CC-KV=V1&HW-CC-Date=20261030T062830Z&HW-CC-Expire=31536000000&HW-CC-Sign=0A2F04DA8789855FE087F186E2474ED2F3F9E2E9BEB76E559ECD27E8AFA29754 "点击放大")

选择对应模板，配置工程路径以及Python环境参数，点击Create即可创建Hypium测试用例工程。工程目录中包含一个模板用例和一个模板配置文件user_config.xml。

以单设备工程为例，创建完成后的界面如下图所示。连接被测设备后，可右键点击模板用例文件代码编辑区域"执行hypium用例"来运行当前用例。

![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/5/v3/Jm_Thf3jS6mXpICw8VTygA/zh-cn_image_0000002633693110.png?HW-CC-KV=V1&HW-CC-Date=20261030T062830Z&HW-CC-Expire=31536000000&HW-CC-Sign=EE0090375C627E8AFBEB0EDAF7A0B5F12BD47E672C940FD55009C0DA2A700C88)

## 测试脚本开发快速入门

本章节将指导用户创建并执行一个简单的测试脚本工程，快速掌握项目目录结构中的关键文件，熟悉基于Hypium的测试脚本开发流程。

* **测试脚本工程创建**

测试脚本工程创建主要有两种方式：

a）直接使用以下附件中的模板工程。

[HypiumProjectTemplate.zip](https://alliance-communityfile-drcn.dbankcdn.com/FileServer/getFile/cmtyPub/011/111/111/0000000000011111111.20260828145420.46179425033343051389088358461583:50001231000000:2800:FD003374EEB2F5C3B0DB924EFED279407454A3863770651236418B114C1E9587.zip?needInitFileName=true)

b）通过PyCharm上的DevEcoTesting-Hypium插件进行创建。请参考本文档的**"安装向导 -> DevEco Testing Hypium插件安装及使用方法 -> 插件功能 -> 工程创建区域** **"**小节。

**Ⅰ.工程目录文件介绍**

```screen
HypiumProjectTemplate
|     |----aw                                     // 工程中自定义模块文件夹
|     |     |----Utils.py                           // 示例模块文件
|     |----config                                   // 测试工程配置文件夹
|     |     |----user_config.xml                    // 测试工程配置文件
|     |----resource                              // 测试资源文件夹，测试过程中用到的资源文件默认会优先从当前文件夹进行查找。
|     |----testcases                             // 测试用例文件夹，测试过程中的测试用例文件优先会从当前文件夹进行查找。
|     |    |----Example.json                        // Example测试用例配置文件，配置用例所需设备等参数。
|     |    |----Example.py                          // Example测试用例文件，存储测试逻辑代码。注意该文件无法直接运行，要通过测试框架启动后加载执行，详情参见后文测试用例执行部分。
|     |----main.py                               // 测试用例执行入口文件，用户可以通过运行该文件启动测试任务，执行测试用例。
```

**Ⅱ.工程配置文件介绍**

```screen
<?xml version="1.0" encoding="UTF-8"?>
<user_config>
    <environment>
        <!-- type: 设备连接方式，仅支持设置为usb-hdc，表示使用hdc命令控制设备（默认)。 -->
        <device type="usb-hdc">
            <!-- ip: 远端hdc server的ip地址，ip和port为空时使用本地设备，非空时使用远端设备。 -->
            <!-- port: 远端hdc server的端口号 -->
            <!-- sn：设备序列号，设为空时，表示所有设备均可用 -->
            <info ip="" port="" sn="sn"/>
            <!-- 可添加多个info标签，配置多个设备 -->
            <info ip="" port="" sn="sn"/>
        </device>
    </environment>
    <testcases>
        <!-- 测试用例目录，该属性为空时默认使用当前项目下的testcases目录。 -->
        <dir></dir>
    </testcases>
    <resource>
        <!-- 测试资源文件目录，该属性为空时默认使用当前项目下的resource目录。 -->
        <dir></dir>
    </resource>
    <!-- 用例执行日志级别，当前仅支持设置为INFO或者DEBUG，默认为INFO，如需更详细信息可设置为DEBUG。 -->
    <loglevel>DEBUG</loglevel>
    <devicelog>
        <!-- 指定用例执行完成后自动从设备端拉取的文件目录，多个目录使用分号分隔。 -->
        <dir>/data/log/tee;/data/log/test</dir>
        <!-- 设置用例执行时抓取的hilog日志等级，默认值为INFO。 -->
        <loglevel>DEBUG</loglevel>    
        <!-- 设置单个用例执行完成并抓取设备端hilog日志文件后，是否自动清空设备端的日志文件，默认值为true。-->
        <clear></clear>                
        <!-- 设置用例执行完成后是否抓取设备端hilog日志文件，默认值为ON。注意设置为OFF时上述devicelog配置下的dir、loglevel以及clear属性不生效。 -->
        <enable>ON</enable>            
    </devicelog>
    <taskargs>
        <!-- pass_through，透传参数给测试用例。如{"task_id":"950191","user_define":{"execType":"3"}} -->
        <!-- 参数获取方法：from xdevice import Variables; print(Variables.config.pass_through) -->
        <pass_through></pass_through>
        <!-- repeat，用例重复运行多少次。大于1的整数才生效 -->
        <repeat></repeat>
        <!-- screenshot，操作类接口运行后是否截图。true开启/false不开启，默认值false -->
        <screenshot>false</screenshot>
        <!-- screenrecorder，用例Step步骤是否录屏。true开启/false不开启，默认值false -->
        <screenrecorder>false</screenrecorder>
    </taskargs>   
</user_config>
```

**Ⅲ.测试用例介绍**

Hypium 测试用例由两部分组成：测试用例配置文件（JSON 格式）和测试用例脚本文件（Python 格式）。测试用例的组织方式支持两种模式：

* **单个用例模式：**包含一个测试用例脚本（Python）文件和一个测试用例配置（JSON）文件；
* **测试套模式：**包含一个测试套脚本（Python）文件、多个测试用例脚本（Python）文件和一个测试套配置（JSON）文件。

用户可根据实际需求选择合适的组织方式。

**单个测试用例模式**

* **测试用例脚本文件**

该文件包含测试用例的执行逻辑，核心为三个关键的生命周期函数：setup、process、teardown。在用例开发时，用户需要根据业务需求在对应的函数中编写测试逻辑代码。生命周期函数的详细说明见下表：

|序号|生命周期函数|说明|
|:-|:-------|:----------------------------------|
|1|setup|测试用例的前置步骤，主要用于执行测试用例的预置动作。|
|2|process|测试用例的实际操作步骤，主要描述当前测试用例中的所有测试用例步骤集合。|
|3|teardown|测试用例的清理步骤，主要用于执行测试用例的环境清理等操作。|

**示例代码**

```screen
# !/usr/bin/env python
# coding: utf-8
from devicetest.core.test_case import TestCase, Step
from devicetest.utils.file_util import get_resource_path
from hypium import *
from aw import Utils
class Example(TestCase):
    def __init__(self, controllers):
        self.TAG = self.__class__.__name__
        TestCase.__init__(self, self.TAG, controllers)
        self.driver = UiDriver(self.device1)
    def setup(self):
        Step('1.回到桌面')
        self.driver.swipe_to_home()
    def process(self):
        Step('2.检查短信应用版本')
        mms_version = Utils.get_app_version_code(self.driver, 'com.ohos.mms')
        host.check_greater(mms_version, 0)
        Step('3.点击桌面上的短信')
        self.driver.touch(BY.text("信息"))
    def teardown(self):
        Step("4. 停止短信应用")
        self.driver.stop_app("com.ohos.mms")
```

* **测试用例配置文件**

该文件主要描述测试用例的配置信息，如测试用例所需设备类型和数量、测试用例的测试驱动信息、测试用例的描述信息等。

**注意**：JSON文件不支持注释，请在使用示例时移除其中以 "//"开头的注释部分。

**示例：**

```screen
{
    // description属性为测试用例的功能描述。
    "description": "Config for app test suites",
    // environment属性用于配置测试用例需要的设备类型和数量。
    "environment": [
        {
            "type": "device",   // 设备操作系统类型，device表示HarmonyOS设备。
            "label": "phone"    // 设备物理形态，phone为手机，tablet为平板，设置为空字符串或者移除该属性表示用例对设备类型无要求。用户可以通过执行hdc shell param get const.product.devicetype查看设备类型。
        }，
        {
            "type": "device",   // 测试用例需要多个设备时，在environment属性中添加多个设备配置项。
            "label": "phone"
        }
    ],
    // driver字段主要描述测试用例的测试驱动是什么，以及具体要执行的Python脚本文件在哪（填写与当前JSON文件的相对路径即可）
    // 不填写则在当前JSON文件下寻找同名Python文件
    "driver": {
        "type": "DeviceTest",
           }
}
```

**测试套模式**

* **测试套脚本文件**

该文件包含测试套的初始化和清理逻辑，核心为两个关键的生命周期函数：setup、teardown。在用例开发时，用户需要根据业务需求在对应的函数中编写测试逻辑代码。生命周期函数的详细说明见下表：

|序号|生命周期函数|说明|
|:-|:-------|:------------------------|
|1|setup|整个测试套的前置步骤，在测试套运行前先执行该函数。|
|2|teardown|整个测试套的清理步骤，在执行完所有测试用例后执行。|

**示例代码**

```screen
from devicetest.core.test_case import Step
from devicetest.core.suite.test_suite import TestSuite
class Testsuite1(TestSuite):
    # 测试套的前置步骤将在所有测试用例执行前运行。当多个测试用例具有相同的初始化操作时，可将共用的前置逻辑定义在此。
   def setup(self):
        Step("TestSuite: setup")
    # 测试套的清理步骤会在所有测试用例执行完成后运行。
   defteardown(self):
        Step("TestSuite: teardown")
```

* **测试套配置文件**

该文件主要描述测试套的配置信息，如测试套所需设备类型和数量、测试套的测试驱动信息、测试套的描述信息等。

**注意**：JSON文件不支持注释，请在使用示例时移除其中以 "//"开头的注释部分。

**示例代码**

```screen
{
    "description": "Config for app test suites",
    // environment属性用于配置测试用例需要的设备类型和数量。
    "environment": [
        {
            "type": "device",     // 配置设备操作系统类型，device表示HarmonyOS设备。
            "label": "phone"      // 设备物理形态，phone为手机，tablet为平板，设置为空字符串或者移除该属性表示用例对设备类型无要求。用户可以通过执行hdc shell param get const.product.devicetype查看设备类型。
        }
    ],
    // driver 属性用于定义测试用例的驱动类型及待执行脚本的路径，脚本路径需为相对于当前 JSON 文件的路径。
    "driver": {
        "type": "DeviceTestSuite",
        // 指定测试套配置（JSON）文件对应的测试套脚本（Python）文件路径（可省略 .py 后缀），支持相对路径或绝对路径。若使用相对路径，需相对于测试工程根目录；若未指定，则默认查找与当前 JSON 文件同目录下同名的 Python文件。
        "testsuite": "TS_001/TS_001",
        // 指定测试套中的测试用例脚本(Python)文件列表，指定方式有两种。
        // 方式一：定义 suitecases 字段，并在其中指定测试用例脚本文件的路径。路径可使用相对路径或绝对路径；若使用相对路径，其根目录为当前测试套目录。
        "suitecases": [
            "TestCase1.py",         // 相对路径
            "/path/to/TestCase2.py" // 绝对路径
        ]
        // 方式二：将测试用例脚本（Python）文件保存到测试套目录中，并且设置文件名前缀为"TC_"，框架即可自动扫描当前测试套对应的所有测试用例脚本文件。
    },
    // kits字段主要描述测试用例需要的测试公共kit，如pushkit、shellkit等
    "kits": []
}
```

* **测试用例脚本文件**

测试套模式中的测试用例脚本文件和单个测试用例中对应文件完全相同，请参考上文**"单个测试用例模式** -> **测试用例脚本文件**"小节。此处介绍测试用例脚本文件和测试套关联的两种方式：

**方式一：**框架自动扫描的与测试套关联的测试用例脚本，测试用例脚本的保存目录和文件命名需要满足以下规则：

1. 测试用例脚本文件需与测试套脚本文件位于同一目录。
2. 测试用例脚本文件的文件名前缀是"TC_"（例如：TC_Login.py）。

**方式二：** 在测试套配置文件中指定所有的测试用例脚本文件路径，详情请参考上文的**"测试套配置文件"**小节。

* **测试用例执行**

本章节主要介绍测试用例的执行方式。测试用例支持两种执行方式：一是通过命令行执行，二是通过 PyCharm IDE 中的DevEco Testing Hypium 插件进行一键执行。

**命令介绍**

Hypium框架命令可以分为三类：help、list和run。其中run为最常用的执行命令。

**命令交互入口**

打开命令行窗口，切换到测试脚本工程的根目录，执行以下命令可以进入Hypium控制台。

```screen
python -m hypium
```

**常用命令介绍**

**help命令**

输入help指令可以查询框架指令帮助信息。

```screen
help:
   use help to get information.  
usage:
    run: Displaya list of supported run command.
    list: Display a list of supported device and task record.  
Examples:
    help run
help list
```

> 说明
>
> help run：展示run指令相关说明；help list：展示 list指令相关说明。

**list命令**

list指令用来展示设备和相关的任务信息。

```screen
list:
    This command is used to display device list and task record.  
usage:
      list
      list history
      list <id> 
Introduction:
    list:         display device list
    list history: display history record of a serial of tasks
    list <id>:    display history record about task what contains specific id  
Examples:
    list
    list history
    list 6e****90
```

> 说明
>
> list：展示设备信息；
>
> list history：展示任务历史信息；
>
> list< id >：展示特定id的任务其历史信息。

**run命令**

run指令主要用于执行测试任务。

```screen
run:
    This command is used to execute the selected testcases.
    It includes a series of processes such as use case compilation, execution, and result collection.  
usage: run [-l TESTLIST [TESTLIST ...] | -tf TESTFILE
            [TESTFILE ...]] [-tc TESTCASE] [-c CONFIG] [-sn DEVICE_SN]
            [-rp REPORT_PATH [REPORT_PATH ...]]
            [-respath RESOURCE_PATH [RESOURCE_PATH ...]]
            [-tcpath TESTCASES_PATH [TESTCASES_PATH ...]]
            [-ta TESTARGS [TESTARGS ...]]
            [-env TEST_ENVIRONMENT [TEST_ENVIRONMENT ...]]
            [--retry RETRY] [--session SESSION]
            [--repeat REPEAT]
            action task  
Specify tests to run.
  positional arguments:
  action                Specify action
  task                    Specify task name,such as "ssts", "acts", "hits"
```

run常用指令基本使用方式如下：

|序号|hypium命令|功能|示例|
|:-|:----------------|:------------------------------------------------|:--------------------------------------------------|
|1|run -l <testcase>|运行指定测试用例。如有多个测试用例，测试用例之间以分号分隔。|run -l Example1;Example2|
|2|run -sn|指定运行设备SN号，多个SN号之间以分号分隔（英文分号）。|run -l Example1 -sn sn1 run -l Example1 -sn sn1;sn2|
|3|run -rp|指定报告生成路径，默认报告生成在项目根目录下的reports文件夹，以时间戳或任务id建立子目录。|run -l Example1 -rp /path/to/report|
|4|run -respath|指定测试资源路径，默认为项目根目录下的resource文件夹。|run -l Example1 -respath /path/to/resource|
|5|run -tcpath|指定测试用例路径,默认为项目根目录下的testcases文件夹。|run -l Example1 -tcpath /path/to/testcases|
|6|run - ta|指定模块运行参数，当前仅支持配置步骤截图开关，配置方式参考示例。|run -l Example1 -ta screenshot:true|
|7|run --retry|重新运行上次失败的测试用例，通过-session指定report任务报告目录。|run --retry --session 2022-12-13-12-21-11|

**PyCharm中用例执行**

PyCharm中执行用例依赖本文档的安装向导部分介绍的PyCharm插件：DevEco Testing Hypium，请参考本文档的**"安装向导 -> DevEco Testing Hypium插件安装及使用方法"**小节。

**测试报告查看**

测试框架执行完用例后，会生成执行结果报告。报告默认存放在测试工程目录的reports目录下。如果用户在启动测试任务时通过-rp参数指定了报告路径，报告会生成在指定的路径下。

测试报告目录结构如下：

```screen
当前报告目录（默认目录/指定目录）
    ├── details（用例步骤截图存放目录）
    ├── result（模块执行结果存放目录）
    │     ├── <测试用例1结果>.xml
    │     ├──  ... ...  
    ├── log (设备和任务运行log存放目录)
    │     ├── <测试用例1设备执行>.log
    │     ├── ... ...
    │     ├── <任务执行>.log
    ├── static (报告展示页面css元素存放目录)
    ├── summary_report.html（测试任务可视化报告）
    ├── summary_report.xml（测试任务数据报告）
    ├── summary.ini（记录测试类型，使用的设备，开始时间和结束时间等信息）
    ├── task_info.record（记录执行命令，失败用例等清单信息）
```

## API使用说明

Hypium测试框架提供了两大类API来支持用例的编写：设备相关API和设备无关API。

设备相关的API主要包括四个基础API类：**UiDriver，BY，IUiComponent，UiWindow**。

* **UiDriver**类为UI测试的入口，代表了一个被测设备，提供控件查找、控件检查、用户操作模拟、执行shell命令、安装卸载应用等UI测试核心能力。
* **BY**对象用于描述需要操作的控件属性，实现控件定位。
* **IUiComponent**为UiDriver查找返回的控件对象，提供控件属性查询、控件点击、滑动查找等触控/检视能力。
* **UiWindow**为UiDriver查找返回的窗口对象，提供窗口属性查询、窗口拖动、大小调整等触控能力。

**示例代码**

```screen
# -*- coding: utf-8 -*-
from devicetest.core.test_case import TestCase, Step, CheckPoint
from hypium import *
from hypium.model import WindowFilter
class DemoCase(TestCase):
    def __init__(self, configs):
        self.TAG = self.__class__.__name__
        TestCase.__init__(self, self.TAG, configs)
    def setup(self):
        pass

    def process(self):
        #创建driver对象（self.device1对象在测试用例类中提供）
        driver = UiDriver(self.device1)
        #查找控件
        component = driver.find_component(BY.text("蓝牙"))
        #查找窗口
        window = driver.find_window(WindowFilter().bundle_name("com.huawei.hmos.settings"))
    def teardown(self):
        pass
```

设备无关的API当前主要包括两个基础API类： **host** 和**CV**。

* **host** 提供基础值断言，PC端shell命令执行等PC端基础操作能力。
* **CV** 提供图像查找，图像比较，压缩，清晰度计算等基础图像操作能力。

**示例代码**

```screen
from hypium import host, CV

# 执行PC端命令
echo = host.shell("a.bat")
# 调用图像接口
brightness = CV.calculate_brightness("/path/to/image.jpeg")
```

此外Hypium还包含一些常量类型，例如**KeyCode，UiParam，MatchPattern** 等，以及数据类型**Point，Rect**等。

**示例代码**

```screen
from hypium.model import KeyCode, UiParam, MatchPattern

# 按下电源键（使用常量KeyCode.POWER）
driver.press_key(KeyCode.POWER)
# 向左滑动屏幕（使用常量UiParam.LEFT）
driver.swipe(UiParam.LEFT)
```

下文各小节将详细介绍主要测试场景中Hypium的API的使用方法。

## API使用方法

* **控件查看**

通过 DevEco Testing Hypium插件中的 UiViewer 工具，可以查看界面控件的各项属性，有助于在后续测试用例开发中准确定位控件。具体使用方法请参考本文档的**"安装向导 -> DevEco Testing Hypium插件安装及使用方法**"小节。

![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/cb/v3/aMuiYKS-RLWxO-rbWyWouQ/zh-cn_image_0000002633693118.png?HW-CC-KV=V1&HW-CC-Date=20261030T062830Z&HW-CC-Expire=31536000000&HW-CC-Sign=5A500F675D54931DF68221EC71647A40EA2A9F91F64642ED373EB3B08048E260 "点击放大")

* **控件查找**

Hypium 支持三种主要的控件定位方式：控件属性定位、图片匹配定位和比例坐标定位。

从定位的稳定性与可靠性来看，优先级如下：

* **首选：**控件属性定位（基于控件的属性信息精确定位）；
* **次选：**图片匹配定位（适用于属性不可用但界面稳定的场景）；
* **备用：**比例坐标定位（仅在前两种方式不可用时使用，受分辨率影响较大）。

控件属性定位通过BY选择器对象来实现。下文将详细介绍基于控件属性、图片匹配和比例坐标三种方式的控件定位方法。

**单属性定位控件**

从**hypium** 包中导入BY选择器对象，从**hypium.model** 包中导入匹配模式常量类**MatchPattern**。

```screen
from hypium importBY
fromhypium.model import MatchPattern
```

通过BY对象描述需要查找或者操作的控件对象的属性，例如查找text属性为"蓝牙"的控件。

```screen
# 查找text属性为"控件文本"的控件。
component = driver.find_component(BY.text("蓝牙"))
# 读取控件的的边框位置。
bounds = component.getBounds()
# 直接点击控件。
component = driver.touch(BY.text("蓝牙"))
```

> 注意
>
> 默认情况下，find_component和touch等方法会查找/操作第一个条件匹配的控件，如需操作第n个满足匹配条件的控件，请参考查找所有匹配控件。

当前字符串类型的控件属性支持以下五种**模糊匹配**方式，通过BY选择器方法的第二个可选参数指定，如下表所示：

|序号|匹配方式常量|说明|
|:-|:------------------------|:-------------|
|1|MatchPattern.STARTS_WITH|前缀匹配|
|2|MatchPattern.ENDS_WITH|后缀匹配|
|3|MatchPattern.CONTAINS|包含匹配|
|4|MatchPattern.REGEXP|正则表达式匹配|
|5|MatchPattern.REGEXP_ICASE|正则表达式匹配（忽略大小写）|

```screen
# 点击text属性值前缀为"今天星期"的控件。
driver.touch(BY.text("今天星期", MatchPattern.STARTS_WITH))
```

BY选择器支持的所有属性如下表所示：

|序号|属性名称|属性值类型|对应BY选择器|是否支持模糊匹配|
|:-|:------------|:----|:---------------|:-------|
|1|text|str|BY.text|是|
|2|key|str|BY.key|是|
|3|type|str|BY.type|是|
|4|checkable|bool|BY.checkable|否|
|5|longClickable|bool|BY.longClickable|否|
|6|clickable|bool|BY.clickable|否|
|7|scrollable|bool|BY.scrollable|否|
|8|enabled|bool|BY.enabled|否|
|9|focused|bool|BY.focused|否|
|10|selected|bool|BY.selected|否|
|11|checked|bool|BY.checked|否|
|12|hint|str|BY.hint|是|

**多属性组合定位控件**

BY选择器支持链式调用，允许用户指定多个控件属性进行联合定位。当界面上存在多个控件的部分属性相同而其他属性不同时，可通过组合条件精确匹配目标控件。

```screen
# 点击文本为"蓝牙", 类型为"Button", 并且key为"bluetooth_switch"的按钮。
driver.touch(BY.text("蓝牙").type("Button").key("bluetooth_switch"))

#查找文本为"蓝牙", 类型为"Button", 并且key为"bluetooth_switch"的按钮。
component = driver.find_component(BY.text("蓝牙").type("Button").key("bluetooth_switch"))
```

**控件相对位置+属性组合定位控件**

对于某些自身属性不唯一，无法精确定位的控件，BY选择器支持通过**与其他控件的相对位置关系**来定位控件。支持的相对定位方式如下表所示：

|序号|相对位置定位接口|功能描述|
|:-|:----------|:------------|
|1|BY.isBefore|匹配在指定控件前边的控件。|
|2|BY.isAfter|匹配在指定控件后边的控件。|
|3|BY.within|匹配在指定控件内部的控件。|
|4|BY.inWindow|匹配在指定窗口内部的控件。|

**注意：** 相对位置中的"前后"关系，对应控件树的前序遍历顺序（即深度优先遍历中根-子节点的访问次序），用户可以在 UiViewer 的可视化控件树中直观查看该顺序：控件在列表中从上到下的排列顺序，即为其在相对定位中的从前到后顺序。

相对位置通常和控件的属性结合使用来定位控件，以下图场景为例，界面上存在多个按钮，用户需要点击显示通知图标之后的按钮，定位方式如下：

![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/54/v3/IIBcBfj2TS6Afv8DmseLsg/zh-cn_image_0000002633693102.png?HW-CC-KV=V1&HW-CC-Date=20261030T062830Z&HW-CC-Expire=31536000000&HW-CC-Sign=9D73DE0AED47EC0ACC07357398736026EC028A4B07EE4B53BE0A125AA264E11B "点击放大")

1. 首先选择一个可以通过属性唯一定位的锚点控件。例如**BY.text("显示通知图标")**
2. 然后找到需要操作的目标控件，选择该控件的一个不唯一属性，通常为type属性。例如**BY.type("Button")**
3. 使用相对位置接口来描述锚点控件和目标控件的位置关系，得到完整的控件选择器。例如**BY.type("Button").isAfter(BY.text** **("显示通知图标"))**，注意到这里组合使用了type属性和isAfter相对位置接口。

**示例代码**

```screen
# 查找在text属性为"显示通知图标"的控件之后的type属性为"Button"的控件。
component = driver.find_component(BY.type("Button").isAfter(BY.text("显示通知图标")))
```

```screen
# 查找在text属性为"账号"的控件之前的type属性为"Image"的控件。
component = driver.find_component(BY.type("Image").isBefore(BY.text("账号")))
```

```screen
# 查找在key为"nav_container"内部的类型为"Image"的控件。
component = driver.find_component(BY.type("Image").within(BY.key("nav_container")))
```

```screen
# 查找包名为"com.huawei.hmos.settings"的应用内部的text属性为"蓝牙"的控件。
component = driver.find_component(BY.text("蓝牙").inWindow("com.huawei.hmos.settings"))
```

> 注意
>
> 相对位置中的锚点控件**不能** 再使用相对位置描述，即**BY.isBefore** 方法的参数中不能再出现**BY.isBefore** 或者**BY.isAfter**等相对定位的方式。

**XPath方式查找匹配的控件**

BY.xpath匹配器支持通过XPath语法来查找控件。部分控件没有唯一定位的属性，同时通过相对定位的方式也无法准确定位，推荐使用XPath语法来进行更精确的控件定位。
> 注意
>
> XPath不能和其他属性匹配一起使用，通过XPath查找控件相比单属性和多属性查找控件的效率会有所下降。

在如下场景中，用户需要找到红框标识的图标，然而该图标没有唯一定位的属性，推荐使用XPath语法描述该控件相对其他可定位控件的路径关系来定位该控件。

![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/d/v3/BNSgbTWoRh-h0dpiVdK3RA/zh-cn_image_0000002633693116.png?HW-CC-KV=V1&HW-CC-Date=20261030T062830Z&HW-CC-Expire=31536000000&HW-CC-Sign=34C3614C1AF7462815DE7519F31EC15C61D0E406D100DCA14065A1C381752E99 "点击放大")

该页面上，"可用 WLAN"是一个固定的可唯一定位的文本，用户可以首先通过XPath定位到该文本**//*[@text='可用 WLAN']** ，然后定位到该文本控件所在的List控件**/ancestor::List** ，然后从该List控件开始找到对应的Image控件**/ListItemGroup/ListItem[1]//Text/following::Image**。

**示例代码**

```screen
# 查找上图中红框所示的图标，并点击。
comp = driver.find_component(BY.xpath("//*[@text='可用 WLAN']/ancestor::List/ListItemGroup/ListItem[1]//Text/following::Image"))
comp.click()
```

在支持传入BY选择器的接口均可以使用XPath来定位控件。

```screen
# 查找text属性为WLAN的控件。
driver.find_component(BY.xpath("//*[@text='WLAN']"))
driver.find_all_components(BY.xpath("//*[@text='WLAN']"))
driver.wait_for_component(BY.xpath("//*[@text='WLAN']"))
# 点击text属性为WLAN的控件。
driver.touch(BY.xpath("//*[@text='WLAN']"))
```

**查找所有匹配控件**

默认情况下，**driver.find_component** 接口和其他支持传入BY选择器的接口会查找第一个匹配的控件进行操作。对于需要操作特定次序的匹配控件或所有匹配控件的场景，用户可以使用**driver.find_all_components**接口。

以如下场景为例，界面上存在多个Button，用户需要点击第2个特定的Button或点击所有Button时，可以使用**driver.find_all_components**。

![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/da/v3/sgjv9GMUTICfWmBjcWzadw/zh-cn_image_0000002663932271.png?HW-CC-KV=V1&HW-CC-Date=20261030T062830Z&HW-CC-Expire=31536000000&HW-CC-Sign=B479D3F38B3A26802CE1B82D829D2D517D4E4F92B61E8E9AB4C0C45076FAC7EF "点击放大")

**示例代码**

```screen
# 查找所有type属性为"Button"的控件, 如果有匹配的结果，components为列表，包含多个满足条件的IUiComponent对象。
components = driver.find_all_components(BY.type("Button"))
# 点击所有的控件。
for component in components:
    driver.touch(component)
# 点击第2个控件。
driver.touch(component[1])
```

**图片定位控件**

如果控件没有可用于定位的唯一属性，通过相对位置也无法实现定位，可以通过截取控件的图片，使用**driver.find_image** 查找控件的位置，或使用**driver.touch_image**直接点击控件。

以如下场景为例，若红框中的控件没有可以唯一定位的属性，也无法通过与附近控件的相对位置定位，用户可以尝试使用图片匹配的方式定位控件，定位方式如下：

![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/70/v3/znatExDbQ1-FaGnzK3UZgg/zh-cn_image_0000002663932237.png?HW-CC-KV=V1&HW-CC-Date=20261030T062830Z&HW-CC-Expire=31536000000&HW-CC-Sign=84EAF4587DC88C73D013947189E641BCE997196C00EDAD6992B246904A052130 "点击放大")

1. 截取红框中图片保存到为template.jpeg（文件名根据需要定义）。
2. 调用driver.touch_image，传入template.jpeg图片的路径。

> 注意
>
> 使用图片定位控件需要安装opencv-python包，使用如下命令安装：
>
> python -m pip install opencv-python

**示例代码**

```screen
# 点击屏幕上和模板图片template.jpeg匹配的位置。
driver.touch_image("/path/to/template.jpeg")

# 查找屏幕上和模板图片template.jpeg匹配的位置, bounds为Rect类型，记录了控件上下左右边框的位置。
bounds = driver.find_image("template.jpeg")
print(bounds.top, bounds.left, bounds.bottom, bounds.right)
```

> 注意
>
> 当前仅支持查找匹配度最高的匹配的图片区域，不支持匹配多个目标。

**比例坐标定位控件**

如果图像特征不明显，使用图像匹配的方式也无法准确识别控件位置，用户可以通过比例坐标的方式点击控件。使用坐标的方式操作控件存在以下两个问题：

1. 在屏幕比例或者控件位置发生变化时该方法可能无法操作到预期的控件。

2. 当实际操作界面非预期页面时，点击也会成功，但实际执行效果不符合预期。

因此，在使用该方法时，建议用户在前一步或者后一步操作中通过控件属性定位控件，避免脚本未按照预期方式操作设备，但用例仍然可以执行通过的问题。

以下图场景为例，如果红框中的控件无法通过上述方式定位，用户可以采用比例坐标的方式点击。

![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/0f/v3/JftnGVZnQnCop2KhIVQINw/zh-cn_image_0000002633533174.png?HW-CC-KV=V1&HW-CC-Date=20261030T062830Z&HW-CC-Expire=31536000000&HW-CC-Sign=683BA506350FDD63DCE2448895C2313D191B1955D6306E84A7CE8181B33D34C4 "点击放大")

用户可以通过 UiViewer 工具的控件查看模式获取控件的比例坐标。

![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/45/v3/4UM3fckXQvShRq5bQ_MAEQ/zh-cn_image_0000002663932255.png?HW-CC-KV=V1&HW-CC-Date=20261030T062830Z&HW-CC-Expire=31536000000&HW-CC-Sign=F60CB88C52439677473194D942D16317EA485BB0FA3BBB62E9ED1AB799E252B3 "点击放大")

```screen
# 点击屏幕上(0.52 * 屏幕宽度, 0.98 * 屏幕高度)的位置。
driver.touch((0.52, 0.98))
```

* **窗口查找**

**查找窗口**

```screen
def find_window(filter: WindowFilter) -> UiWindow
```

**接口说明**

根据指定条件查找窗口，返回窗口对象。

**参数说明**

|参数名称|参数描述|
|:-----|:------------------------|
|filter|使用WindowFilter对象指定的窗口查找条件|

**返回值**

如果找到window则返回UiWindow对象，否则返回None。

**使用示例**

```screen
# 查找标题为日历的窗口。
window = driver.find_window(WindowFilter().title("日历"))
# 查找包名为com.huawei.hmos.calendar，并且处于活动状态的窗口。
window = driver.find_window(WindowFilter().bundle_name("com.huawei.hmos.calendar").actived(True))
# 查找处于活动状态的窗口。
window = driver.find_window(WindowFilter().actived(True))
# 查找聚焦状态的窗口。
window = driver.find_window(WindowFilter().focused(True))
```

* **界面操作**

**Ⅰ.触摸屏**

**点击**

```screen
def touch(target: Union[ISelector, IUiComponent, tuple], mode: str = UiParam.NORMAL, scroll_target: Union[ISelector, IUiComponent] = None, wait_time: float = 0.1)
```

**接口说明**

根据选定的控件或坐标位置执行点击操作。

**参数说明**

|序号|参数名称|参数描述|
|:-|:------------|:-----------------------------------------------------------------------------------------|
|1|target|需要点击的目标，支持三种类型： 1. BY控件选择器 2. 控件对象 2. 屏幕坐标（通过tuple类型指定，例如(100, 200)， 其中100为x轴坐标，200为y轴坐标。）|
|2|mode|点击模式，支持三种模式： UiParam.NORMAL 点击 UiParam.LONG 长按（长按后放开） UiParam.DOUBLE 双击。|
|3|scroll_target|指定可滚动的控件，在该控件中滚动搜索指定的目标控件target，仅在target为BY选择器时有效。|
|4|wait_time|点击后等待响应的时间，单位为秒，默认0.1秒。|

**使用示例**

```screen
# 点击文本为"hello"的控件。
driver.touch(BY.text("hello"))
# 点击(100, 200)的位置。
driver.touch((100, 200))
# 点击比例坐标为(0.8, 0.9)的位置。
driver.touch((0.8, 0.9))
# 双击确认按钮(控件文本为"确认", 类型为"Button")。
driver.touch(BY.text("确认").type("Button"), mode=UiParam.DOUBLE)
# 在类型为Scroll的控件上滑动查找文本为"退出"的控件并点击。
driver.touch(BY.text("退出"), scroll_target=BY.type("Scroll"))
# 长按比例坐标为(0.8, 0.9)的位置。
driver.touch((0.8, 0.9), mode="long")
```

**长按**

```screen
def long_click(self, target: Union[ISelector, IUiComponent, tuple], press_time: float = 2, offset=None):
```

**接口说明**

执行长按操作。

**注意：**该接口仅DevEco Testing Hypium 6.0.5.200以及更新的版本支持。

**参数说明**

|序号|参数名称|参数描述|
|:-|:---------|:--------------------------------------------------------------------------------------------------|
|1|target|需要点击的目标，可以为控件查找条件，控件对象或者屏幕坐标(通过tuple类型指定，例如(100, 200)， 其中100为x轴坐标，200为y轴坐标。）|
|2|press_time|长按时间，单位为秒。|
|3|offset|点击坐标在目标控件区域的偏移值。不设置时该参数时默认为(0.5, 0.5), 表示控件中心。支持设置范围是0到1，如(0.1, 0.1)表示点击目标左上角为坐标原点x方向10%，y方向10%的位置。|

**使用示例**

```screen
#长按文本为"按钮"的控件5秒
driver.long_click(BY.text("按钮"), press_time=5)
#长按(100, 200)的位置5秒
driver.long_click((100, 200), press_time=5)
#长按文本为"设置"的控件左上角(偏移0, 0)
driver.long_click(BY.text("设置"), offset=(0, 0))
```

**多指点击**

```screen
def multi_finger_touch(points: List[tuple], duration: float = 0.1, area: Rect = None)
```

**接口说明**

执行多指点击操作。

**参数说明**

|序号|参数名称|参数描述|
|:-|:-------|:----------------------------------------------------------|
|1|points|需要点击的坐标位置列表，每个坐标对应一个手指，例如[(0.1, 0.2), (0.3, 0.4)]，最多支持4指点击。|
|2|duration|按下/抬起的时间，可实现多指长按操作，单位秒。|
|3|area|点击操作的区域，当起始结束坐标为(0.1, 0.2)等相对比例坐标时生效，默认为操作区域为全屏。|

**使用示例**

```screen
# 执行多指点击操作, 同时点击屏幕(0.1, 0.2), (0.3, 0.4)的位置。
driver.multi_finger_touch([(0.1, 0.2), (0.3, 0.4)])
# 执行多指点击操作, 设置点击按下时间为1秒。
driver.multi_finger_touch([(0.1, 0.2), (0.3, 0.4)], duration=2)
# 查找Image类型控件。
comp = driver.find_component(BY.type("Image"))
# 在指定的控件区域内执行多指点击(点击坐标为控件区域内的比例坐标)。
driver.multi_finger_touch([(0.5, 0.5), (0.6, 0.6)], area=comp.getBounds())
```

**滑动**

**执行指定方向的滑动操作**

```screen
def swipe(direction: str, distance: int = 60, area: Union[ISelector, IUiComponent] = None, side: str = None, start_point: tuple = None, swipe_time: float = 0.3)
```

**接口说明**

在屏幕上或者指定区域中执行朝向指定方向的滑动操作。该接口用于无需指定精确起始和结束坐标的滑动操作场景。

**参数说明**

|序号|参数名称|参数描述|
|:-|:----------|:----------------------------------------------------------------------------------------------------------|
|1|direction|滑动方向，目前支持： UiParam.LEFT 左滑 UiParam.RIGHT 右滑 UiParam.UP 上滑 UiParam.DOWN 下滑|
|2|distance|相对滑动区域总长度的滑动距离，范围为1-100，表示滑动长度为滑动区域总长度的1%到100%， 默认为60。|
|3|area|通过控件指定的滑动区域，默认为None表示滑动区域为整个屏幕。|
|4|side|滑动位置， 指定滑动区域内部（屏幕内部）执行操作的大概位置，支持： UiParam.LEFT 靠左区域 UiParam.RIGHT 靠右区域 UiParam.TOP 靠上区域 UiParam.BOTTOM 靠下区域|
|5|start_point|滑动起始点，默认为None，表示在区域中间位置执行滑动操作，可以传入滑动起始点坐标，支持使用比例坐标，例如(0.5, 0.5)。 当同时传入side和start_point的时候，仅start_point生效。|
|6|swipe_time|滑动时间，单位为秒， 默认0.3秒。|

**使用示例**

```screen
# 在屏幕上向上滑动, 距离40。
driver.swipe(UiParam.UP, distance=40)
# 在屏幕上向右滑动, 滑动时间为0.1秒。
driver.swipe(UiParam.RIGHT, swipe_time=0.1)
# 在屏幕起始点为比例坐标为(0.8, 0.8)的位置向上滑动，距离30。
driver.swipe(UiParam.UP, 30, start_point=(0.8, 0.8))
# 在屏幕左边区域向下滑动， 距离30。
driver.swipe(UiParam.DOWN, 30, side=UiParam.LEFT)
# 在屏幕右侧区域向上滑动，距离30。
driver.swipe(UiParam.UP, side=UiParam.RIGHT)
# 在类型为Scroll的控件中向上滑动。
driver.swipe(UiParam.UP, area=BY.type("Scroll"))
```

**执行指定起始结束位置的精确滑动操作**

```screen
def slide(start: Union[ISelector, tuple], end: Union[ISelector, tuple], area: Union[ISelector, IUiComponent] = None, slide_time: float = 0.3)
```

**接口说明**

根据指定的起始和结束位置执行滑动操作，起始和结束的位置可以为控件或屏幕坐标。该接口用于执行精准的滑动操作。

**参数说明**

|序号|参数名称|参数描述|
|:-|:---------|:----------------------------------------------------------------------------------------|
|1|start|滑动起始位置，支持三种类型： 1. BY控件选择器 2. 控件对象 3. 屏幕坐标（通过tuple类型指定，例如(100, 200)， 其中100为x轴坐标，200为y轴坐标。）|
|2|end|滑动结束位置，支持三种类型： 1. BY控件选择器 2. 控件对象 3. 屏幕坐标（通过tuple类型指定，例如(100, 200)， 其中100为x轴坐标，200为y轴坐标。）|
|3|area|滑动操作区域。指定区域后，当start或end参数为坐标类型时，其坐标被视为相对于该指定的区域的相对位置坐标。|
|4|slide_time|滑动时间，单位为秒，默认为0.3秒。|

**使用示例**

```screen
# 从类型为Slider的控件滑动到文本为最大的控件
driver.slide(BY.type("Slider"), BY.text("最大"))
# 从坐标100, 200滑动到300，400
driver.slide((100, 200), (300, 400))
# 从坐标100, 200滑动到300，400, 滑动时间为3秒
driver.slide((100, 200), (300, 400), slide_time=3)
#在类型为Slider的控件上从(0, 0)滑动到(100, 0)
driver.slide((0, 0), (100, 0), area = BY.type("Slider"))
```

**拖拽**

```screen
def drag(start: Union[ISelector, tuple, IUiComponent], end: Union[ISelector, tuple, IUiComponent], area: Union[ISelector, IUiComponent] = None, press_time: float = 1, drag_time: float = 1)
```

**接口说明**

根据指定的起始和结束位置执行拖拽操作，起始和结束的位置可以为控件或者屏幕坐标。

**参数说明**

|序号|参数名称|参数描述|
|:-|:---------|:-------------------------------------------------------------------------------------------------------------------------|
|1|start|拖拽起始位置，支持三种类型： 1. BY控件选择器 2. 控件对象 3. 屏幕坐标（通过tuple类型指定的坐标，例如(100, 200)， 其中100为x轴坐标，200为y轴坐标；或相对于区域长度和宽度的比例坐标，例如(0.1, 0.2)。)|
|2|end|拖拽结束位置，支持三种类型： 1. BY控件选择器 2. 控件对象 3. 屏幕坐标（通过tuple类型指定的坐标，例如(100, 200)， 其中100为x轴坐标，200为y轴坐标；或相对于区域长度和宽度的比例坐标，例如(0.1, 0.2)。)|
|3|area|拖拽操作区域，指定区域后，当start或end参数为坐标类型时，其坐标被视为相对于该指定的区域的相对位置坐标。|
|4|press_time|拖拽操作开始时，长按的时间，单位为秒，默认为1.5秒。 **注意：** 该参数为可选参数，仅DevEco Testing Hypium 6.0.5.200及更新的版本，且配套测试设备的API level >= 20时支持。|
|5|drag_time|拖动的时间，单位秒， 默认为1秒（拖拽操作总时间 = press_time + drag_time）。|

**使用示例**

```screen
#拖拽文本为"文件.txt"的控件到文本为"上传文件"的控件。
driver.drag(BY.text("文件.txt"), BY.text("上传文件"))
#拖拽id为"start_bar"的控件到坐标(100, 200)的位置, 拖拽时间为2秒。
driver.drag(BY.key("start_bar"), (100, 200), drag_time=2)
#在id为"Canvas"的控件上执行拖拽操作，从"Canvas"控件中(0.1, 0.5)的位置拖拽到(0.9, 0.5)位置。
# 假如"Canvas"控件左上角坐标(100, 100), 宽度为200，高度为50，此操作等价于
# driver.drag((100 + 0.1 * 200, 100 + 0.5 * 50), (100 + 0.9 * 200, 100 + 0.5 * 50))。
driver.drag((0.1, 0.5), (0.9, 0.5), area=BY.id("Canvas"))
#在滑动条上执行拖拽操作, 以滑动条组件左上角为原点, 从滑动条区域中的(10, 10)拖拽到(10, 200)。
# 假设滑动条左上角坐标为(500, 500), 此操作等价于driver.drag((500 + 10, 500 + 10), (500 + 10, 500 + 200))。
driver.drag((10, 10), (10, 200), area=BY.type("Slider"))
```

**捏合缩小**

```screen
def pinch_in(area: Union[ISelector, IUiComponent, Rect], scale: float = 0.4, direction: str = "diagonal", **kwargs)
```

**接口说明**

在指定控件上执行双指捏合缩小操作。

**参数说明**

|序号|参数名称|参数描述|
|:-|:--------|:------------------------------------------------------------------------------------------------------------------------------|
|1|area|手势操作执行的区域，支持三种类型： 1. BY控件选择器 2. 控件对象 3. 屏幕区域，通过Rect类型指定，例如 Rect(left, right, top, bottom)，其中 left，right，top，bottom 为区域左右上下的坐标值。|
|2|scale|缩放的比例，范围(0, 1)，值越小表示缩放操作距离越长，缩小的越多。|
|3|direction|双指缩放时缩放操作方向，当前支持： "diagonal" 对角线滑动 "horizontal" 水平滑动|
|4|kwargs|其他可选滑动配置参数： dead_zone_ratio 缩放操作时控件靠近边界不可操作的区域占控件长度/宽度的比例，默认为0.2，调节范围为(0, 0.5)。|

**使用示例**

```screen
# 在类型为Image的控件上进行双指捏合缩小操作。
driver.pinch_in(BY.type("Image"))
# 在类型为Image的控件上进行双指捏合缩小操作, 设置水平方向捏合。
driver.pinch_in(BY.type("Image"), direction="horizontal")
```

**双指放大**

```screen
def pinch_out(area: Union[ISelector, IUiComponent, Rect], scale: float = 1.6, direction: str = "diagonal", **kwargs)
```

**接口说明**

在指定控件上执行双指放大操作。

**参数说明**

|序号|参数名称|参数描述|
|:-|:--------|:-----------------------------------------------------------------------------------------------------------------------------|
|1|area|手势操作执行的区域，支持三种类型： 1. BY控件选择器 2. 控件对象 2. 屏幕区域，通过Rect类型指定，例如 Rect(left, right，top, bottom)，其中 left，right，top，bottom 为区域左右上下的坐标值。|
|2|scale|缩放的比例，范围 (1, 2)，值越大表示缩放操作滑动的距离越长。|
|3|direction|双指缩放时缩放操作方向，当前支持： "diagonal" 对角线滑动 "horizontal" 水平滑动|
|4|kwargs|其他可选滑动配置参数： dead_zone_ratio 缩放操作时控件靠近边界不可操作的区域占控件长度/宽度的比例，默认为0.2，调节范围为(0, 0.5)。|

**使用示例**

```screen
# 在类型为Image的控件上进行双指放大操作。
driver.pinch_out(BY.type("Image"))
# 在类型为Image的控件上进行双指捏合缩小操作, 设置水平方向捏合。
driver.pinch_out(BY.type("Image"), direction="horizontal")
```

**双指滑动**

```screen
def two_finger_swipe(start1: tuple, end1: tuple, start2: tuple, end2: tuple, duration: float = 0.5, area: Rect = None)
```

**接口说明**

执行双指滑动操作。

**参数说明**

|序号|参数名称|参数描述|
|:-|:-------|:-----------------------------------------------|
|1|start1|手指1起始坐标|
|2|end1|手指1结束坐标|
|3|start2|手指2起始坐标|
|4|end2|手指2结束坐标|
|5|duration|滑动操作持续时间，单位为秒，默认0.5秒。|
|6|area|滑动操作的区域，当起始结束坐标为(0.1, 0.2)等相对比例坐标时生效，默认为操作区域为全屏。|

**使用示例**

```screen
# 执行双指滑动操作, 手指1从(0.4, 0.4)滑动到(0.2, 0.2), 手指2从(0.6, 0.6)滑动到(0.8, 0.8)。
driver.two_finger_swipe((0.4, 0.4), (0.2, 0.2), (0.6, 0.6), (0.8, 0.8))
# 执行双指滑动操作, 手指1从(0.4, 0.4)滑动到(0.2, 0.2), 手指2从(0.6, 0.6)滑动到(0.8, 0.8), 持续时间3秒。
driver.two_finger_swipe((0.4, 0.4), (0.2, 0.2), (0.6, 0.6), (0.8, 0.8), duration=3)
# 查找Image类型控件。
comp = driver.find_component(BY.type("Image"))
# 在指定的控件区域内执行双指滑动(滑动起始/停止坐标为控件区域内的比例坐标)。
driver.two_finger_swipe((0.4, 0.4), (0.1, 0.1), (0.6, 0.6), (0.9, 0.9), area=comp.getBounds())
```

**自定路径滑动手势（单指）**

```screen
def inject_gesture(gesture: Gesture, speed: int = 2000)
```

**接口说明**

执行自定义滑动手势操作。

**参数说明**

|序列|参数名称|参数描述|
|:-|:------|:--------------------------------------------------------------|
|1|gesture|描述手势操作的Gesture对象。|
|2|speed|默认操作速度，单位像素/秒，默认值为2000像素/秒，当生成Gesture对象的步骤中未传入操作时间时默认使用该速度进行操作。|

**使用示例**

```screen
from hypium.uidriver import Gesture

# 创建一个gesture对象。
gesture = Gesture()
# 获取控件计算器的位置。
pos = driver.findComponent(BY.text("计算器")).getBoundsCenter()
# 获取屏幕尺寸。
size = driver.getDisplaySize()
# 起始位置, 长按2秒。
gesture.start(pos.to_tuple(), 2)
# 移动到屏幕边缘。
gesture.move_to(Point(size.X - 20, int(size.Y / 2)).to_tuple())
# 停留2秒。
gesture.pause(2)
# 移动到(360, 500)的位置。
gesture.move_to(Point(360, 500).to_tuple())
# 停留2秒结束。
gesture.pause(2)
# 执行gesture对象描述的操作。
driver.inject_gesture(gesture)
```

**自定路径滑动手势(多指)**

```screen
def inject_multi_finger_gesture(gestures: List[Gesture], speed: int = 6000)
```

**接口说明**

注入多指手势操作。

**参数说明**

|序号|参数名称|参数描述|
|:-|:-------|:-------------------------------------------------------------------------------------------------|
|1|gestures|表示单指手势操作的Gesture对象列表，每个Gesture对象描述一个手指的操作轨迹，最多4指。 注意如果各个手势持续时间不同，时间短的手势操作会保持在结束位置，等待所有手势完成后抬起对应手指。|
|2|speed|Gesture对象的步骤未设置时间时，使用该速度计算时间，单位为像素/秒，默认为6000像素/秒。|

**使用示例**

```screen
from hypium.uidriver import Gesture
# 创建手指1的手势, 从(0.4, 0.4)的位置移动到(0.2, 0.2)的位置。
gesture1 = Gesture().start((0.4, 0.4)).move_to((0.2, 0.2), interval=1)
# 创建手指2的手势, 从(0.6, 0.6)的位置移动到(0.8, 0.8)的位置。
gesture2 = Gesture().start((0.6, 0.6)).move_to((0.8, 0.8), interval=1)
# 注入多指操作。
driver.inject_multi_finger_gesture((gesture1, gesture2))
```

**Ⅱ. 键盘鼠标**

**鼠标点击**

```screen
def mouse_click(pos: Union[tuple, IUiComponent, ISelector], button_id: MouseButton = MouseButton.MOUSE_BUTTON_LEFT, key1: Union[KeyCode, int] = None, key2: Union[KeyCode, int] = None)
```

**接口说明**

执行鼠标点击操作, 支持键鼠组合操作。

**参数说明**

|序号|参数名称|参数描述|
|:-|:--------|:---------------------------------------------------------------------------------------|
|1|pos|点击的位置，支持三种类型： 1. BY控件选择器 2. 控件对象 3. 屏幕坐标（通过tuple类型指定，例如(100, 200)， 其中100为x轴坐标，200为y轴坐标。)|
|2|button_id|需要点击的鼠标按键。|
|3|key1|需要组合按下的第一个键盘按键。|
|4|key2|需要组合按下的第二个键盘按键。|

**使用示例**

```screen
# 使用鼠标左键点击(100, 200)的位置。
driver.mouse_click((100, 200), MouseButton.MOUSE_BUTTON_LEFT)
# 使用鼠标右键点击文本为"确认"的控件。
driver.mouse_click(BY.text("确认"), MouseButton.MOUSE_BUTTON_RIGHT)
# 使用鼠标右键点击比例坐标(0.8, 0.5)的位置。
driver.mouse_click((0.8, 0.5), MouseButton.MOUSE_BUTTON_RIGHT)
```

**鼠标拖拽**

```screen
def mouse_drag(start: Union[tuple, IUiComponent, ISelector], end: Union[tuple, IUiComponent, ISelector], speed: int = 3000)
```

**接口说明**

执行鼠标拖拽操作（即按住鼠标左键并移动鼠标）。

**参数说明**

|序号|参数名称|参数描述|
|:-|:----|:--------------------------------------------------------------------------------------|
|1|start|起始位置，支持三种类型： 1. BY控件选择器 2. 控件对象 3. 屏幕坐标（通过tuple类型指定，例如(100, 200)， 其中100为x轴坐标，200为y轴坐标。)|
|2|end|结束位置，支持三种类型： 1. BY控件选择器 2. 控件对象 3. 屏幕坐标（通过tuple类型指定，例如(100, 200)， 其中100为x轴坐标，200为y轴坐标。)|
|3|speed|鼠标移动速度，像素/秒，默认3000像素/秒。|

**使用示例**

```screen
# 鼠标从控件1拖拽到控件2。
driver.mouse_drag(BY.text("控件1"), BY.text("控件2"))
```

**鼠标移动**

```screen
def mouse_move(start: Union[tuple, IUiComponent, ISelector], end: Union[tuple, IUiComponent, ISelector], speed: int = 3000)
```

**接口说明**

将鼠标指针从指定起始位置移动到结束位置，模拟移动轨迹和移动速度。

**参数说明**

|序号|参数名称|参数描述|
|:-|:----|:--------------------------------------------------------------------------------------|
|1|start|起始位置，支持三种类型： 1. BY控件选择器 2. 控件对象 3. 屏幕坐标（通过tuple类型指定，例如(100, 200)， 其中100为x轴坐标，200为y轴坐标。）|
|2|end|结束位置，支持三种类型： 1. BY控件选择器 2. 控件对象 3. 屏幕坐标（通过tuple类型指定，例如(100, 200)， 其中100为x轴坐标，200为y轴坐标。）|
|3|speed|鼠标移动速度，像素/秒，默认3000像素/秒。|

**使用示例**

```screen
# 鼠标从控件1移动到控件2。
driver.mouse_move(BY.text("控件1"), BY.text("控件2"))
```

**按键**

```screen
def press_key(key_code: Union[KeyCode, int], key_code2: Union[KeyCode, int] = None, mode="normal")
```

**接口说明**

执行按键操作（注意不推荐使用该接口实现组合按键模拟，模拟组合按键键请使用press_combination_key）。

**参数说明**

|序号|参数名称|参数描述|
|:-|:--------|:-----------------------------------------------------------------------------|
|1|key_code|需要按下的按键编码。|
|2|key_code2|需要按下的按键编码。|
|3|mode|按键模式，仅在进行单个按键时支持，当前支持以下模式： UiParam.NORMAL 单击 UiParam.LONG 长按 UiParam.DOUBLE 双击|

**使用示例**

```screen
# 按下电源键。
driver.press_key(KeyCode.POWER)
# 长按电源键。
driver.press_key(KeyCode.POWER, mode=UiParam.LONG)
# 按下音量下键。
driver.press_key(KeyCode.VOLUME_DOWN)
```

**按组合键**

```screen
def press_combination_key(key1: Union[KeyCode, int], key2: Union[KeyCode, int], key3: Union[KeyCode, int] = None)
```

**接口说明**

执行组合键操作，支持2键或3键组合。

**参数说明**

|序号|参数名称|参数描述|
|:-|:---|:-------|
|1|key1|组合键第一个按键|
|2|key2|组合键第二个按键|
|3|key3|组合键第三个按键|

**使用示例**

```screen
# 按下音量下键和电源键的组合键
driver.press_combination_key(KeyCode.VOLUME_DOWN, KeyCode.POWER)
#同时按下ctrl, shift和F键
driver.press_combination_key(KeyCode.CTRL_LEFT, KeyCode.SHIFT_LEFT, KeyCode.F)
```

* **hdc/shell命令执行**

**hdc命令执行**

```screen
def hdc(cmd, timeout: float = 60) -> str
```

**接口说明**

执行hdc命令。

**参数说明**

|序号|参数名称|参数描述|
|:-|:------|:--------------|
|1|cmd|需要执行的hdc命令。|
|2|timeout|超时时间，单位秒，默认60秒。|

**返回值**

命令执行后的回显内容。

**使用示例**

```screen
# 执行hdc命令list targets。
echo = driver.hdc("list targets")
# 执行hdc命令hilog, 设置30秒超时。
echo = driver.hdc("hilog", timeout = 30)
```

**设备侧shell命令执行**

```screen
def shell(cmd: str, timeout: float = 60) -> str
```

**接口说明**

在设备端shell中执行命令。

**参数说明**

|序号|参数名称|参数描述|
|:-|:------|:--------------|
|1|cmd|需要执行的shell命令。|
|2|timeout|超时时间，单位秒，默认60秒。|

**返回值**

命令执行后的回显内容。

**使用示例**

```screen
# 在设备shell中执行命令ls -l。
echo = driver.shell("ls -l")
# 在设备shell中执行命令top, 设置10秒超时时间。
echo = driver.shell("top", timeout=10)
```

**PC侧shell命令执行**

```screen
def shell(cmd: Union[str, list], timeout: float = 300) -> str
```

**接口说明**

在PC端执行shell命令。

**参数说明**

|序号|参数名称|参数描述|
|:-|:------|:---------------|
|1|cmd|需要执行的命令内容。|
|2|timeout|超时时间，单位秒，默认300秒。|

**使用示例**

```screen
# 在PC端执行dir命令。
echo = host.shell("dir")
# 在PC端执行netstat命令读取回显结果, 设置超时时间为10秒。
echo = host.shell("netstat", timeout=10)
```

* **应用预置操作**

**安装应用**

```screen
def install_app(package_path: str, options: str = "", **kwargs)
```

**接口说明**

安装指定应用安装包。

**参数说明**

|序号|参数名称|参数描述|
|:-|:-----------|:--------------------|
|1|package_path|PC端保存的安装包路径。|
|2|options|传递给bm install命令的额外参数。|

**使用示例**

```screen
# 安装路径为test.hap的安装包到手机。
driver.install_app(r"test.hap")
# 替换安装路径为test.hap的安装包到手机(增加-r参数指定替换安装)。
driver.install_app(r"test.hap", "-r")
```

**卸载应用**

```screen
def uninstall_app(package_name: str, **kwargs)
```

**接口说明**

卸载指定包名应用。

**参数说明**

|参数名称|参数描述|
|:-----------|:--------|
|package_name|需要卸载的应用包名|

**使用示例**

```screen
# 卸载包名为com.test.myapp的应用。
driver.uninstall_app("com.test.myapp")
```

**清除应用缓存数据**

```screen
def clear_app_data(package_name: str)
```

**接口说明**

清除应用的缓存数据。

**参数说明**

|参数名称|参数描述|
|:-----------|:-----------------------|
|package_name|需要清除缓存的应用包名（bundle name）|

**使用示例**

```screen
# 清除包名为com.test.myapp的应用的缓存数据。
driver.clear_app_data("com.test.myapp")
```

**启动应用**

```screen
def start_app(package_name: str, page_name: str = None, params: str = "", wait_time: float = 1)
```

**接口说明**

根据包名启动指定的应用。

**参数说明**

|序号|参数名称|参数描述|
|:-|:-----------|:----------------------------|
|1|package_name|应用程序包名(bundle name)。|
|2|page_name|应用内页面名称(ability name)。|
|3|params|其他传递给aa命令的参数。|
|4|wait_time|发送启动指令后，等待应用启动的时间，单位为秒，默认为1秒。|

**使用示例**

```screen
# 启动浏览器。
driver.start_app("com.huawei.hmos.browser", "MainAbility")
```

**停止应用**

```screen
def stop_app(package_name: str, wait_time: float = 0.5)
```

**接口说明**

停止指定包名的应用。

**参数说明**

|序号|参数名称|参数描述|
|:-|:-----------|:-----------------------|
|1|package_name|应用程序包名。|
|2|wait_time|停止应用后等待的时间，单位为秒，默认为0.5秒。|

**使用示例**

```screen
# 停止包名为com.huawei.hmos.settings的应用。
driver.stop_app("com.huawei.hmos.settings")
```

* **文件拉取/推送**

**拉取文件**

```screen
def pull_file(device_path: str, local_path: str = None, timeout: int = 60)
```

**接口说明**

从设备端的传输文件到PC端。

**参数说明**

|序号|参数名称|参数描述|
|:-|:----------|:------------------|
|1|device_path|设备侧保存文件的路径。|
|2|local_path|PC侧保存文件的路径。|
|3|timeout|拉取文件超时时间，单位秒，默认60秒。|

**使用示例**

```screen
# 从设备中拉取文件"/data/local/tmp/test.log"保存到PC端的test.log。
driver.pull_file("/data/local/tmp/test.log", "test.log")
```

**推送文件**

```screen
def push_file(local_path: str, device_path: str, timeout: int = 60)
```

**接口说明**

从PC端传输文件到设备端。

**参数说明**

|序号|参数名称|参数描述|
|:-|:----------|:------------------|
|1|local_path|PC侧文件的路径。|
|2|device_path|设备侧文件的路径。|
|3|timeout|推送文件超时时间，单位秒，默认60秒。|

**使用示例**

```screen
# 从PC端推送文件test.hap保存到设备端的"/data/local/tmp/test.hap"。
driver.push_file("test.hap", "/data/local/tmp/test.hap")
```

**查询文件是否存在**

```screen
def has_file(file_path: str) -> bool
```

**接口说明**

查询设备中是否有存在路径为file_path的文件。

**参数说明**

|参数名称|参数描述|
|:--------|:------------|
|file_path|需要检查的设备端文件路径。|

**使用示例**

```screen
# 查询设备端是否存在文件/data/local/tmp/test_file.txt。
driver.has_file("/data/local/tmp/test_file.txt")
```

* **文本输入/清除**

**输入文本**

```screen
def input_text(component: Union[ISelector, IUiComponent, tuple], text: str, mode: InputTextMode = None):
```

**接口说明**

向指定控件中输入文本内容。

**参数说明**

|序号|参数名称|参数描述|
|:-|:--------|:--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|1|component|需要输入文本的控件，支持三种类型： 1. BY控件选择器 2. 控件对象 3. 屏幕坐标（通过tuple类型指定，例如(100, 200)， 其中100为x轴坐标，200为y轴坐标。）|
|2|text|需要输入的文本。|
|3.|mode|输入模式配置，默认模式操作如下： 1. 默认清空指定的控件中的文本后再执行输入。 2. 英文字符长度<200时，逐个输入，超过200时，通过剪切板粘贴一次输入。 3. 中文文本通过剪切板粘贴一次输入。 通过该参数可以配置： 1. 追加输入：InputTextMode().addition(True)。 2. 输入英文时，不考虑文本长度直接使用剪切板快速输入：InputTextMode().paste(True)。 **注意**：该参数为可选参数，仅DevEco Testing Hypium 6.0.5.200以及更新的版本，且配套测试设备的API level >= 20支持。|

使用示例

```screen
from hypium import BY
from hypium.model import InputTextMode
#在类型为"TextInput"的控件中输入文本"hello world"。
driver.input_text(BY.type("TextInput"), "hello world")
#在类型为"TextInput"的控件中使用剪切板一次性输入文本"hello world"。
driver.input_text(BY.type("TextInput"), "hello world", mode=InputTextMode().paste(True))
#在类型为"TextInput"的控件中使用剪切板一次性并追加输入文本"hello world"。
driver.input_text(BY.type("TextInput"), "hello world", mode=InputTextMode().paste(True).addition(True))
```

**清除文本**

```screen
def clear_text(component: [ISelector, IUiComponent])
```

**接口说明**

清空指定控件中的文本内容。

**参数说明**

|参数名称|参数描述|
|:--------|:--------|
|component|需要清除文本的控件|

使用示例

```screen
# 清除类型为"InputText"的控件中的内容。
driver.clear_text(BY.type("InputText"))
```

* **断言**

**Ⅰ. 常规断言**

**检查是否相等**

```screen
def check_equal(value: Any, expect: Any = True, fail_msg: str = None, expect_equal=True)
```

**接口说明**

检查实际值和期望值相等，在不一致时抛出异常，并打印fail_msg。

**参数说明**

|序号|参数名称|参数描述|
|:-|:-------|:------------------------------------------|
|1|value|实际值，如果为list或者tuple，将取其中每个值同expect中的每个值进行比较。|
|2|expect|期望值， 如果为list或者tuple，将取其中每个值同value中的每个值进行比较。|
|3|fail_msg|断言失败时打印的提示信息。|

**使用示例**

```screen
# 检查a等于b。
host.check_equal(a, b, "a != b")
```

**检查是否超过预期值**

```screen
def check_greater(value: Any, expect: Any, fail_msg: str = None)
```

**接口说明**

检查value是否大于expect，不满足时抛出异常，并在日志中打印fail_msg。

**参数说明**

|序号|参数名称|参数描述|
|:-|:-------|:-----------|
|1|value|实际值|
|2|expect|期望值|
|3|fail_msg|断言失败时打印的提示信息|

**使用示例**

```screen
# 检查a大于b
host.check_greater(a, b)
```

**Ⅱ. 控件断言**

**检查控件是否存在**

```screen
def check_component_exist(component: ISelector, expect_exist: bool = True, wait_time: int = 0, scroll_target: Union[ISelector, IUiComponent] = None)
```

**接口说明**

检查指定控件在当前界面是否存在。

**参数说明**

|序号|参数名称|参数描述|
|:-|:------------|:------------------------------------|
|1|component|待检查的UI控件，使用BY选择器指定。|
|2|expect_exist|是否期望控件存在，True表示期望控件存在，False表示期望控件不存在。|
|3|wait_time|检查过程中等待控件出现的时间，单位秒，默认为0。|
|4|scroll_target|需要上下滚动检查目标控件时滑动的控件，默认为None，表示不进行滑动查找。|

**使用示例**

```screen
# 检查类型为Button的控件存在。
driver.check_component_exist(BY.type("Button"))
# 检查类型为Button的控件存在，如果不存在等待最多5秒。
driver.check_component_exist(BY.type("Button"), wait_time=5)
# 在类型为Scroll的控件上滚动检查文本为"hello"的控件存在。
driver.check_component_exist(BY.text("hello"), scroll_target=BY.type("Scroll"))
# 检查文本为确认的控件不存在。
driver.check_component_exist(BY.text("确认"), expect_exist=False)
```

**检查控件属性**

```screen
def check_component(component: Union[ISelector, IUiComponent], expected_equal: bool = True, **kwargs)
```

**接口说明**

检查当前界面上指定控件的属性是否符合预期。

**参数说明**

|序号|参数名称|参数描述|
|:-|:-------------|:------------------------------------------------------------------------------------------------------------|
|1|component|需要检查的控件，支持BY选择器或控件对象。|
|2|expected_equal|预期值和实际值是否相等，True表示预期相等，False表示预期不相等。|
|3|kwargs|指定预期的控件属性值，目前支持： "id"，"text"，"key"，"type"，"enabled"，"focused"，"clickable"，"scrollable" "checked"，"checkable"。|

**使用示例**

```screen
# 检查id为xxx的控件的checked属性为True。
driver.check_component(BY.key("xxx"), checked=True)
# 检查id为check_button的按钮enabled属性为True。
driver.check_component(BY.key("checked_button"), enabled=True)
# 检查id为container的控件文本内容为"正在检查"。
driver.check_component(BY.key("container"), text="正在检查")
# 检查id为container的控件文本内容不为空。
driver.check_component(BY.key("container"), text="", expect_equal=False)
```

**检查图片是否存在**

```screen
def check_image_exist(image_path_pc: str, expect_exist: bool = True, similarity: float = 0.95, timeout: int = 3, mode="template", **kwargs)
```

**接口说明**

使用图片模板匹配算法检测当前屏幕截图中是否有指定图片，需要保证模板图片的分辨率和屏幕截图中目标图像的分辨率一致。

**参数说明**

|序号|参数名称|参数描述|
|:-|:------------|:------------------------------------------------------------------------------|
|1|image_path_pc|待检查的图片路径（图片保存在PC端）。|
|2|expect_exist|是否期望图片在设备屏幕上存在，True表示期望控件存在，False表示期望控件不存在。|
|3|similarity|图像匹配算法比较图片时使用的相似度，范围[0, 1]。|
|4|timeout|检查的总时间，每秒会进行获取一次屏幕截图检查指定图片是否存在，通过timeout可指定检查的次数。|
|5|mode|图片匹配模式，支持"template"和"sift"，图片分辨率/旋转变化对sift模式影响相对较小，但sift模式难以处理缺少较复杂图案的纯色，无线条图片。|
|6|kwargs|其他配置参数： min_match_point： 最少匹配特征点数，值越大匹配越严格，默认为16，仅sift模式有效。|

**使用示例**

```screen
# 检查图片存在。
driver.check_image_exist("test.jpeg")
# 检查图片不存在。
driver.check_image_exist("test.jpeg", expect_exist=False)
# 检查图片存在, 图片相似度要求95%, 重复检查时间5秒。
driver.check_image_exist("test.jpeg", timeout=5, similarity=0.95)
# 检查图片不存在, 重复检查时间5秒。
driver.check_image_exist("test.jpeg", timeout=5, expect_exist=False)
# 使用sift算法检查图片存在, 设置最少匹配特征点数量为16。
driver.check_image_exist("test.jpeg", mode="sift", min_match_point=16)
```

**Ⅲ. 窗口断言**

**检查窗口**

```screen
def check_window(window: WindowFilter, title: str = None, bundle_name: str = None)
```

**接口说明**

检查指定的window的属性是否符合预期。

**参数说明**

|序号|参数名称|参数描述|
|:-|:----------|:---------------------|
|1|title|预期的窗口标题，None表示不检查。|
|2|bundle_name|预期窗口所属的应用包名，None表示不检查。|

**使用示例**

```screen
# 检查当前焦点窗口的包名为com.huawei.hmos.settings。
driver.check_window(WindowFilter().focused(True), bundle_name="com.huawei.hmos.settings")
```

* **日志打印**

用户使用以下方法可以在测试用例脚本中打印日志，日志会记录到测试报告中。

```screen
fromdevicetest.core.test_case import Step, CheckPoint, MESSAGE

Step("点击按钮")
CheckPoint("检查联系人存在")
MESSAGE("打印一条提示消息")
```

在自定义实现的接口中，可以调用driver对象中的log模块打印日志消息，对应日志也会记录到测试报告中。

```screen
driver.log.debug("debug级别的日志")
driver.log.info("info级别的日志")
driver.log.warning("warning级别的日志")
driver.log.error("error级别的日志")
```

* **读取测试项目中资源文件路径**

用户可通过以下接口读取测试工程资源目录中的文件路径。接口接收文件名或相对路径作为参数，搜索测试工程资源文件目录并返回文件的完整路径。若未找到对应文件，则抛出异常。

```screen
from devicetest.utils import file_util
file_path = file_util.get_resource_path("filename")
```

该接口默认搜索文件，开发者可以设置isdir=True来搜索目录路径。

```screen
dir_path = file_util.get_resource_path("dirname", isdir=True)
```

## 隐私协议

**概述**

DevEco Testing Hypium(以下简称Hypium)是由华为终端有限公司（以下简称"我们"或"华为"）提供的UI自动化测试框架。华为非常重视您的个人信息和隐私保护，我们将会按照法律要求和业界成熟的安全标准，为您的个人信息提供相应的安全保护措施。

**1** **我们如何收集和使用您的个人信息**

我们将通过Hypium为您提供下述业务功能，在您使用相关业务功能的过程中，我们会处理下列提供功能所必需的信息，以便履行我们的合同义务。若您不提供相关信息，会影响到您使用本应用的相关功能。

**运行Hypium**

在您使用Hypium的过程中，我们会收集执行设备的操作系统平台和版本号，用于更好的提供和执行平台适配的测试服务。

**测试鸿蒙设备**

当您使用Hypium测试鸿蒙设备上的应用时，我们会收集被测设备的型号以及鸿蒙系统版本、被测应用的名称或者包名、Hypium特性功能的触发时间和使用次数，用于分析Hypium各功能在不同平台上的使用情况，从而针对性的优化我们的产品，更好的为客户提供服务。

**2** **对未成年人的保护**

我们非常重视对未成年人个人信息的保护，华为将严格按照国家法律法规要求在未成年人使用服务时提供相应的保护。如果您是未成年人，需要您的父母或其他监护人同意您使用本应用并同意相关应用的服务条款。父母或其他监护人也应采取适当的预防措施来保护未成年人，包括监督其对本应用的使用。如您是儿童，请务必退出使用本应用。

**3** **管理您的个人信息**

华为非常尊重您对个人信息的关注，并为您提供了数据主体权利及选择。

**3.1** **信息访问**

如您希望收集和存储的您的个人信息及其副本，可通过本声明中"如何联系我们"章节中所述方式与我们取得联系，并获取您的个人信息及其副本。

**3.2** **信息更正**

当您需要更新您的个人信息，或发现我们处理您的个人信息有误时，您有权作出更正或更新。您可以通过本声明中"如何联系我们"章节中所述方式与我们取得联系，并修改您的个人信息。

**3.3** **信息删除**

您随时可以通过本声明中"如何联系我们"章节中所述方式与我们取得联系，并要求我们删除您的个人信息。

**3.4** **停用服务**

对于hypium-driver-js安装包，您可以在项目根目录运行 `npx hypium-driver telemetry disable` 来停止Hypium处理您的个人信息。

对于hypium安装包，您可以在项目根目录运行 `python -m hypium telemetry disable` 来停止Hypium处理您的个人信息。

对于hypium-pycharm-plugin的插件，您可以在pycharm顶部导航栏中的DevEco Testing Hypium > 隐私协议页面，点击"拒绝并关闭"按钮来停止Hypium处理您的个人信息。

对于hypium-driver-js安装包，您可以在项目根目录运行 `npx hypium-driver telemetry enable ` 来恢复Hypium对您个人信息的处理。

对于hypium安装包，您可以在项目根目录运行 ` python -m hypium telemetry enable` 来恢复Hypium对您个人信息的处理。

对于hypium-pycharm-plugin的插件，您可以在pycharm顶部导航栏中的DevEco Testing Hypium > 隐私协议页面，点击"同意并开启"按钮来恢复Hypium对您个人信息的处理。

对于hypium-driver-js安装包，您可以在项目根目录运行 `npx hypium-driver telemetry status` 来查看Hypium个人信息处理状态。

对于hypium安装包，您可以在项目根目录运行 `python -m hypium telemetry status` 来查看Hypium个人信息处理状态。

对于hypium-pycharm-plugin的插件，您可以在pycharm顶部导航栏中的DevEco Testing Hypium > 隐私协议页面来查看Hypium个人信息处理状态。

**4** **数据存储地点及期限**

**4.1** **存储地点**

上述信息将会传输并保存至中华人民共和国境内的服务器。

**4.2** **存储期限**

我们仅在实现本声明所述目的所必需的时间内保留您的个人信息，并在超出下述保留时间后删除或匿名化处理您的个人信息，除非法律法规另有要求。

工具自身的测试数据及其备份数据将保存5年，目的是为了确保您的数据安全。

此外，当我们的产品或服务发生停止运营的情形时，我们将以推送通知、公告等形式通知您，并在合理的期限内删除您的个人信息或进行匿名化处理。

**5** **如何联系我们**

我们指定了个人信息保护负责人，您可以通过此[链接](https://consumer.huawei.com/cn/legal/privacy-questions/)联系个人信息保护负责人。您也可以通过访问[隐私问题页面](https://consumer.huawei.com/cn/legal/privacy-questions/)与我们其取得联系，我们会尽快回复。

如果您对我们的回复不满意，特别是当我们的个人信息处理行为损害了您的合法权益时，您还可以通过向有管辖权的人民法院提起诉讼、向行业自律协会或政府相关管理机构投诉等外部途径进行解决。您也可以向我们了解可能适用的相关投诉途径的信息。

华为将始终遵照我们的隐私政策来收集和使用您的信息。有关我们的隐私政策，可参阅[华为消费者业务隐私声明](https://consumer.huawei.com/minisite/legal/privacy/statement.htm?code=CN&language=zh-CN)。

