HarmonyOS自动化测试实践

系统 自动化 OpenHarmony
在自动化过程中,元素出现受网络环境,设备性能等多种因素影响。因此元素加载的时间可能不一致,从而会导致元素无法定位超时报错,但是实际上元素是正常加载了的,只是出现时间晚一点而已。

[[420953]]

想了解更多内容,请访问:

51CTO和华为官方合作共建的鸿蒙技术社区

https://harmonyos.51cto.com

一、运行环境

工具列表

  • Appium-Desktop v1.8.2
  • Android SDK
  • Python
  • Appium-Python-Client
  • Pytest
  • Pycharm

工具安装:

Appium-Desktop v1.8.2

下载地址:Appium-Desktop v1.8.2, 对于鸿蒙系统,最佳的Appium兼容版本为v1.8.2。其他版本在获取text时的值为“0.0”

安装过程:

【中软国际】HarmonyOS 自动化测试实践-鸿蒙HarmonyOS技术社区
【中软国际】HarmonyOS 自动化测试实践-鸿蒙HarmonyOS技术社区
【中软国际】HarmonyOS 自动化测试实践-鸿蒙HarmonyOS技术社区
【中软国际】HarmonyOS 自动化测试实践-鸿蒙HarmonyOS技术社区

Android SDK

1.下载地址:Android SDK

2.将Android Studio安装在默认路径: C:\Program Files\Android\Android Studio

3.在Android Studio的SDK Manager中下载Android SDK

4.配置环境变量:

  • 新建JAVA_HOME,值为C:\Program Files\Android\Android Studio\jre
  • 新建ANDROID_HOME,值为C:\Users\Administrator\AppData\Local\Android\Sdk
  • 编辑Path, 新建%JAVA_HOME%\bin, %JAVA_HOME%\jre\bin, %ANDROID_HOME%\tools, %ANDROID_HOME%\tools\bin, %ANDROID_HOME%\platform-tools

Python

下载地址:Python

将Python安装在默认位置

环境变量配置

打开CMD,输入 python –version 测试python命令,输入 pip –V 测试pip命令

如果测试失败,则需要配置python的环境变量

Appium-Python-Client

安装命令:pip install Appium-Python-Client

【中软国际】HarmonyOS 自动化测试实践-鸿蒙HarmonyOS技术社区

Pytest

安装命令:pip install pytest

【中软国际】HarmonyOS 自动化测试实践-鸿蒙HarmonyOS技术社区

Pycharm

1.下载地址:Pycharm

Pycharm是比较流行Python编辑器(IDE工具),选择Community版本下载

2.将Pycharm安装在默认位置

3.选择python编译器

【中软国际】HarmonyOS 自动化测试实践-鸿蒙HarmonyOS技术社区

二、元素定位

元素定位工具常用的有:uiautomatorviewer.bat,weditor.exe,Appium-Desktop

【中软国际】HarmonyOS 自动化测试实践-鸿蒙HarmonyOS技术社区

以uiautomatorviewer为例看一下常见的查找控件方式

1.通过id定位,resrouce-id

  1. element = conf.driver.find_element_by_id("Id_myButton").click() 

 2.通过ClassName定位: classname

  1. element = conf.driver.find_elements_by_class_name("android.widget.Button").click() 

 3.通过Accessiblityld定位:content-desc

  1. element = driver.find_element_by_accessibility_id("content-desc-text").click() 

 4.通过AndroidUiAutomator

  1. ui_str = 'new UiScrollable(UiSelector().className("{}")).scrollIntoView(new UiSelector().textContains("{}"))'.format(list_id, text_contains) 
  2. element = conf.driver.find_element_by_android_uiautomator(ui_str).click() 

 5.通过坐标定位,XY

  1. TouchAction(conf.driver).tap(x=int(x * phonewidth), y=int(y * phoneheight)).release().perform() 

 6.通过xpath定位终极定位,方式有很多种,以下列几种常见:

  • 如果元素text是唯一的,可以通过text文本定位:
  1. //*[@text=’text文本属性’] 
  2. element = conf.driver.find_element_by_xpath("//*[@text='Click me!']").click() 
  • 如果元素id是唯一的,也可以id属性定位
  1. //*[@resource-id=’id属性’] 
  2. element = conf.driver.find_element_by_xpath("//*[@resource-id='org.ohosannotations.sample:id/Id_myButton']").click() 
  • 通过content-desc属性定位
  1. //*[@content-desc=’desc的文本’] 
  2. element = conf.driver.find_element_by_xpath("//*[@content-desc='desc的文本']").click() 
  • contains模糊定位
  1. //[contains(@content-desc, ‘desc的文本’)] 
  2. element = conf.driver.find_element_by_xpath("//*[contains(@content-desc, 'desc的文本')]").click() 
  • 组合定位

如果一个元素有2个属性,通过xpath也可以同时匹配2个属性,text, resource-id,class ,index,content-desc 这些属性都能任意组合定位

通过id和class属性 定位搜索框

  1. id_class = '//android.widget.EditText[@resource-id="org.ohosannotations.sample:id/Id_myTextField"]' 
  2. element = conf.driver.find_element_by_xpath(id_class).click() 

通过text和index属性 定位按钮Start list ability !

  1. desc_class = '//*[@text="Start list ability !" and @index="3"]' 
  2. element = conf.driver.find_element_by_xpath(desc_class).click() 

 通过class和text属性 定位输入框

  1. class_text = '//android.widget.EditText[@text="输入框默认值"]' 
  2. element = conf.driver.find_element_by_xpath(class_text).send_keys("zdhtest"

 通过class和desc 定位搜索框

  1. id_desc = '//*[contains(@resource-id, "Id_myTextField") and @content-desc="desc的文本"]' 
  2. element = conf.driver.find_element_by_xpath(id_desc).click() 

 鸿蒙与安卓定位方式基本相同

三、模拟用户事件

在自动化用户操作事件中,鸿蒙与安卓基本方式一致,以下列举常见的几种操作事件:

1.点击(确认点击)、输入和清空操作

  • 点击:能支持点击跳转的定位元素,通过.click()执行
  1. driver.find_element_by_id(‘org.ohosannotations.sample:id/Id_myTextField’).click() 

 输入:有输入框需要输入的定位元素,通过.send_keys()执行

  1. driver.find_element_by_id(‘org.ohosannotations.sample:id/Id_myTextField’).send_keys(‘zdhtest’) 

 清空:对已输入的输入框清空内容,通过.clear()执行

  1. driver.find_element_by_id(‘org.ohosannotations.sample:id/Id_myTextField’).clear() 

 2.元素等待作用

在自动化过程中,元素出现受网络环境,设备性能等多种因素影响。因此元素加载的时间可能不一致,从而会导致元素无法定位超时报错,但是实际上元素是正常加载了的,只是出现时间晚一点而已, 故设置元素等待可以更加灵活的制定等待定位元素的时间,从而增强脚本的健壮性,提高执行效率

  • 强制等待: 设置固定的等待时间,使用sleep()方法即可实现
  1. from time import sleep   
  2. #强制等待5秒 
  3. sleep(5) 
  • 隐式等待: 隐式等待是针对全部元素设置的等待时间
  1. driver.implicitly_wait(20) 
  • 显式等待: 显式等待是针对某个元素来设置的等待时间。

方法WebDriverWait格式参数如下:

  1.  
  2. from selenium.webdriver.support.ui import WebDriverWait 
  3.  
  4. WebDriverWait(driver, timeout, poll_frequency=0.5, ignored_exceptions=None) 
  5.  
  6. driver : WebDriver 
  7.  
  8. #timeout : 最长超时时间,默认以秒为单位 
  9.  
  10. #poll_frequency : 休眠时间的间隔时间,默认为0.5秒 
  11.  
  12. #ignored_exceptions : 超时后的异常信息,默认情况下抛NoSuchElementException异常。 
  13.  
  14. WebDriverWait()一般和until()或until_not()方法配合使用 
  15.  
  16. from selenium.webdriver.support.ui import WebDriverWait 
  17.  
  18. WebDriverWait(conf.driver, 10).until(EC.visibility_of_element_located((By.ID, self.locator))) 

3.Toast内容获取

Toast是一种简易的消息提示框。 当视图显示给用户,在应用程序中显示为浮动,和Dialog不一样的是,它永远不会获得焦点,无法被点击,而且Toast显示的时间有限,一般3秒左右就消失了,在鸿蒙应用中,Toast目前还捕捉不到,解决方法也是采用截图比较

  1. #Android获取Toast方式 
  2. toast_message = "这是一个toast文本" 
  3. message ='//*[@text=\'{}\']'.format(toast_message) 
  4. #显示等待检测元素 
  5. toast_element=WebDriverWait(driver, 5).until(EC.visibility_of_element_located((message, self.locator))) 
  6. print(toast_element.text) 
  7.  
  8. #鸿蒙中Toast处理方式 
  9. self.get_image(imagepath) 
  10. flag = self.image_assert(assertimagepath, imagepath, imagesucess) 

 4.截图操作

  1. save_screenshot() :方法直接保存当前屏幕截图到当前脚本所在文件位置 
  2. driver.save_screenshot(‘aa.png’) 
  3.  
  4. get_screenshot_as_file(self, filename) :将截图保留到指定文件路径 
  5. driver.get_screenshot_as_file(’./images/aa.png’) 

 5.滑动操作

  1. #获得机器屏幕大小x,y 
  2. def getSize(): 
  3.     x = dr.get_window_size()['width'
  4.     y = dr.get_window_size()['height'
  5.     return (x, y) 
  6.   
  7. #屏幕向上滑动 
  8. def swipeUp(t): 
  9.     l = getSize() 
  10.     x1 = int(l[0] * 0.5)    #x坐标 
  11.     y1 = int(l[1] * 0.75)   #起始y坐标 
  12.     y2 = int(l[1] * 0.25)   #终点y坐标 
  13.     dr.swipe(x1, y1, x1, y2,t) 
  14. #屏幕向下滑动 
  15. def swipeDown(t): 
  16.     l = getSize() 
  17.     x1 = int(l[0] * 0.5)    #x坐标 
  18.     y1 = int(l[1] * 0.25)   #起始y坐标 
  19.     y2 = int(l[1] * 0.75)   #终点y坐标 
  20.     dr.swipe(x1, y1, x1, y2,t) 
  21. #屏幕向左滑动 
  22. def swipLeft(t): 
  23.     l=getSize() 
  24.     x1=int(l[0]*0.75) 
  25.     y1=int(l[1]*0.5) 
  26.     x2=int(l[0]*0.05) 
  27.     dr.swipe(x1,y1,x2,y1,t) 
  28. #屏幕向右滑动 
  29. def swipRight(t): 
  30.     l=getSize() 
  31.     x1=int(l[0]*0.05) 
  32.     y1=int(l[1]*0.5) 
  33.     x2=int(l[0]*0.75) 
  34.     dr.swipe(x1,y1,x2,y1,t) 
  35. #调用向左滑动 
  36. swipLeft(1000) 
  37. #调用向右滑动 
  38. swipRight(1000) 
  39. #调用向上滑动 
  40. swipeUp(1000) 
  41. #调用向下滑动 
  42. swipeDown(1000) 

 6.按压、长按、点击(单纯点击)、移动、暂停、释放、执行等操作

  • 强制等待: 设置固定的等待时间,使用sleep()方法即可实现
  • 按压:press() 开始按压一个元素或坐标点(x,y)。通过手指按压手机屏幕的某个位置。 press也可以接收屏幕的坐标(x,y)。press(self, el=None, x=None, y=None)
  1. TouchAction(driver).press(x=0,y=308) 
  • 长按:longPress() 开始按压一个元素或坐标点(x,y)。 相比press()方法,longPress()多了一个入参,既然长按,得有按的时间吧。duration以毫秒为单位。1000表示按一秒钟。其用法与press()方法相同。
  1. long_press(self, el=None, x=None, y=None, duration=1000) 
  • 点击:tap() 对一个元素或控件执行点击操作。用法参考press()。不能点击跳转,单纯的点击(例如:点击勾选、点击点赞,点击播放等)
  • 移动:move_to() 将指针从上一个点移动到指定的元素或点。(滑动验证条)
  1. move_to(self, el=None, x=None, y=None) 
  • 暂停:Wait()暂停脚本的执行,单位为毫秒
  1. wait(self, ms=0) 
  • 释放:方法release() 结束的行动取消屏幕上的指针。
  1. release(self) 
  • 执行:perform() 执行的操作发送到服务器的命令操作。
  1. perform(self) 

7.获取元素的屏幕尺寸和名称

  • 获取屏幕尺寸:
  1. 屏幕总尺寸:分辨率 phonesize = self.get_phone_size() 
  2.  
  3. 屏幕宽度:X值 phonewidth = phonesize["width"
  4.  
  5. 屏幕高度:Y值 phoneheight = phonesize["height"
  • 获取元素的名称:
  1. driver.find_element_by_xpath(xpath).text 
  2. driver.find_element_by_id(“org.ohosannotations.sample:id/Id_myTextField”).text 

四、简单示例

以下是两个简单case

1.示例一

下面以ohosannotations组件为例,case中包含事件有:点击、长按、输入、文本断言和图片对比断言

  1. def test_ohosannotations(self, getlocator): 
  2.         annotations_locators = getlocator["ohosannotations"
  3.         with allure.step("点击Click me_按钮的点击事件"): 
  4.             self.ta_tap(annotations_locators["Click me_按钮"]) 
  5.         with allure.step("向输入框输入内容"): 
  6.             self.text_input(annotations_locators["myTextField_控件"], "这是一条有内涵的内容!"
  7.             self.ta_tap(annotations_locators["Click me_按钮"]) 
  8.             time.sleep(2) 
  9.             assert "这是一条有内涵的内容!" == self.get_element_text(annotations_locators["myText_控件"]), "文本显示不正确" 
  10.         with allure.step("长按Start extra ability, long click !控件"): 
  11.             logger.info("长按Start extra ability, long click !控件"
  12.             self.ta_longpress(annotations_locators["Start extra ability, long click_按钮"], 1000) 
  13.             time.sleep(2) 
  14.         with allure.step("断言弹出框图片与期望图片是否一致"): 
  15.             self.get_image(imagepath) 
  16.             flag = self.image_assert(assertimagepath, imagepath, imagesucess) 
  17.         if flag is True
  18.             with open(imagesucess, "rb"as f: 
  19.                 context = f.read() 
  20.                 allure.attach(context, "匹配成功的图片", attachment_type=allure.attachment_type.PNG) 
  21.         else
  22.             with open(imagepath, "rb"as f: 
  23.                 context = f.read() 
  24.                 allure.attach(context, "匹配失败的图片", attachment_type=allure.attachment_type.PNG) 
  25.                 logger.info("匹配结果:%s" % flag) 
  26.                 assert flag is True 

 运行结果:

2.示例二

以Sensey组件为例,演示多点触控的使用方法,验证Sensey组件的双指检测功能

  1. @allure.story('Sensey'
  2. @allure.title("sensey_006 双指检测"
  3. @allure.tag("L1"
  4. @allure.severity("normal")  # blocker:阻塞缺陷 critical:严重缺陷 normal:一般缺陷 minor:次要缺陷 trivial:轻微缺陷 
  5. @allure.description("双指检测"
  6. @pytest.mark.flaky(reruns=1, reruns_delay=5)  # reruns:重试次数 reruns_delay:重试的间隔时间 
  7. def test_sensey_006(self, getlocator): 
  8.     logger.info("sensey_006 双指检测"
  9.     self.ta_tap(["TOUCH DETECTOR""XPATH""//*[@text=\"TOUCH DETECTOR\"]"]) 
  10.     self.ta_tap(["Touch Detection""XPATH""//*[@resource-id=\"Id_switch_touch\"]"]) 
  11.     a1 = TouchAction(conf.driver).tap(x=530, y=1380).release() 
  12.     a2 = TouchAction(conf.driver).tap(x=730, y=1380).release() 
  13.     action = MultiAction(conf.driver) 
  14.     action.add(a1,a2) 
  15.     action.perform() 
  16.     time.sleep(0.5) 
  17.     text = self.get_element_text(["Result""XPATH""//*[@resource-id=\"Id_tv_result\"]"]) 
  18.     assert text == "Two Finger Tap""双指检测不正确" 

 运行结果:

五、测试报告生成

使用allure-pytest插件

  1. @allure.feature('设置应用')  # 功能名称 
  2. class TestSettings(BaseCase): 
  3.  
  4.     @allure.story('声音和振动')  # 子功能名称 
  5.     @allure.title('settings_001 设置来电铃声')  # 用例标题 
  6.     @allure.severity('normal')  # 缺陷级别 
  7.     @allure.description('检查是否可以设置来电铃声')  # 用例描述 
  8.     def test_settings_001(self): 
  9.         # 测试步骤 
  10.         with allure.step('进入声音和振动'): 
  11.             pass 
  12.         with allure.step('设置来电铃声'): 
  13.             pass 
  14.         with allure.step('断言来电铃声设置成功'): 
  15.             pass 

 生成html报告和打开

  1. if __name__ == '__main__'
  2.  
  3.     now = time.strftime('%Y%m%d%H%M%S'time.localtime()) 
  4.     print('执行脚本(%s)' % now) 
  5.  
  6.     xml_path = './reports/report-%s/xml' % now 
  7.     html_path = './reports/report-%s/html' % now 
  8.     case_path = './testcases/' 
  9.  
  10.     # 运行测试脚本 
  11.     pytest.main(['-s''-q''--alluredir', xml_path, case_path]) 
  12.  
  13.     # 生成html报告 
  14.     cmd = 'allure generate %s -o %s --clean' % (xml_path, html_path) 
  15.     os.system(cmd) 
  16.  
  17.     # 打开测试报告 
  18.     cmd = 'allure open %s' % html_path 
  19.     os.system(cmd) 

 生成报告如下:

【中软国际】HarmonyOS 自动化测试实践-鸿蒙HarmonyOS技术社区

展开详情:

【中软国际】HarmonyOS 自动化测试实践-鸿蒙HarmonyOS技术社区

想了解更多内容,请访问:

51CTO和华为官方合作共建的鸿蒙技术社区

https://harmonyos.51cto.com

 

责任编辑:jianghua 来源: 鸿蒙社区
相关推荐

2022-09-12 16:02:32

测试企业工具

2017-08-29 09:57:26

SaaS产品自动化

2021-09-07 09:00:00

开发测试工具

2023-02-07 08:11:15

2020-11-04 09:00:00

自动化测试回归测试软件测试

2022-02-17 10:37:16

自动化开发团队预测

2012-02-27 17:34:12

Facebook自动化

2014-04-16 14:15:01

QCon2014

2013-05-16 10:58:44

Android开发自动化测试

2011-12-23 17:09:57

自动化测试

2023-03-29 08:33:03

仓储自动化系统

2021-06-30 19:48:21

前端自动化测试Vue 应用

2012-12-24 22:54:31

2024-11-01 15:05:12

2017-09-06 16:08:45

JmeterJenkins自动化测试

2017-09-21 16:06:43

DevOps自动化测试代码

2021-11-05 09:00:00

Selenium工具自动化测试

2022-05-26 10:13:22

C/C++GCC插件单元测试

2014-11-20 13:49:15

2011-06-03 17:24:48

自动化测试
点赞
收藏

51CTO技术栈公众号