顾铮,10年+测试及测试开发相关经验,2014年加入京东,曾主导设计开发UI测试框架,参与CI测试平台建设,现负责iOS侧的工具,框架建设。在UI自动化,性能测试,单元测试方面有较深刻研究,在App,web端等有较丰富的测试开发和设计经验。php
>>>>android
写在前面web
关于UI测试的文章,多数是经过架构的演进,或是重构,或是推翻重作来说述的。今天我想讲述个人“一步到位”的测试框架设计。固然,这个“一步到位”是加引号的,并非说没有持续的优化或改进,而是指基础结构的稳定;这个“一步到位”是基于以前的失败经历和不少思考而得出的,总结我的经验,避免其余接触很少的同窗走弯路、踩坑。架构
UI自动化测试,即经过模拟手动操做用户UI界面的方式,以代码方式实现自动操做和验证的一种自动化测试手段。在十年前,那时候仍是PC web的天下,以Selenium驱动web UI的自动化测试仍是主流。五年前,当测试人员逐渐熟悉了Selenium API编写UI自动化用例时,互联网的主战场已经从web端逐渐过渡到了app端。如今,app在UI自动化方面的框架已经比较成熟,例如咱们已经使用了三年多的appium,还有诸如uiautomator、espresso、robotium等等。app
>>>>框架
UI能解决什么问题?运维
一、重复性的功能测试及验证函数
二、避免疲惫操做时的人为测试遗漏工具
三、经过UI自动化操做获取其余测试数据的能力性能
>>>>
UI的优缺点是什么?
在实际应用中,UI自动化能够帮助咱们节省人工测试成本,提升功能测试的测试效率。
缺点也是比较明显,随着敏捷迭代的速度愈来愈快,UI控件的频繁变动致使控件定位不稳定,提升了用例脚本的维护成本,同时定位的不稳定致使用例的可信度下降。
>>>>
UI的应用场景
主要应用于冒烟测试、回归测试、Dailybuild等阶段。
>>>>
UI存在的意义
存在即合理,咱们能够先看下软件测试的金字塔模型。
这个模型描述了从单元测试、集成测试,到UI测试的渐进式测试过程。越是底层,用例的执行速度越快,维护成本越低。到了最上层的UI时,执行速度处于比单元测试、接口测试慢,比手工测试快的这种阶段。维护成本上比单元测试,接口测试要高。
那么为何须要作UI呢?
一、实施起来较容易:不少同窗都有过这种经历,刚开始接触测试开发时,都是先接触UI的自动化。UI的框架比较成熟,容易上手,相关学习文档比较全面。实施起来通常都不依赖于源码,是比较容易落地的一种自动化测试手段。
二、覆盖范围广:此项是重点。UI上的一次操做的函数触发数量可能会很是多,点击一个按钮,可能触发了内部的几十个或者更多的函数调用。从函数调用数量来看,和单元测试的一个单测用例检查一个函数的逻辑是不一样的。UI操做检查的各个模块集成后模块之间的联动逻辑。是集成测试的有效手段,而单元测试是模块内部逻辑的检查。
>>>>
框架优势
>>>>
框架如何避免或下降UI的问题呢?
首先看下架构图
一、用例编写简单,下降上手门槛
因为测试人员的代码编写能力良莠不齐,让业务同窗能够快速上手编写是基本诉求。在operation层,使用了业界通用的Page-Object模式,即针对页面或模块封装操做方式,这也符合咱们的正常认知,在哪一个模块应该有什么样的功能操做。因此咱们在case层调用operation提供的接口时是很是方便的。下图是一条比较复杂的购物车测试用例。page是模块集合,main是首页接口,switchView为封装的切换操做。
2. 下降用例维护成本
当UI控件发生改动时,咱们须要对对应的控件定位方式进行修改。通常地,一个控件会被多条甚至几十条用例引用到,那么维护成本与引用数量成正比,引用的地方越多,维护成本越大。如何下降控件修改为本是很是关键的。
首先,须要作的是当封装的逻辑发生改变时,不会影响咱们用例层的逻辑组织。解决办法:
抽取各个模块的功能接口,在用例层调用统一接口进行操做,与具体的实现无关。具体是执行android的操做逻辑,仍是iOS的操做逻辑须要在运行时判断来选择对应的实现类。既能保持调用的一致性,也能够屏蔽不一样端的逻辑差别性。当android和iOS操做逻辑一致时能够卸载Adaptor里,当两端操做逻辑不一致时,须要分别在各自端的Operation中实现。
而后,当控件定位发生改变时,不会影响咱们在操做层的方法封装代码,把一处控件改动对应多处引用修改的一对多关系变为一对一关系,即不管引用了多少处此控件,只须要修改一处代码。
解决办法:为了使操做层在获取控件时与控件的定位方式解耦,在操做层经过获取自定义ID的方式来获得控件对象。此ID须要在控件的配置文件中定义好,再经过操做层之下的代理层来统一处理。
操做层的操做封装示例以下:
如上图所示,自定义ID为SearchBar,经过调用代理层的getTextBox方法来获得一个文本输入框类型的对象,并调用该接口的清除文本方法。
而后,在对应模块的XML配置文件中添加ID名及控件的定位方式。
其中dependMethod为控件查找方式,内嵌元素为查找的值。因为在编写操做方法时引用的是自定义ID,且ID不会改变。因此在Operation层封装的全部操做是不会由于控件改变而修改代码的。一对一的关系即:控件修改 —> xml配置修改。
经过以上这些设计,大大下降咱们在用例编写完成以后的维护成本。
三、底层识别框架(Appium)的可替换性,屏蔽不一样框架的差别性API
有的时候,咱们须要不止一套控件的识别驱动来帮助咱们定位控件或执行操做。好比:若是不用appium,那么使用其余框架势必会带来一些底层的改动,好比因为API的不一样而须要重写大部分的查找和操做方法。形成较大的替换成本。那么设计一套自定义的控件接口,与控件识别驱动解耦是一个好的选择,上层统一调用自定义接口进行操做,而控件的实现类能够根据你须要的驱动类进行选择或封装。
四、失败重试机制,提升用例稳定性
因为用例执行的稳定性直接决定用例在业务落地时的可信度,因此提升用例稳定性是必要的,框架提供了失败重试的机制来间接保证稳定性。即当监听到用例执行失败异常时,从新执行当前用例逻辑,若是执行成功,覆盖当前用例的执行结果;若是失败,从新执行,直到超太重试次数。
五、协助快速定位问题的能力
框架提供了日志和失败时截图进行分析和定位问题的能力。
六、数据统计的能力
用例的执行信息等数据都是由TestNG提供,再作自定义处理。
>>>>
UI测试的落地指标
一、用例执行经过率(稳定性)
通常地,执行经过率达到95%以上时,对功能测试同窗的帮助才是有意义的。经过率达不到的时候会大大增长执行用例同窗的运维成本。把大量时间放在了排查不稳定用例的问题上。
经过率的定义:(成功数 / 成功+失败+跳过数 )* 100%
二、核心用例覆盖率
覆盖率定义:已实现自动化用例数 / 功能测试核心用例总数 * 100%
通常地,总有一小部分手工用例是没法经过UI来实现的,或者就算实现了也很是不稳定。也就是说达到100%的覆盖率是基本不可能的。此项指标的意义在于能够客观的反应经过自动化手段代替手工劳动的覆盖比例。一味的提升覆盖率是不可取的,保持用例的经过率,提升用例的稳定性是重点。
三、资源投入度
这个指标实际上是一个通用指标,但它与咱们具体的落地密切相关。更多的时候,前2个指标都会依赖于此项指标。自动化测试须要的是持续资源投入,只有自上而下的推进才能取得更好的效果,体现它该有的做用。
>>>>
UI测试对接CI平台
因为appUI框架是线下本机环境执行和操做手机,能够搭建一个线上的公共平台来选择和触发UI的执行。做为一种常规的,自动化得测试类型嵌入到敏捷测试流程中。
如下是对接CI平台的执行简图: