iOS 测试 Appium IOS 测试速度优化策略

Stepthen · 2015年09月16日 · 最后由 yy 回复于 2021年05月11日 · 3236 次阅读

Guide

用 appium 测试过 IOS 的同学都会发现,IOS 脚本执行速度比 Android 慢很多,具体原因这里不深究;只讲下自己目前的优化策略,希望对后学习的同学有些帮助,有经验的同学也希望多多提供分享。

  • 1.尽量避免使用 xpath: -
    xpath 的通用灵活性使用起来确实很方便,一开始我们找元素是全部用二次封装的 xpath 来查找;然而对比后却发现,用 xpath 找元素要比 ByName 和其他慢很多。所以建议大家尽量避免使用 xpath 查找元素。

  • 2.用 SetValue 代替 SendKey: -

    //C#语言:
    AppiumWebElement appiumElement = (AppiumWebElement)driver.FindElementById("账号");
    appiumElement.SetImmediateValue(136xxxx9501);
    

    代替:

    IWebElement element = driver.FindElementById("账号");
    element.SendKeys("136xxxx9501");
    
  • 3.尽可能少的去和 appium 通讯: -
    能直接在代码中处理的,就尽量在代码中处理,减少和 appium 的通讯,例如:

    startX = elmentA.Location.X ; 
    endX = startX /5 ;
    

    代替:

    startX = elmentA.Location.X ; 
    endX = elmentA.Location.X/5 ;
    
  • 4.待尝试: -
    另外想到的一种优化方式就是缓存页面,暂时还没开始做:思路是先用 driver.PageSouce 将页面缓存起来,重写查找方法,先去缓存中找元素,缓存中找不到时,再重新用 driver.PageSouce 下载页面元素重新找。这种方式理论上会快很多,不过麻烦的是需要重写很多东西了。

鄙人基础比较差,刚做 Appium 自动化不久,希望高手们多多指导,多多分享!

如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
共收到 16 条回复 时间 点赞

#4 楼 @happystone 截图和录视频这个可以看下 stf 的 minicap ,doctorq 之前写过一个帖子:STF 框架之 minicap 工具

对于 xpath 的慢,我目前查看源码后理解的原因是这样的:

  1. xpath 需要遍历整个元素树,生成一个 xml 数据,然后再做 xpath 查找。遍历和在 xml 中进行 xpath 查找都相当耗时。
  2. 除 xpath 外主要有几类方法。
    1. UIAutomation 代码(如 ios-predicate),直接执行,速度杠杠的。
    2. byId,byName,byAccessibility 这些都是边查找边比较,不会遍历所有元素,所以速度相对快。

至于前面 @among29 提到的 page_source 的坑,不知和我们遇到的是否一样?我们遇到的是用例不稳定,is_display 方法和 click 方法有一定概率失效,结果发现失效原因是 appium 在 find 的时候缓存的对象已经失效(我们项目中是对应的 app 元素已经被 remove+add 过,内存地址都已经改了),但调用这个对象的方法也不会出错(没有任何异常抛出,只是一直 click 会报错,而 is_display 一直返回 False )。标志是获取这个元素的坐标 (el.position) 出来的值很不正常,会有一个带有 e32 的无穷大值。

现在我们通过改造 appium 对应模块的方法解决,主要改了两处:

  1. 在内部缓存中不仅存储元素对象,还存储元素查找方法。一旦对象无效(如 name 属性为 null)就执行查找方法再次查找,如果找不到(UIAElementNil),就抛 StaleElementReference 异常。对应代码:https://github.com/appium/appium-uiauto/compare/master...chenhengjie123:element-cache-fix

  2. 增加一个 onlyVisible 属性,在 xpath 查找和 byId,byName 查找中跳过不可见元素(ByUIAutomation 暂时还没做,还在构想要怎么做中),一个是提高查找效率(遍历的元素数量少了),另一个是更好地实现 android 和 iOS 脚本复用(iOS 上有些隐藏元素和可见元素有一样的 id 和 name )。对应代码(还在调试中):https://github.com/appium/appium-uiauto/compare/master...chenhengjie123:hide-invisible-elements

由于修改的不是 appium 核心代码,所以只需要用这个修改后的替代原来的 appium-uiauto 就可以了。

def tmp_page(self):
        temp = self.dr.page_source
        fh = codecs.open(self.tmp_source_file, "w", "utf-8")
        fh.write(temp)
        fh.close()

self.dr.page_source 有坑,要小心,一旦用了这个方法,有些元素的 el.is_enabled() and el.is_displayed() 可能会发生变化,导致后续的一个 click , clear 会失败。当时 debug 了很久,所以这个方法少用。具体你们可以试试。

嗯,是一个办法。但如果判断元素是否可操作?比如点击动作,无论元素是否可以点击,都没有返回值。是不是页面跳转来判断?

陈恒捷 回复

嗯,我看到有一个 visable 属性,如果元素被弹框遮挡,visable 应该为 false。所以,如果我用 find_ele_by_Xx 是不是可以再加一个条件,visable 必须为 true,我才认为元素真的被找到了,就是不知道这样的方法,visable 在不同场景下其返回的值是不是正确的,如果 visable 值返回与实际不符合,感觉也没有意义

yy 回复

点击动作,如果失败的话,应该会抛出异常的。你上面这个场景,无法操作的表现是可以正常调用点击事件,且没有出现任何异常?

如果界面有弹框,在没有取消弹框的情况下,去点击弹框下一层的元素,是没有任何异常的,所以无法根据点击结果来判断是否成功呢?

yy · #16 · 2021年05月11日
仅楼主可见
yy · #17 · 2021年05月11日
仅楼主可见
陈恒捷 回复

大神,每次困惑的时候帖子。现在有一个场景需要解决,但是一直没有好的办法。
场景:某一个页面需要定位一个元素,但此时存在异常弹框,弹框并未把元素遮挡住,元素依然能定位到,只是无法操作。代码处理异常弹框的逻辑是,只有当目标元素无法定位时,才会进入到异常弹框处理流程。所以该场景就会有问题了。

按照我的理解,想根据元素的属性来判断当前元素是否应该被找到,但是有无弹框,目标元素的属性都是一样的,请问这种场景下,怎么处理呢?谢谢

第 3 个用过,效果明显。其他还未尝试。

@seveniruby ,很赞同你的说法,稳定性确实要排在第一位的。我们这边之所以对速度比较关注是因为我们这边的测试环境需要:

  1. 我们这边主要做回归测试,代码和测试用例是分离的,也就是对 appium 进行二次分装,分装结束后直接用行为和数据驱动。这样需要代码具有通用性,缺少了直接写脚本的灵活性,导致速度更慢。
  2. 测试平台要求实现录制测试过程,方便业务错误分析,其实是没多大必要的,错误截图就够了,但是领导要花样我们也是没办法的,目前实现了一个步骤截一张图,测试结束后转换成 gif 动画上传服务器,这个截图也是很耗时间。
  3. 测试的是手机银行软件,业务逻辑比较多,后期案例有几百个,且变更测试频繁。优化前一个转账要 12 分钟,目前 5 分钟左右。

@chenhengjie123 ,非常感谢分享,对我们这些初学的同学帮助很大!

匿名 #8 · 2016年04月13日

感谢分享,收藏

@among29 ,暂时还没怎么用过 pageSource ,后面会注意一下。

写的不错. 赞. XPath 的支持, 官方实现的不好. 所以形同鸡肋. 不过做 UI 自动化的话, 速度还不是最大的问题. 稳定性才是.

yy 回复

最简单的办法,可以加上无法操作时(应该有对应的异常类),也进入异常弹窗处理流程,检测有没有弹窗,有就关掉?

需要 登录 后方可回复, 如果你还没有账号请点击这里 注册