2017/06/21自动化的坑

摘抄自:http://tmq.qq.com/2017/03/uizidonghua/

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

一、引子

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自动化过程中遇到过难以解决的问题呢?欢迎大家留言讨论。也祝愿大家在UI自动化的道路上越走越顺!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,324评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,303评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,192评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,555评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,569评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,566评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,927评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,583评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,827评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,590评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,669评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,365评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,941评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,928评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,159评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,880评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,399评论 2 342

推荐阅读更多精彩内容