一、引子

UI自动化,在移动互联网时代的今天,一直都是在各大测试测试社区最为火爆的一个TOPIC。甚至在测试同行面前一提起自动化,大家就会自然而然的问:“恩,你们是用的什么框架?appium?还是robotium?”

其实在笔者看来,UI自动化是一个ROI较低的测试项(ROI即return on investment,中文意思是投资回报率)。但UI自动化相比接口自动化、白盒测试等,它更贴近手工业务测试行为。对于刚起步测试左移、效率提升的团队来说,是最迅速的切入点,也是广大黑盒tester,提升自身技术能力的起跑线。

笔者接触UI自动化一年多,兼顾业务测试的同时断断续续地投入,曾经无数次的想放弃:

“才刚写完用例,怎么开发大哥又改了UI了?”

“维护这些破用例的时间,都够我手工测三遍了,真的有意义么?”

“测试框架自己有bug,我改用例也没用啊……”

“我调试的时候这个用例还是通的,放到daily里面跑就不通,到底怎么回事嘛!”

“adb怎么这么不稳定啊,老是断!!!”

“怎么跑着跑着就crash了,到底是被测应用有问题,还是测试代码有问题啊?”

“明明界面上有这个元素,怎么就是查不到呢?”

“这破手机,能不能别老是系统弹框……”

“这手机真是渣,adb screencap截个图,居然要三分钟才返回!”

“这些控件都没有id,没有text,层级还三天两头改,要我怎么查……”

“查了这么多论坛,怎么就没有人遇到过类似的问题呢?”

……

这些问题让笔者一度怀疑,UI自动化这个TOPIC,是不是根本没用,只是tester为了涨薪,或者为了摆脱重复无聊的手工业务测试,而YY出来自我欺骗的。

二、问题分类及目标明确

笔者将以上所有的问题简单分成三类:设计类、环境类、细节类。一个好的设计模式,能够避免一部分问题;一套好的环境,可以让我们从乏味的维护工作中解脱;精益求精的细节,让测试用例更加可靠稳定。

图一UI自动化常见问题

填掉这三类坑,基本上就获得了一套低成本高产出、少量维护、稳定可靠的UI自动化用例集。

三、设计类问题分析与解决

“才刚写完用例,怎么开发大哥又改了UI了?”

“测试框架自己有bug,我改用例也没用啊……”

这类问题,我们需要从根上治。UI自动化开发,也应该是严谨的开发工作,它也需要设计模式,也是磨刀不误砍柴工。这里的设计,主要包括选工具、框架分层等。很多前辈都分析过UI自动化各类工具的优缺点,对工具选用笔者不再赘述。主要依托uiautomator来介绍下笔者认为比较巧妙的用例框架设计。

1、优化测试代码框架

无论你选择appium、uiautomator、robotium还是espresso,刚入门时,看到的sample应该大致都是这样的。

图二 uiautomator和espresso逻辑样例

问题在哪里?这些sample过于简单,都只教了我们UI自动化三元素:怎么查找元素、怎么操作元素、怎么校验结果。如果我们按照大多数分享帖或GitHub sample来写作自己的case。最后这种没有任何设计模式的框架,肯定会面临重构。拿上面的espresso来说:

1.假如action_save这个id开发改了,而你的用例集中,有30个步骤用例到了这个id,一个个去改,是不是要疯?

2.不厌其烦的重复写onView(withXX(xxx)).perform(click())这一长串,你不烦?

笔者是如何做的呢?

分层设计和PageObjects模式。这两个方法,基本解决了笔者遇到的图一中所有的设计类问题。

图三 框架设计建议

按照图三进行分层设计后,得到如图四的测试代码包。

图四 分层后的用例框架

PageObjects模式发源于selenium社区,它的目的是减少重复代码,当开发修改UI时,测试只需在有限的位置修改代码。如果大家想深入了解PageObjects,请参照如下wiki:

(https://github.com/SeleniumHQ/selenium/wiki/PageObjects

http://blog.csdn.net/kittyboy0001/article/details/25219053)。

我们来看一下,现在手管首页Page包中的代码和页面。

图五 手管首页Page层部分代码

回忆一下上面的google提供的sample,再对比引入分层设计和PO模式前后的代码,点击图五中的一键加速:

图六 引入PO前后代码对比

带来的好处,当然不仅仅是业务用例代码更清爽。

1、通过将查找和操作封装到基础层中,这部分代码就具体业务无关了,即使拿到其他产品中也可以复用;

2、通过page层的分离,所有的与业务相关的id,text等都被限定在了page包中,哪怕开发改了UI,修改page包特定的页面中对应的元素就好了。

3、对page包进行合理的业务拆分,比如将手管分成 MainPage(主页),SoftwareManagerPage(软件管理页),WiFiManagerPage(WiFi管理页)等,在开发改了某个具体业务的界面后,测试能够迅速知道测试代码需要改哪里。

2、兼容资源混淆的测试代码

除了整个框架的设计,有时候一些小问题也可以经过巧妙设计。比如资源混淆的问题。

图七 资源混淆

如图七,在手机管家的发布包中,用uiautomatorviewer dump下来发现,一键优化的button,其resource-id是o3,但其实开发coding时,定义的id显然不会用这种没有任何字面意义的代号,它在混淆之前叫optimize_button。

纯黑盒的UI自动化,也许你会摒弃optimize_button,直接写o3,但这样显然不够科学,既带来了严重的代码可读性问题,同时一旦版本迭代,混淆变了,o3也许就变成了o4。或者你会让开发给你测试的包,不要混淆,但如果想用UI自动化测试已发布的apk呢?

解决该问题,也得从PageObjects说起。回到图五中OPTIMIZE_BTN的定义,这个静态变量并未在page中初始化,只有一个@FindBy的注解。其实,在框架层驱动测试开始前,框架会先调用如下图八所示的setAllField来初始化所有的page页面。

1、如果被测应用未混淆资源,该方法只是将@FindBy中的值赋值给Field。

2、如果被测应用已混淆资源,该方法则会从mObfuscationMap(未贴出全部代码,实际是解析一个开发提供的混淆表,以原始id为key,混淆id为value的HashMap)中读出对应的id对应关系,将混淆后的id赋值给Field。

图八 Page层动态初始化

四、环境类问题分析与解决

“adb怎么这么不稳定啊,老是断!!!”

“明明界面上有这个元素,怎么就是查不到呢?”

“这破手机,能不能别老是系统弹框……”

“这手机真是渣,adb screencap截个图,居然要三分钟才返回!”……

引子中提到的这些问题,根据经验,多半你的环境执行环境还不够稳定。

1、ADB相关问题

已知的ADB不稳定原因如:电压不稳,各类手机助手的干扰,系统版本与ADB版本不匹配、ADB crash等等。如果我们迎难而上,去重写ADB,投入将无限扩大。所以建议主要的解决方案,还是尽量规避。

1)、选用可靠硬件规避电压不稳定。github上的STF项目组有过成熟的经验,选用性能更优的USB分接器,电压和可靠性会有更稳定的表现。(附上链接,wiki Recommended hardware一节中有不同硬件详细的性能对比:https://github.com/openstf/stf)。

2)、屏蔽各类手机助手的干扰。91助手、豌豆荚等,基本都在adb上做了二次开发,它们会与原生adb间有兼容性问题。建议直接使用Linux/MAC系统作为运行环境以屏蔽这类干扰。

3)、降低用例在执行过程中对环境的依赖。Appium这类自动化工具,每一个测试步骤都需要PC端的appium server和测试手机端的bootstrap交互消息。测试过程中只要USB连接不稳定,都会导致整个测试套的失败。所以笔者认为,使用更原生的uiautomator会是更好的选择;同时,测试过程中的日志、截图等,也尽量在测试手机上做持久化。

2、弹框问题的解决

权限弹框,是手管UI自动化中的一个大坑。如下图,是测试手管过程中,在华为手机上遇到的部分权限弹框。这些弹框,并不会用例每次执行都弹出,不同厂商的弹出框也不一致。显然点击弹框的逻辑,写在case逻辑中,只会导致自动化变得更复杂更不稳定。

图九 各类权限弹框

uiautomator的watcher,能够完全实现点击弹框和用例逻辑的解耦。当前笔者的实现逻辑是,监听弹框上的某个控件,当该控件出现时,执行action来点击掉其中的取消或确定按钮。这样,用例就只需关注业务逻辑,而任何时候的弹框,都由watcher来自动点击。如下图中,checkForCondition关注条件,action是操作。

图十 查找型Watcher

将所有的watcher分不同的手机厂商进行注册后,再调用runWatchers(),然后再执行用例。该方法可以在@BeforeClass中或者RunListener的testRunStarted中调用。当然,如果某个用例不想某个具体的弹框被watcher点击掉,也可以调用removeWatcher()反注册。

图十一 注册监听器

Watcher并不能解决所有的弹框问题。例如,在开启WiFi的场景中,由于WifiManager的setWifiEnabled和UI上的弹框点击是同步的(意思是调用了setWifiEnabled之后,如果界面上不点允许,该方法是不会返回的),使用上面的watcher方式并不会点击WiFi权限申请的允许。这时,就需要用到线程方式来解决(如下图十二),调用setWifiEnabled前,先启动一个线程等待弹框弹出。

图十二 多线程方式点掉弹框

五、细节类问题分析与解决

“我调试的时候这个用例还是通的,放到daily里面跑就不通,到底怎么回事嘛!”

出现上述问题,多半是因为我们的用例细节不够严谨。这类问题,往往决定着我们自动化用例集,是不是能从90%的case通过率,提升到100%。

1、顺序逻辑的用例

自动化相比手工,它只会关注code告诉它的验证点,所以选择逻辑在用例中应该是禁用的。如下图十三中右侧的case,如果用例执行到if中,也许else流程中存在BUG,反之亦然。此时考虑拆分用例,左侧才是理想的用例逻辑。

图十三 用例逻辑

另外,写作case时,一定要牢记,只有我们告知程序要assert,它才会去assert。查找,操作,断言,UI自动化三要素缺一不可。

2、解耦的用例

在testng中,会提供dependsOnMethods注解,似乎在鼓励写作用例时,使用用例间依赖。但笔者认为,用例间的依赖,会带来不必要的维护成本。只有高度解耦的用例逻辑,才能够更加健壮的支撑用例执行顺序调整、用例增删、出现异常场景后,A用例失败不会导致B用例也失败。

3、优化等待

有时候会遇到以下场景,虽然原生的自动化工具提供了等待元素可见的方法,但使用起来,还是无法真正等到元素可见。针对这个问题,如下图的waitCondition方法是一个不错的方案,它相对于thread.sleep来说,更节省时间。

图十四 反复等待方法

4、不用绝对坐标点击

绝对坐标点击,在不同尺寸屏幕上无法兼容。

第一方案应该是,推动开发对需要用到的控件添加ID或Accessibility。但根据经验还是会有一些场景需要用到坐标点击:

1、考虑投入产出比,为所有控件添加id的成本过高;

2、动态布局添加的ID都一样;

3、存在非xml布局的界面(代码中直接布局)。

这时,笔者依然不建议mDevice.click(100,200)这样的坐标点击。有以下两种值得一试的方案。

1、找到相邻控件坐标,计算当前控件的绝对坐标。如下图十四,uiautomatorviewer中点击右上角警告小三角,会得到有一些元素(黄色控件),是可能无法找到的。而使用相对坐标就是说,我们可以获取它相邻控件的坐标,然后减去或加上一个比较小的px值,再点击计算后的坐标即可。

图十五相对坐标

2、使用屏幕尺寸计算相对位置。在测试开始,将屏幕尺寸存下来,使用百分比的方式计算得到需要点击的位置。如下代码,点击【50%屏幕宽度,80%屏幕高度】的位置。

CODE: mDevice.click( screenWidth/2 , screenHeight*80/100 )。

六、总结

UI自动化测试是一门学起来很简单,用起来很麻烦的测试技术。

想要入门,两周就可以了解清楚uiautomator或espresso这类工具。UI自动化,无非就是查找元素、操作元素或设备、验证结果。这三个步骤循环多次,就是一个用例。

但要用好,并产出能效,需要走的路其实很长。由于篇幅限制和知识有限,这里不可能把所有的问题一一列出。对于所有这些问题,无非两个思路:一是绕过,二是解决。

1、选一个尽量简化,尽量底层的工具(uiautomator或espresso),从根上绕过一些工具会存在的问题;

2、采用良好的设计模式,让自己的框架更稳定,生命周期更长,维护成本更低;

3、明知道会耗费很多时间精力,收效却很小的环境问题,尽量绕过;

4、优化用例逻辑和细节,使之稳定可靠,更能说服别人相信自动化的测试结论。

做UI自动化一定要跨过这些坑相关推荐

  1. 小心!做UI自动化一定要跨过这些坑

    楚杰 2017年03月24日 一.引子 UI自动化,在移动互联网时代的今天,一直都是在各大测试测试社区最为火爆的一个TOPIC.甚至在测试同行面前一提起自动化,大家就会自然而然的问:"恩,你 ...

  2. 深圳软件测试培训:Pytest+Appium+Allure 做 UI 自动化的那些事

    深圳软件测试培训:Pytest+Appium+Allure 做 UI 自动化的那些事 文本主要介绍下 Pytest+Allure+Appium 记录一些过程和经历. 法主要用了啥: Python3 A ...

  3. python做ui自动化_[python]RobotFramework自定义库实现UI自动化

    1.安装教程 环境搭建不多说,网上资料一大堆,可参考https://www.cnblogs.com/puresoul/p/3854963.html,写的比较详细,值得推荐.目前python3是不支持r ...

  4. html5做ui自动化,案例赏析:某WEB系统UI自动化测试方案

    测试范围的确定原则: 1.稳定的需求点.变动较少的页面 2.比较频繁的回归测试 3.需要在多平台上运行的相同测试案例.组合遍历型的测试.大量的重复任务 1.主要功能模块及页面加载 2.页面中图表.数据 ...

  5. 【自动化测试】Pytest+Appium+Allure 做 UI 自动化的那些事

    文本主要介绍下 Pytest+Allure+Appium 记录一些过程和经历. 法主要用了啥: Python3 Appium Allure-pytest Pytest Appium 不常见却好用的方法 ...

  6. python自动化客户端_python 在 nwjs 应用客户端做 UI 自动化

    提示如下错误: Session ID: e5e688a264451f17c879ef6ab88ef3b5 at sun.reflect.NativeConstructorAccessorImpl.ne ...

  7. UI自动化原理 以及 那些跳过的坑

    接下来我准备系统学习 UI自动化 性能自动化 接口自动化 谢谢大家,要一直努力 做为测试工程师,我时常感觉到,测试生命中有两大幻觉: 今天能发布 明天能发布 一.原理 1.什么是UI自动化测试 使用工 ...

  8. UI自动化之driver.Tap坐标定位

    相信做UI自动化的小伙伴都知道,appium不是左右页面的元素都能定位的到的,尤其是原生中嵌套了H5页面,所有这个时候我们可以通过坐标定位的方式去解决,理论上坐标定位可以解决所有的元素识别问题,但有一 ...

  9. UI自动化平台(一)

    前言:最近萌生了做UI自动化平台的想法,以前做UI自动化都是直接脚本化的,也一直觉得UI改动一般都是很频繁,所以慢慢的脚本化的工作都放弃了,但是目前在公司,发现还是有点用的,公司的前辈也一直在完善脚本 ...

最新文章

  1. 超实用的 Mybatis 3.5 新特性
  2. mysql优化之--skip-name-resolve
  3. GPU迎来投资热潮 退潮后谁在裸泳
  4. es6 Promise.prototype.then()方法
  5. 检验mysql安装成功win7,手把手教你win7系统成功安装 RMySQL的处理对策
  6. 基于阿里云服务器使用宝塔面板搭建 Typecho 博客
  7. Unable to install breakpoint in XXX due to missing line number attributes的解决
  8. Linux下Shell脚本运行程序不输出日志到终端
  9. vs2005中分割线怎么插入
  10. win7本地登录计算机,win7系统绑定微软账户到本地电脑上的具体办法
  11. 在阿里云服务器上安装常用应用
  12. 中国能源与环保领域知名的调查研究咨询公司
  13. 浅谈zookeeper
  14. mybatis入门实例(xml文件配置)
  15. 你所知道的文字识别工具有哪些呢?不如看看这几款吧!
  16. CSP-202112-3-登机牌
  17. struts2漏洞学习记录
  18. myeclipse中怎么显示代码行号
  19. C# 网络编程之套接字编程基础知识
  20. 安装catia时 计算机ID不同步,CATIAV5R20安装手册A

热门文章

  1. fetch基于ajax,fetch与ajax(XMLHttpRequest)相比
  2. win10+mysql慢_Win1064位下mysql插入百万行数据耗时问题
  3. C#培训视频-《c#中国象棋》界面设计
  4. 上班坐坐族应该学的瑜珈
  5. web前端面试题分享(一)
  6. Python实现简单游戏:飞机大战
  7. 前端机器学习--识别人脸在脸颊上画草莓
  8. 2021年全球青贮玉米种子收入大约6382.6百万美元,预计2028年达到8090.4百万美元
  9. illusion,heftier
  10. jqgrid如何渲染表格数据_JqGrid 使用方法详解