当前位置: 首页 > 科技观察

鸿蒙自动化常见踩坑点及解决方法

时间:2023-03-19 23:23:04 科技观察

HarmonyosAutomation的常见陷阱及解决办法有些让同学头疼的问题有时会阻碍很长时间,影响编写自动化脚本的进度。那么,当我们遇到这些障碍时,我们应该如何下手呢?下面介绍几种常见的地坑机解决方案。当方法使用的定位元素为非坐标控件时,图片获取方法无法拦截toast!如何获取自动化的吐司样式?1.步骤:截取toast样式并保存样式图片(点击非元素坐标,获取不到toast图片)踩坑点:使用gif录制工具计算点击到弹出的时间toast,点击使用非元素坐标,获取不到toast的截图,正常逻辑思维,将点击时间改为弹出toast,总不能获取到toast图片,截取全屏比较样式图片与整体图片验证样式是否存在且一致2.获取图片方法:defget_image(png_path,xy=None):"""截图,当xy输入参数有效时,将进行裁剪:parampng_path:截图路径:paramxy:(x1,y1,x2,y2):return:"""conf.driver.get_screenshot_as_file(png_path)logger.debug("截图成功")ifxyisnotNone:ifisinstance(xy,tuple):foriinxy:ifisinstance(i,int):passelse:logger.error("xy的输入参数必须全部为正整数gers")raise(Exception,"xy的输入参数必须全部为正整数")try:Image.open(png_path).crop(xy).save(png_path)logger.debug("图片[%s]裁剪成功,裁剪坐标%s"%(png_path,xy))exceptExceptionase:logger.error("截屏失败")raiseeelse:logger.error("xyAdmission格式必须是(x1,y1,x2,y2)")raise(Exception,"xy的输入格式必须是(x1,y1,x2,y2)")3.创建文件名:expect_image=os.path.join(self.expect_images,"expect_Toast.png")assert_image=os.path.join(self.assert_images,"assert_Toast_001.png")success_image=os.path.join(self.success_images,"success_Toast_001.png")4.图片比较方法:defimage_assert(img1,img2,image_path=None,threshold=0.95,cvformat=1):"""断言img1是否在img2中,断言成功则将图片保存到本地!!!断言的图片必须使用appium进行截图,可以根据需要裁剪(可以使用该类下的get_image方法进行截图)!!!直接在模拟器上手动截图再对比appium的自动截图是比不上的,因为分辨率完全不一样!!!:paramimg1:期望图片:paramimg2:用例执行时的截图:paramimage_path:判断后,如果断言成功,则将对比图片保存在本地,本地路径,如果是则不生成对比图片不输入参数:paramthreshold:匹配度,建议大于0.9:paramcvformat:图像转换格式,输入参数1-转换为灰度图,输入参数不为1-转换为RGB格式,如果有严格的验证要求对于颜色,转换为RGB格式:raise(Exception,"[%s]图片不存在!"%img2)scale=1img=cv2.imread(img2)#大图img=cv2.resize(img,(0,0),fx=scale,fy=scale)template=cv2.imread(img1)#图片中的小图template=cv2.resize(template,(0,0),fx=scale,fy=scale)template_size=template.shape[:2]ifint(cvformat)==1:img_gray=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)template_=cv2.cvtColor(template,cv2.COLOR_BGR2GRAY)else:img_gray=cv2.cvtColor(img,cv2.COLOR_BGR2RGB)template_=cv2.cvtColor(template,cv2.COLOR_BGR2RGB)result=cv2.matchTemplate(img_gray,template_,cv2.TM_CCOEFF_NORMED)loc=np.where(result>=threshold)#使用灰度中的坐标对image原始RGB图像标记为point=()forptinzip(*loc[::-1]):cv2.rectangle(img,pt,(pt[0]+template_size[1],pt[1]+template_size[0]),(0,0,255),2)point=ptifpoint==():logger.debug("图片[%s]在图片[%s]中不匹配"%(img1,img2))returnFalseelse:ifimage_pathisnotNone:cv2.imwrite(image_path,img,[int(cv2.IMWRITE_PNG_COMPRESSION),3])#保存图片到本地logger.debug("图片[%s]与图片[%s]匹配成功"%(img1,img2))再转真5。Tap方法:defta_tap(self,selector,wait_presence=0,wait_visibility=0,timeout=20):"""模拟手指点击元素或坐标:paramselector:被点击的元素,定位器,要求格式为["元素名称","定位方式","定位表达式"],例如["XXX按钮","XPATH","//a[@text='测试location']"],["XXXbutton","ID","username"]:paramwait_presence:是否等待元素加载,0-否,1-required:paramwait_visibility:是否等待元素加载可见,0-不需要,1-需要:paramtimeout:等待时间,默认20秒:return:"""ifselector:try:locator_name=selector[0]locator_by=str(selector[1]).upper()#locationmethodlocator_value=str(selector[2])#locatorvalueexceptExceptionase:logger.error("ta_tapmethod:selector输入参数格式必须为list,[元素名称,定位方法,定位表达式]")raiseifstr(wait_presence)=="1"andstr(wait_visibility)=="1":logger.warning("ta_tap方法:请不要同时使用等待元素加载和等待元素可见!!!")iflocator_by=="XY":try:x,y=int(locator_value.split(",")[0]),int(locator_value.split(",")[1])exceptExceptionase:logger.error("XY坐标值格式错误,正确格式:x,y")raiseTouchAction(conf.driver).tap(x=x,y=y).release().perform()logger.debug("ta_tap模拟手指点击元素:(%s,%s)"%(x,y))eliflocator_by=="XY%":phonesize=self.get_phone_size()phonewidth=phonesize["width"]phoneheight=phonesize["height"]try:x,y=float(locator_value.split(",")[0]),float(locator_value.split(",")[1])exceptExceptionase:logger.error("XY坐标值格式错误,正确格式:x、y-x、y均为小数(不要填写百分比),如0.8、0.5")raiseeTouchAction(conf.driver).tap(x=int(x*phonewidth),y=int(y*phoneheight)).release().perform()logger.debug("ta_tap模拟手指点击元素:(%s,%s)"%(x*phonewidth,y*phoneheight))else:ifstr(wait_presence)=="1":self.wait_element_presence(selector,timeout)ifstr(wait_visibility)=="1":self.wait_element_visibility(selector,timeout)try:el=self.xlsxfind_element(selector)TouchAction(conf.driver).tap(el).release().perform()logger.debug("ta_tap模拟手指点击%s"%locator_name)exceptExceptionase:logger.error("tap方法异常,元素名%s"%locator_name)raiseeelse:raiseException("wait_element_presencemethod:theselectorparameterisrequired")6.例子:踩坑点2.appium版本1.5后不再支持ByName定位appium版本1.5后不再支持ByName定位,在appium1中。6.3/1.6.4/1.6.5版本后如何支持ByName定位,适用于Android和鸿蒙在使用appium1.5之后的版本,当我们直接应用ByName方法查找控件时,一定看到了这个错误:org.openqa.selenium.InvalidSelectorException:LocatorStrategy'name'isnotsupportedforthissessionfoundthattheoncepositioningartifactactuallyByName不再支持,那么如何解决这个问题?这里有两种解决方案:使用其他定位方式,比如使用xpath代替ByAByAccessibilityId,但是实践证明这种方式并不能代替ByName。第一个是可取的,还有其他定位方法方法,这里给大家提供一个不改变定位方法就可以使用的方法,可以在升级appium版本的时候无缝解决ByName的定位方法。一种方法是修改源代码来解决问题的根本原因。修改方法如下:本地找到Appium路径下的driver.js文件Appium\resources\app\node_modules\appium\node_modules\appium-android-driver\build\lib\driver.js只需要修改一行打开driver.js文件将“name”属性添加到代码行this.locatorStrategies=['xpath','id','classname','accessibilityid','-androiduiautomator','name'];修改完成后,保存,再次重启appium服务,可以继续使用ByName定位element=conf.driver.find_element_by_name("name").click()如果不想使用该方法,也可以使用通用的xpathelement=conf.driver.find_element_by_xpath("//*[@text='name']").click()来踩坑点3.弹窗点击确认或选择一个后option,存在脚本无法向下执行的问题。遇到这个问题,可以通过坐标点击页面弹窗,然后点击空白处释放,就可以继续执行了。比如desCharts组件在弹窗切换图表类型后,脚本会卡住。可以通过坐标点击一个不影响功能的弹窗,然后点击空白让弹窗消失,脚本可以继续执行:defexchange(self,elements,chart):"""切换图表选项(选择弹窗后脚本会卡住,需要松开)"""self.ta_tap(elements["图表切换选项"])ifchartin["堆叠折线图"、"直方图"、"堆叠柱形图"]:self.swipe_xy(452,680,450,150)time.sleep(1)self.ta_tap(elements[chart])time.sleep(1)self.ta_tap(elements["释放屏幕坐标"])time.sleep(1)self.ta_tap(elements["释放屏幕坐标"])time.sleep(1)踩坑点4.滚动功能不能时使用时,需要将列表滑动到特定位置AppiumSwipe此时不好用,drag_and_drop方式不能使用坐标点。解决方法:1、重写drag_and_drop方法,使其可以使用坐标点defdrag_and_drop(self,origin_el:Union["WebElement","dict"],destination_el:Union["WebElement","dict"]):action=TouchAction(self)ifisinstance(origin_el,dict):action.long_press(**origin_el)else:action.long_press(origin_el)ifisinstance(destination_el,dict):action.move_to(**destination_el)else:action.move_to(destination_el)action.release().perform()返回self2。示例:@allure.story("MusicBobber")@allure.title("MusicBobber_015")@allure.tag("L1")@allure.severity("normal")#blocker:阻止缺陷严重:严重缺陷正常:一般defectminor:minordefecttrivial:minordefect@allure.description("deletesuspensionpendant")@pytest.mark.flaky(reruns=1,reruns_delay=5)#reruns:heavyReruns_delay:重试间隔deftest_MusicBobber_015(self,allow):logger.info("MusicBobber_015")withallure.step("按下回车键"):logger.info("按下回车键")self.keyboard(4)time.sleep(1)withallure.step("删除暂停小部件”):记录器.info("DeleteSuspendedWidget")self.drag_and_drop({x:74,y:176},{x:540,y:2048})time.sleep(0.5)withallure.step("Verification"):logger.信息(“验证”)expect_image=os.path.join(self.expect_images,f“expect_MusicBobber_015.png”)assert_image=os.path.join(self.assert_images,f“assert_MusicBobber_015.png”)contrast_images=os.path。join(self.contrast_images,f"contrast_MusicBobber_015.png")self.get_image(contrast_images)flag=self.image_assert(expect_image,contrast_images,assert_image)self.image_in_report(flag,assert_image,expect_image)assertflagisFalse结论其实在UI自动化实践中我们还会遇到其他不同的障碍。Appium本身有一些错误。鸿蒙应用的自动化原理与Android基本一致。我们都是在摸索的过程中不断前行,所以遇到陷阱不要慌张。在出现问题的情况下,另一种解决方法也会让你豁然开朗。希望以上的问题和解决办法可以帮到你。更多信息请访问:鸿蒙科技与华为官方共建社区https://harmonyos.51cto.com