鸿蒙自动化UI测试框架Hypium使用指南
前言
最近在做鸿蒙的自动化测试Hap开发,类似安卓的monkey,一开始考虑的是使用鸿蒙提供的无障碍服务去实现,详情可以看我的上一篇文章,本来是打算往这一系列更新的,但目前鸿蒙的无障碍框架bug还是有点多的,功能也不完善,加上咨询了华为相关技术人员后得到的回复是无障碍服务可能再维护两三个版本就不再维护了,所以转而从别的方向下手,于是在华为的文档里看到了Hypium这个框架。
一、Hypium是什么?
DevEco Testing Hypium(以下简称Hypium)是HarmonyOS平台的UI自动化测试框架,支持开发者使用python语言为应用编写UI自动化测试脚本,主要包含以下特性:
- Hypium提供了原生控件/图像/比例坐标等多种控件定位能力,支持多窗口操作以及触摸屏/鼠标/键盘等多种模拟输入功能,支持多设备并行操作,能够覆盖各类场景和多种形态设备上的自动化用例编写需求。
- Hypium包含配套用例编写辅助插件, 支持控件查看/投屏操作等多种用例开发辅助功能,提升用例开发体验和效率。
- Hypium能够为执行的用例生成详细的用例执行报告,并且自动记录设备日志以及执行步骤截图,为开发者和测试人员提供高效和专业的测试用例执行和结果分析体验。
二、使用步骤
本机环境:windows11
python 3.8.10
Hypium-5.0.4.100
调试设备:HUAWEI Mate 60 Pro
OpenHarmony版本 5.0.0.31(Beta2)
1.环境配置
Hypium是基于python开发的,所以电脑上需要配置python环境,没有的可以点击去官网下载,建议版本在3.10以上python官网,同时调试设备需要用到HDC命令,所以也需要配置HDC环境,建议阅读华为官方文档的HDC配置教程。
配置完python环境后在本机用户目录下创建pip文件夹,并在pip目录中创建pip.ini文件,配置pip源为可以正常访问的pip源
代码如下(示例):
[global]
index-url = https://pypi.python.org/simple/
trusted-host = pypi.python.org
配置完后在CMD命令窗口输入 python -m pip install --upgrade pip 更新pip
开发平台选择pycharm,可以去官网下载pycharm官网下载地址
2.Hypium环境配置
从华为官网下载最新的Hypium框架安装包,解压后得到以下文件
其中hypium-5.0.4.100.zip需要解压,会得到四个gz包,DevecoTesting-Hypium-5.0.4.100.zip不需要解压,用来在pycharm中配置Hypium插件的,可以看官方指导(建议使用真机调试,这个插件提供的UiViewer不稳定)。
解压完hypium-5.0.4.100.zip,进入目录,此目录下输入cmd进入命令行工具,执行以下操作
pip install xdevice-5.0.3.300.tar.gz
pip install xdevice-devicetest-5.0.3.300.tar.gz
pip install xdevice-ohos-5.0.3.300.tar.gz
pip install hypium-5.0.3.300.tar.gz
请严格按照此顺序,因为相互依赖,顺序不对可能会安装失败。
3.使用
环境配置好后,在pycharm中新建一个工程如下:
单双设备主要用于后面同时调试设备的数量,最大数量为2
下面看一下新建的项目工程的项目目录
初始是这些目录,当然也可以自己创建目录,比如monkey就是我自己创建的模块
aw模块:可以用来存放工具类,也属于用户模块
config模块:该目录下有一个user_cxonfig.xml文件,配置信息如下
<?xml version="1.0" encoding="UTF-8"?>
<user_config>
<environment>
<!-- type: 设备连接方式,usb-hdc表示使用hdc命令控制设备(默认) -->
<device type="usb-hdc">
<!-- ip: 远端设备地址,ip和port为空时使用本地设备,非空时使用远端设备 -->
<ip></ip>
<!-- port: 远端设备端口号 -->
<port></port>
<!-- sn: 设备SN号列表,SN之间用分号";"分隔,sn字段为空时使用所有本地设备,非空时使用指定的sn设备 -->
<sn></sn>
</device>
</environment>
<testcases>
<!-- 指定测试用例目录,为空则默认设置为当前项目下的testcase文件夹 -->
<dir></dir>
</testcases>
<resource>
<!-- 指定资源目录,为空则默认设置为当前项目下的resource文件夹 -->
<dir></dir>
</resource>
<!-- 默认为INFO,如需更详细信息可设置为DEBUG -->
<loglevel>DEBUG</loglevel>
<devicelog>
<!--在测试用例结束后额外后拉取以下路径的日志到报告下-->
<dir>/data/log/tee;/data/log/test</dir>
<!--控制hilog日志等级,默认值为INFO-->
<loglevel>DEBUG</loglevel>
<!--控制是否在拉取日志后设备端的日志,默认值为true-->
<clear></clear>
<!--控制是否抓取设备日志,默认值为ON,OFF时候上述两个标签不生效-->
<enable>ON</enable>
</devicelog>
</user_config>
reports模块:用来存放日志记录的,可在user_config文件中修改
resources模块:用来存放资源文件,也属于默认资源文件存放路径,可修改
testcases模块:这个模块就是核心的执行模块,官方称为测试目录,以下重点介绍。
4.testcases模块
此模块分单测试用例和多测试用例,顾名思义,我们把该目录下的一个py文件当成一个测试用例,单测试用例就只有一个符合执行要求的py文件,而多测试用例就有多个符合执行要求的py文件
1.单测试用例
需要一个py文件和一个配套的json文件,json文件配置如下
{
"description": "Config for OpenHarmony app test suites",
//environment字段主要描述测试用例需要的环境信息,如需要多少个设备
"environment": [
{
"type": "device", //device表示OpenHarmony设备
"label": "phone" //设备类型,phone为手机,tablet为平板,默认不填写则对设备无要求
},
{
"type": "device", //多个设备时填写
"label": "phone"
}
],
// driver字段主要描述测试用例的测试驱动是什么,以及具体要执行的py脚本文件在哪(填写与当前json文件的相对路径即可)
// 不填写则在当前json文件下寻找同名py文件
// 注意:“py_file”字段当前只能填写一个py文件
"driver": {
"type": "DeviceTest",
"py_file": ["Test.py"]
}
}
单测试用例下py_file只能填写一个文件,其中文件名应改成当前目录下需要执行的py文件名,比如此处为Example.py,下面看Example.py文件内容
# !/usr/bin/env python
# coding: utf-8
"""
#!!================================================================
#版权 (C) 2023, Huawei Technologies Co.
#==================================================================
#文 件 名: Example.py
#文件说明: Example TestScript
#作 者: author
#生成日期: 2023-07-13
#!!================================================================
"""
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")
以官方案例讲解,只有继承TestCase类的py对象才是符合测试用例执行要求的,所以当我们想自定义测试用例的时候只需要新建一个py文件创建一个继承该类的对象,并在json文件中更改用例文件即可。
继承该文件后,需要重写上面几个方法,init里面可以用来初始化一些参数。setup、process、teardown被称为测试用例生命周期函数,顾名思义,会依次执行这三个函数。
setup:测试用例的前置步骤,主要用于执行测试用例的预置动作
process:测试用例的实际操作步骤
teardown:测试用例的清除步骤,主要用来执行测试用例的环境清理等操作
其实这三个函数都能写各种逻辑,但是尽量还是按照人家赋予的含义去执行相应的逻辑,在准备好项目后可以在当前工程根目录下打开cmd命令行,执行
python -m hypium run -l Example
即可开始运行,当然,前提是你得确保鸿蒙手机连接,hdc和python均可正常执行,都没问题后就会依次执行这三个函数的步骤。
def __init__(self, controllers):
self.TAG = self.__class__.__name__
TestCase.__init__(self, self.TAG, controllers)
self.driver = UiDriver(self.device1)
self.hapBundleName = ""
self.hapFileName = ""
def setup(self):
with open('apkConfig.json', 'r') as file:
data = json.load(file)
if data is not None:
self.hapBundleName = data['hapBundleName']
self.hapFileName = data['hapFileName']
self.handleHAP(self.hapBundleName, self.hapFileName)
time.sleep(2)
self.driver.start_app(self.hapBundleName)
else:
sys.exit("未传入正确hap配置信息")
def process(self):
while True:
self.checkCurrentPage(self.hapBundleName)
try:
nodeList = self.driver.find_all_components(BY.clickable())
node = random.choice(nodeList)
if not self.checkCurrentPage(self.hapBundleName):
continue
self.driver.touch(node)
except Exception as e:
print(e)
finally:
continue
def teardown(self):
self.process()
def checkCurrentPage(self,hapBundleName) -> bool:
result = self.driver.check_window(WindowFilter().focused(True), bundle_name=hapBundleName)
if not result:
self.driver.start_app(hapBundleName)
return result
def handleHAP(self,hapBundleName,hapFileName):
self.driver.uninstall_app(hapBundleName)
self.driver.shell("mkdir data/local/tmp/8bceae19e89344d9af43ac35fcb64988")
self.driver.hdc("file send "+hapFileName+" \"data/local/tmp/8bceae19e89344d9af43ac35fcb64988\"")
self.driver.shell("bm install -p data/local/tmp/8bceae19e89344d9af43ac35fcb64988")
self.driver.shell("rm -rf data/local/tmp/8bceae19e89344d9af43ac35fcb64988")
以上是我写的demo,作用是执行当前测试用例读取当前目录下的配置文件指定的需要自动执行的应用bundlename和apk名,完成自动安装的功能,并且自动打开该应用死循环执行模拟点击按钮并在跳出指定应用后会再次回到该应用继续执行。
2.多测试用例
其实多测试用例区别不大,只需要在新建文件的时候选择Hypium TestSuite就可以自动帮我们生成多测试用例可执行的文件,以我为例
基本结构和单测试用例差不多,只不过在testcases模块变化较大,但实际上这里的json文件配置更简单
默认可以什么都不配置,但是Ts_001.py要和json名称一样,进入Ts_001.py文件
可以看到两个熟悉的函数,没错,就是整个测试过程中的周期函数,开始和结束都会执行,具体的测试用例文件则是TC_001这些,因为我们在json文件中没做任何配置,所以我们的测试用例必须要以TC_开头,这样在框架执行的时候,才会自动去寻找这些文件并依次执行,如果不按照这个命名规则则找不到文件,执行指令依然是python -m hypium run -l Ts_001
当然,如果不按照这个命名规则也是可以的,但是要严格配置json文件
{
"description": "Config for OpenHarmony app test suites",
//environment字段主要描述测试用例需要的环境信息,如需要多少个设备
"environment": [
{
"type": "device",
"label": "phone"
}
],
// driver字段主要描述测试用例的测试驱动是什么,以及具体要执行的py脚本文件在哪(填写与当前json文件的相对路径即可)
"driver": {
"type": "DeviceTestSuite",
"testsuite": "TS_001",
//指定测试套中的测试用例列表,有两种方式
//方式一,定义suitecases字段,然后明确定义好当前测试套下有哪些测试用例(相对路径或者是绝对路径)
"suitecases": [
"testsuite1/XXX_001.py",
"testsuite1/XXX_002.py"
]
//方式二,测试用例的py文件放在testsuite1文件夹中,并且命名以"TC_"开头,框架即可自动扫描所有用例并执行
},
// kits字段主要描述测试用例需要的测试公共kit,如pushkit、shellkit等
"kits": [
]
}
说实话,我觉得这样挺麻烦的,还不如第一种方法。
总结
今天主要介绍了一下Hypium框架的配置和执行,后续再介绍控件相关的操作,自我记录一下,如果对您有帮助麻烦给个好评!
版权归原作者 平平无奇吗喽哥 所有, 如有侵权,请联系我们删除。