前言

最近在做IOS自动化测试,IOS的Appium环境都配置OK,Demo脚本运行没有问题,多开执行没有问题,IOS安卓统一平台调度集成没有问题,可以进行自动化测试。
课时真正执行用例时发现个严重问题:执行速度过慢,慢的像中国男足,Appium的执行log满屏刷,找元素像男国足球场一样骚,一个像无头苍蝇满场跑,一个有模有样的一轮又一轮的查找,就是命中不了。
很是蛋疼,一直疼了好几天,都有放弃的念头了。

调查

Xcode9 SDK不再支持snapshot功能了,没有snapshot功能就无法获取page_source。而从Appium1.6.5+后,Facebook用WDA snapshot, 相比于Xcode SDK的snapshot, WDA snapshot在生成page source的时候包含了一个之前没有的属性, 也就是visibility属性。计算元素的visibility在XCTest中是非常痛苦和昂贵的操作。
xpath 好像每次查找时都是重新生成一棵树,WDA需要额外的努力来实施XPath查询,这会严重影响查找时间遍历整个元素树,生成一个 xml 数据,然后再做 xpath 查找。遍历和在 xml 中进行 xpath 查找都相当耗时。论坛比较多的说法是查找元素策略的性能从高到低排列如下:Class Name>Accessibility Id>Link Text>Predicate>Class Chain>XPath
但是以上各种方式试过了,也没有让我的用例快起来。

大坑

搜索了很多帖子,很多人都是反映IOS自动化速度太慢。但是都没提怎么解决。由于不想改现在共通的滑动和安卓手机按键操作的代码,没有java-client升级,保留当前5.0.4的版本,没有想到掉这么个大坑里,搞了两三天百撕不得骑姐。
和py最新库执行相同用例后的速度对比后才发现,可能是jar包的原因。升级java-client版本5.0.4-->6.1.0,升级前来执行6分钟左右的下单用例,升级后2分钟(包括人为设置的等待时间)不到就执行完成了。
更换版本后真的快的飞起啊,比安卓用例执行更快了。
这里说一下我的环境配置,方便速度慢的同学参考:

  • Xcode:9.4.1
  • Appium:1.8.1
  • 模拟器:11.4
  • java-client:6.1.0(非常重要,和5比速度差的不是一个级别的)

元素定位优化策略

  • 尽量不使用xpath

长的Xpath定位可以使用谓词定位,Accessibility Id定位等来逐步缩小搜索的范围,曲线救国。如下例:

IOSElement inputEL = driver.findElementByXpath("//XCUIElementTypeNavigationBar[@name='LVMMTabBar']/XCUIElementTypeStaticTex");

转换成

IOSElement  barEL = driver.findElementByIosNsPredicate("type == 'XCUIElementTypeNavigationBar' AND name == 'LVMMTabBar'");
IOSElement inputEL =barEL.findElementByIosNsPredicate("type == 'XCUIElementTypeStaticText'");

但是由于有些复杂的Xpath很难完全将Xpath的定位方式转换成Class Name,Accessibility Id,Predicate或者classChain定位,所以Xpath还是不能抛弃的。
只能说尽量不使用xpath特别是页面元素比较多的时候。不到万不得已,尽量不用(页面元素少,速度还可以接受时,可以不转换,灵活运用,转换前后性能自行比较一下)。

  • 尽量使用高性能查找

各种查找元素策略的性能从高到低排列如下(未一一按时间来具体验证):
Class Name
AccessibilityId
Link Text
Predicate
classChain
XPath

使用方法这里就不一一赘述了。很多同学估计对谓词不了解,也是java-client版本5.0.4以及以后版本才可以使用的,用下来感觉蛮好的的。
可以看一下全网最好的谓词扫盲贴---->谓词大法传送门

  • 尽量使用精确查找

例如通常我们知道"name='https://testerhome.com'"的元素只有一个时,尽量使用

IOSElement  niubiEl = driver.findElementByIosNsPredicate("type == '最牛逼的测试交流论坛' AND name == 'https://testerhome.com'");

不要使用

List<IOSElement> niubiEls  = driver.findElementsByIosNsPredicate("type == '最牛逼的测试交流论坛' AND name == 'https://testerhome.com'");
IOSElement niubiEl = niubiEls.get(0);

同类的findElementByAccessibilityId和findElementsByAccessibilityId等

通常情况下findElements方法会遍历这个页面去找出所有匹配查询的页面元素,而findElement花费更多的时间, 因为findElement不会,而是仅仅返回第一个匹配查询的元素(机器是不会喊累,但也请不要让人家干无用功)。

  • 尽量少通配符

很多人喜欢封装,但是过度封装,使用很多通配符,以达到万能找元素的效果,但是可能带来的后果就是执行效率低。例如:

List<IOSElement>  comnEls  = driver.findElement("//*[contains(@name,'" + targetParam+ "') or contains(@label,'" + targetParam+ "') or contains(@value,'" + targetParam+ "')]");

调用是简单了,只需传个参数targetParam就好了,但是这需要扫描每个UI元素的所有name,lable,value属性(上面属性还可以继续加,达到万能匹配), 无疑这是极度低效的。
对于爬虫来说,可能需要爬取更多相关的东西,但是我们自动化来说,目标很明确。老老实实的的使用

IOSElement  niubiEl = driver.findElementByAccessibilityId("type == '最牛逼的测试交流论坛' AND name == 'https://testerhome.com'");

更高效。

  • 尽量减少和服务的通信

    if (driver.isElementExist("//XCUIElementTypeButton[@name='未选择']"))
    { driver.findElement("//XCUIElementTypeButton[@name='未选择']").click();
    }

    上述如果存在时,则会查找两次(也许例子不恰当)。不如把逻辑放在自己代码里。

    IOSElement  selEl = driver.findElement("//XCUIElementTypeButton[@name='未选择']");
    if(selEl != null)
    {
    selEl .click();
    }

升级后的小问题

升级后一些方法无法正常使用或者过时了。
点击升级前

new TouchAction(driver).tap(x , y).perform();

点击升级后

new AndroidTouchAction(driver).tap(PointOption.point(x , y )).perform();
安卓和IOS分开了
new IOSTouchAction(driver).tap(PointOption.point(x , y )).perform();

滑动升级前

new TouchAction(driver).press(beginX, beginY).waitAction().moveTo(endX, endY).release().perform();

滑动升级后

new AndroidTouchAction(driver).press(PointOption.point(beginX, beginY)).waitAction().moveTo(PointOption.point(endX, endY)).release().perform();
安卓和IOS分开了
new IOSTouchAction(driver).press(PointOption.point(beginX, beginY)).waitAction().moveTo(PointOption.point(endX, endY)).release().perform();

Android按键操作
升级前

driver.pressKeyCode(AndroidKeyCode.HOME);
driver.pressKeyCode(AndroidKeyCode.BACK);
.
driver.pressKeyCode(AndroidKeyCode.KEYCODE_NUMPAD_9);

升级后

androidDriver.pressKey(new KeyEvent(AndroidKey.HOME));
androidDriver.pressKey(new KeyEvent(AndroidKey.BACK));
.
androidDriver.pressKey(new KeyEvent(AndroidKey.NUMPAD_9));

后记

升级版本后总于解决了执行龟速的问题,蛋也不疼了,如同梦中看到国足秒杀欧冠一样的快意,看着执行速度快的飞起,简直要GC了。
这些遇到的一些小坑,总结分享一下。大神轻喷,分享给那些和我一样low 的人(看到很多人Q群里问环境搭建,Demo跑不了,求视频,还有很多付费培训广告),我感觉分享还是很有必要的,毕竟大神麼就你们几个。

关于IOS执行速度,你有什么骚操作,欢迎一起交流探讨。

一招让 IOS 自动化化快的飞起的更多相关文章

  1. iOS自动化环境搭建——macaca

    macaca-java for ios 自动化环境搭建 基础原理解析:https://testerhome.com/topics/6608 一.环境搭建 1.安装eclipse; -----Java开 ...

  2. 初识ios自动化(一)

    Appium进行自动化测试有两个好处: 1. Appium在不同平台中使用了标准的自动化APIs,所以在跨平台时,不需要重新编译或者修改自己的应用. 2. Appium支持Selenium WebDr ...

  3. iOS 组件化

    iOS 组件化介绍 随着应用需求逐步迭代,应用的代码体积将会越来越大,为了更好的管理应用工程,我们开始借助CocoaPods版本管理工具对原有应用工程进行拆分.但是仅仅完成代码拆分还不足以解决业务之间 ...

  4. 基于facebook-wda的iOS自动化操作实践记录

    [本文出自天外归云的博客园] 原理 对于iOS自动化操作,主要靠WebDriverAgent来完成.在Mac电脑上连接真机iPhone,运行WebDriverAgentRunner会在Mac端启动WD ...

  5. Jenkins+ Xcode+ 蒲公英 实现IOS自动化打包和分发

    Jenkins+ Xcode+ 蒲公英 实现IOS自动化打包和分发 直接入正题: Screen Shot 2015-09-18 at 16.56.20.png Mac上安装Jekins jekins下 ...

  6. 使用CocoaPods创建自己的私有库-iOS组件化第一步

    目前iOS组件化常用的解决方案是Pod+路由+持续集成,通常架构设计完成后第一步就是将原来工程里的模块按照架构图分解为一个个独立的pod工程(组件),今天我们就来看看如何创建一个Pod私有库. 新建: ...

  7. iOS 组件化路由框架 WisdomRouterKit 的应用

    [前言] 大家好,写作是为了和读者沟通交流,欢迎各位开发者一起了解 WisdomRouterKit SDK 的功能. 关于 iOS 组件化路由方案框架: WisdomRouterKit 的功能介绍,之 ...

  8. iOS组件化实现方案

    作者原文iOS组件化 - 路由架构从0到1实战  合伙呀 1.CTMediator作为路由中间件 2.基础UI组件以pod形式引入,并且能够独立运行调试 3.基础工具组件以pod形式引入,并且能够独立 ...

  9. IOS自动化打包介绍

    IOS自动化打包介绍  标签: app打包 , Ios打包 , iphone打包 , iphone自动化打渠道包    分类:无线客户端技术, 贴吧技术 摘要 随着苹果手持设备用户的不断增加,ios应 ...

随机推荐

  1. 树的遍历——c#实现

    树作为一种重要的非线性数据结构,以分支关系定义其层次结构,在客观世界中应用广泛.通过对树遍历,将树进行线性化处理,即遍历的结果是将非线性结构的树种节点排列成一个线性序列.其中,最常见的遍历方式包括先序 ...

  2. openstack swift curl 常用操作

    上传文件 curl -v -X PUT -H 'X-Auth-Token: AUTH_tkd9276f23b3404c67b8a6be45da881d6e' http://127.0.0.1:8080 ...

  3. Activity 启动模式 FLAG

    原文:https://blog.csdn.net/youhongyan/article/details/64151922 一.Activity启动模式的设置在AndroidManifest.xml文件 ...

  4. 【LeetCode刷题系列 - 002题】Add Two Numbers

    题目: You are given two non-empty linked lists representing two non-negative integers. The digits are ...

  5. margin-top / padding-top 的百分比 到底是多少?

    之前,我以为 margin-top/padding-top 如果设置成%,得到的是 基于父对象总高度的百分比. 但是,这种想法是错的.因为在CSS标准里,是基于父对象宽度的百分比. <style ...

  6. tiny4412--linux驱动学习(2)

    在ubuntu下编写验证字符设备驱动 1,准备工作 uname -r  查看电脑版本信息 apt-get  install  linux-source  安装相应版本的linux内核 2,编写驱动程序 ...

  7. python3 requestsGET请求传参

    GET方式传参方式一: import requests url = 'http://www.baidu.com/s?page=2' # 使用?携带参数 r = requests.get(url) pr ...

  8. RDMA RC UC UD

    RC:面向连接的可靠服务 UC:面向连接的不可靠服务 UD:面向数据报的不可靠服务 RD:面向非连接(类似UDP)的可靠服务 面向连接 vs 面向数据报 相同点:两者的通信均包括双方QP对的参与 不同 ...

  9. Oracle通过SCN做增量备份修复DG

    DG由于网络原因或者bug原因经常不同步,有时隔得时间久了,就会丢失归档日志,或者长时间的归档恢复较慢,有一种可以基于scn的方式来恢复DG库,使用基于scn的增量备份来恢复standby库可以节省大 ...

  10. 201621123002《java程序设计》第十二周学习总结

    1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结多流与文件相关内容. 2. 面向系统综合设计-图书馆管理系统或购物车 使用流与文件改造你的图书馆管理系统或购物车. 2.1 简述如何 ...