第2章 移动测试的伪银弹—— UI自动化 · 2016-08-12 ·...

16
第2章 移动测试的伪银弹—— UI自动化 2.1 为什么测试热衷于UI自动化 2.2 我们为什么不做UI自动化 2.3 我们为什么要做UI自动化 2.4 你做的是伪UI自动化吗 2.5 UI自动化框架

Transcript of 第2章 移动测试的伪银弹—— UI自动化 · 2016-08-12 ·...

第2章  移动测试的伪银弹——UI自动化

2.1  为什么测试热衷于UI自动化

2.2  我们为什么不做UI自动化

2.3  我们为什么要做UI自动化

2.4  你做的是伪UI自动化吗

2.5  UI自动化框架

86

大话APP测试2.0 ——移动互联网产品测试实录

其实本章原本是不存在本书当中的,但是由于笔者感觉移动互联网绝大部分的人都在做UI自

动化,从而带给这个世界一个错觉,自动化只有UI,别的没有办法做了,而且感觉就是要做一辈

子的样子。所以决定介绍一下UI自动化。笔者已经很久不做这传说中的UI自动化了,所以如果以

下说明有问题,还请大家随时来咬我。

2.1  为什么测试热衷于UI自动化

2.1.1  Android与iOS框架历史回顾

这里介绍一下为什么移动互联网的测试那么热衷于UI自动化。首先给出UI自动化定义,这里的

UI自动化无非是指两类。

1)界面层面(控件、元素、位置、显示等)。

2)功能交互层面(往往是通过代码或者测试框架来模拟真实用户的操作)。

测试人员热衷于UI自动化,与两个平台的历史以及提供的框架都有关系。Android 平台上第一

个接触的 UI 自动化工具肯定是 Monkey 这个工具了,这个工具的使用我在《大话移动APP测试》

这本书中已经很详细讲过了,这里不多提了。但无论Android的Monkey还是iOS的手动测试,其本

质都是UI的测试,这也决定了很多入门的测试者潜意识中被UI测试、黑盒测试、功能测试等所占

据,难以完整认识测试行业。

而iOS的人员,我真的不是鄙视测试iOS的人员,曾经我说过这样一段话“100个测试iOS的工

程师里面,有50个没有用过Macbook,10个没有用过Xcode,10个没有用过Instruments,10个没有

看过产品代码”,所以大部分测试iOS的人员仅仅也只是拿着iPhone在自己模拟Monkey Test。

然 后 再 来 看 两 个 平 台 的 框 架 。 A n d r o i d 从 发 展 到 现 在 大 家 最 熟 悉 的 莫 过 于

ActivityInstrumentationTestCase和ActivityInstrumentationTestCase2这样两个类。但我相信

大部分只做UI自动化的测试人员,其实并不知道有ActivityInstrumentationTestCase的存在,

并且认为ActivityInstrumentationTestCase2是Instrumentation的全部,其实Instrumentation作

为Android最早的合法的测试框架已经哭了很久了。从行业以及Google近几年提供的测试框架来

看,热门的有Robotium、NativeDriver、Athrun(TMTS)、Calabash、Appium、Espresso、

MonkeyRunner、Monkey、uiautomator等,无一不是UI自动化框架,所以也不能怪测试人员被

这样一个趋势就带着走了。如果这些框架都用过,源码都解析过的话,那么肯定是不会被众多框

架所迷惑。iOS相对就好很多,非侵入式的话无非就是使用instruments下面的uiautomation,这

里不解释了,这个名字已经说明了一切。侵入式代表有KIF、Calabash等,这两个也都是UI自动化

测试框架。

87

第2章  移动测试的伪银弹——UI自动化

从以上的历史和目前的框架发展情况来看,不难看出UI自动化工具和框架的确有很多,多到足

以让一个资深测试者眼花缭乱,然而这可以成为一个借口,但并不能成为测试者热衷UI自动化的一

个主要原因。

2.1.2  原因

我们来探索测试人员热衷于UI自动化还有什么原因。是的,和测试人员所在的环境、所在的企

业有密不可分的关系。其实移动互联网行业中的大部分企业的确就是喜欢做UI自动化,主要有以下

几个原因。

1)企业中的管理者大多不懂技术,但为了凸显自己很懂技术所以就会去选择一个大家都在做

的,而且框架相对多,最好下手的切入点。

2)管理者大多不懂测试,几乎除了测试以外所有行业的人都可成为管理者(包括卖水果的,

破产的等),所以对他们来讲,最接近模拟用户操作的UI自动化成为了首选。

3)测试行业的从业人员大多技术能力不高,同时也认为UI自动化就是自动化和技术的全部,

所以就一头钻进UI自动化中。

有人会问前面两点仅仅是那么“单纯”的原因吗,当然不是,企业人员这样做还有一个很大的

动力——KPI。为了去争功劳去忽悠更上面的老板从而牟取“暴利”,谁都会去挑软柿子捏吧,UI

自动化就是其中的一个。而第三点在本章后面还会提到,测试人员相对宽松的要求促使企业对测试

不重视,甚至认为任何一个人都可以做测试。所以我也一直说一句话——“测试人员老是抱怨薪资

低,抱怨企业不重视,首先先看看自己是不是正确地理解测试了,自己是不是以正确的态度对待测

试了。自己都不明白,不知道怎么去做,让别人来重视自己,如何做得好”。

不难看出,UI自动化在各个企业就是最好捏的柿子。当然我需要明确一点的是,最好捏的柿子

并不代表就很容易去做,UI自动化要做得好,无论对于设计模式、代码架构、团队合作、测试策略

等各个方面都是有极高要求的。

当然这并不在本章节里讨论,本章只要知道UI自动化是各个公司拿来换取KPI的上古神器就足

够了。那下面的测试人员们自然也为了生存只要去做,所以才有很多测试人员抱怨自己什么都不

懂,却要做这个做那个。其实我想说的是,这不是废话吗,你不做,哪里来的KPI,没有KPI,你

的主管怎么交差?

最后讲一下根本问题,即为什么测试人员那么热衷于UI自动化,以上所有的论点都能很完美

地套用在测试人员身上,除了这些还有如下原因。

1)若是在做黑盒测试,那么UI自动化最贴近黑盒,可模拟用户操作。

2)若不会代码,Monkey只要跑一个命令即可。

3)公司不给代码,我怎么办呢?谁教教我?

4)UI易出成绩,为了成为领导我也是要好好拼一下的。

88

大话APP测试2.0 ——移动互联网产品测试实录

5)移动无线的自动化就是UI自动化,不要说我坐井观天好么?你们其实就是在嫉妒我。

当然还有很多理由,我不一一列举了,测试行业到现在,从各个方面都能够散发出一种屌丝气

息,真不知道这样怎么让企业,让整个IT行业去重视呢(叹气),关键是很多人还真就觉得自己已

经到了世界顶峰一样,这莫名的优越感不知何处而来。

我们言归正传,从上面的理由来看,其实测试人员那么多人喜欢去做UI自动化不是没有道

理,反而显得那么顺理成章。但总体来讲就还是我上面说的,这都是相辅相成的,但凡测试人员

自己要求高点、对测试的理解正确点、对技术有点追求,那么整个行业至少肯定比现在要好。

但是,有个很奇怪的现象,Android的UI自动化的从业人员远远比iOS的UI自动化的人员多,原

因很露骨。

1)我没有钱买Macbook。

2)我没钱买Apple Developer。

3)公司不给配Mac。

4)我买不起iPhone。

5)我不会配置Xcode导致我Instruments也启动不了。

6)我不会写JS。

不一一列举了。大家会发现虽然测试人员都很喜欢UI自动化,但是又有各种理由来证明自己做

不了iOS的UI自动化。

2.2  我们为什么不做UI自动化

很多读者其实看到标题既有“我们为什么不做UI自动化”又有“我们为什么做UI自动化”,

那到底应该不应该做UI自动化,就如同很多测试人员问我“不做自动化那么还做什么呢?”,我

想说的是很多事情不是除了1就是0,除了好就是坏,除了对就是错的。这也就是为什么我一直

强调我们去判断问题的时候要先清楚上下文,否则就是在胡说。那么这里来看一下“不做UI自动

化”的上下文是什么。

2.2.1  原因一:测试大多喜欢伸手

在很多测试群中常看到十个测试九个是伸手党。以Appium为例,看看测试人员常见的伸手

问题。

1)Windows、Mac、Linux环境怎么搭建?

2)Node.js安装怎么卡住了?

3)Appium Server怎么报500了?

89

第2章  移动测试的伪银弹——UI自动化

4)Appium大家都用什么语言写用例?

5)大家做UI自动化用不用Appium?

6)谁有Appium入门文档?

当然肯定不止这些问题,但我想表达的是如果要去做UI自动化,那么需要依靠的还是测试人员

本身。而现在的测试先不说伸手不伸手,在问问题之前都不问清楚上下文就问,注定这些测试是无

法做好测试技术的,与其是这样,那么还不如不要做UI自动化。

先来仔细看看上面的问题,简单回答一下。

1)Windows、Mac、Linux环境怎么搭建?

  Monkey:学习一门语言或者工具,参考官方文档。

2)Node.js安装怎么卡住了?

  Monkey:作为一个技术人员,可以翻墙查询。

3)Appium Server怎么报500了?

  Monkey:先学会怎么提问再提问。

4)Appium大家都用什么语言写用例?

  Monkey:别人用什么语言和你有什么关系呢?问问题要有上下文,否则问问题和回答这

个问题都在浪费时间。

5)大家做UI自动化用不用Appium?

  Monkey:同上回答。

6)谁有Appium入门文档?

  Monkey:编写Appium在GitHub上面Wiki的人及Testerhome翻译文档的人员已累死……

接着介绍上下文的事情。我们问一个问题首先要做好几个准备。

1)基础的看过相关的国外国内的文档。

2)描述清楚问题相关的一些环境和客观情况,就如同去汇报一个bug一样。

3)自己是否做过了相关的调研。比如查看过了Stack Overflow,但是现在还有什么疑问等。

很多测试上来就问“Appium好不好用”“自动化用什么工具”,这些问题根本不存在任何意

义。也许对方做的是一个金融软件,你做的是一个社交软件。对方团队有100人,你只有自己。对

方有很强的技术能力,而你什么都不会。对方可能除了UI自动化,其余的测试流程和平台都很完善

了,而你就想着靠UI自动化去节省人力。在什么都不清楚的情况下就去问问题,然后得到的答案有

意义吗?只会误导罢了。

如果公司有这样的测试,那么先不论技术如何,在学习方式和做事态度都有问题的情况下,那

么自然不要去做什么UI自动化了,做也是做不起来的。

2.2.2  原因二:公司没有人懂得分层测试的理念

若公司没有人懂分层测试的理念,那么整个公司就会完全地扑在UI自动化上面,那么这样

90

大话APP测试2.0 ——移动互联网产品测试实录

的公司也没有必要去做移动互联网的UI自动化。在移动互联网的测试中,我们策略不在于将所

有的风险都放在UI上,而是需要针对不同的层面去使用不同的技术从而从各个点去保证产品的质

量。如果连这些都不知道或者没有这个意识的话,那么UI自动化也是做不起来的,也许有人会说

“UI自动化不要做,那么除了UI自动化还有什么?”这个其实都会分散在其他各个章节,这里简单

列举几个。

1)服务于应用的平台。

 z  Hybrid或者H5 App对应的Service监控和巡检平台,保证服务实时的稳定,并具有报警

机制。

 z  数据搜集机制,线上功能使用率,crash日志,性能数据等搜集,持续对应用的体验和性能

做分析和优化。

2)持续集成平台。

 z  服务的接口自动化测试。

 z  日常的编译打包、安装卸载、执行Monkey测试等。

 z  核心功能的回归测试。

 z  静态/动态代码扫描。

 z  日志明文的正则扫描等。

3)应用细分的测试。

 z  Hybrid应用的细分。可以将WebView部分做成Web UI自动化,如果有自定义容器和内嵌

SDK,那么就需要做相对应的JS接口自动化和SDK暴露的接口自动化。

 z  必要的时候,直接使用JUnit或者OCUnit调用客户端发出请求的方法来做接口自动化测试。

当然,详细可参考本书其他各个章节,这里仅列举其中的一部分,但仅仅这些相对也是很大的

一个工程。如果没有这些,仅仅靠自动化或人工的UI功能自动化测试根本无法在现在的移动互联网

中保证产品质量。

2.2.3  原因三:大部分测试并不知道什么是自动化

简单来讲,其实就是现实与理想真的差得很远。很多人写个DEMO,用IDE跑一下就认为自己

在做自动化了。我们真正想要做的自动化是上了持续集成或者某个平台,并且能够稳定地在多

个迭代的项目中经过考验的。在此中间,会有很多在做DEMO时考虑不到的地方。我举些例子

来讲。

1)做DEMO面对的case只是少量的,做自动化需要考虑用例的管理、集合运行等。

2)做DEMO在IDE上面运行即可,做自动化需要去监控SVN或者Git的代码库。需要去使用命

令去实现所有的自动化行为。

91

第2章  移动测试的伪银弹——UI自动化

3)做DEMO只需考虑串行的情况。做自动化需要考虑并行的情况,比如多台机器的执行、任

务并行触发的情况。

4)做DEMO只需跑通流程即可。做自动化更多地需要去考虑异常的情况。需要从代码上去

catch住各种异常情况,去适应不同版本、不同ROM的机型,去检查手机是否连接正常、是否死

机等情况。

5)做DEMO面对的仅仅是一个裸的工程。做自动化时会面对一个有外部依赖库和复杂逻辑的

项目。测试工程的创建、管理都变得不那么容易,更不要说用例的编写以及稳定性了。

6)做DEMO面对的肯定是一个native的工程,最多也就是个带有原生WebView的工程。而自

动化需要面对的大多是很复杂的Hybrid工程,并且还拥有很多自定义的WebView容器或者组件的

应用。

到这里为止,你还觉得你会做自动化吗?你做的真的就是自动化吗?如果你或你的团队没有丰

富的经验和扎实的技术基础,那么去做UI自动化也是投入产出比很低的一件事,按照目前移动互联

网发展的速度,还不如不去做。

那么来总结一下,如果一家公司没有分层测试的意识,测试代码基础不扎实,对被测对象的实

现也不够了解,甚至拿不到被测对象的代码,同时学习方法和做事态度又欠妥,公司内也没有

任何保证质量的基础流程和平台,那么请问有任何一个理由需要去做UI自动化吗?我的答案就是

没有。

2.3  我们为什么要做UI自动化 

我一直强调我们讨论问题要有前后文,要基于实际的场景。那在合适的团队、合适的企业中自

然可以去做UI自动化测试以提升测试效率,何乐而不为?不过前提是你或者你的团队克服了上面所

说的那些问题,否则就是在给自己添堵。

我曾经在各个大会上都提到在移动互联网的项目中不能没有持续集成的帮助,没有持续集成

平台支持的项目会让人感觉支离破碎和力不从心。前互联网时代如同玩星际争霸,不停地堆人口

往前线上冲去打败对手,去解决问题。而移动互联网时代更多的像WCG的星际魔兽的比赛,我

们需要用好每个人,堆人的战术已经一去不复返了。换而言之,移动互联网的团队成员少已经是

一种现状,一种趋势,我们要做的就是自己在不同的阶段面临不同的问题使用不同的技术手段去

解决。说到持续集成也许很多人想到的就是UI自动化,但并非仅此而已,后续的持续集成的章节

会详细讲述这部分内容。当然UI自动化在持续集成中也扮演着非常重要的角色,使用得当,它

就如同一名优秀的卫士随时告知我们项目的现状和问题所在,否则它会是一个青春期的孩子,

让你痛苦不堪。

不过在详细讨论UI自动化有哪些用途之前先强调一点,UI自动化在移动互联网项目中的定位并

非像很多人想的那样可以大大减少人力或者说大量地减少手动测试的用例。在移动互联网中UI自动

92

大话APP测试2.0 ——移动互联网产品测试实录

化更多的是作为一个辅助的角色,首先它是一个UI的自动化,其次它往往不可能100%去覆盖UI的

功能验证,更多的是辅助做兼容性、压力、回归等测试,所以回归本章的中心思想,UI自动化在移

动互联网并非银弹,但同时没有UI自动化也是万万不能的。

我曾经去过高通、阿里云OS、小米等OTT部门,几乎每个部门都是被大量的电子板和电视机

所围绕(顺便提一句,我曾经自己也做过两个月的OTT,当初PPTV最早的Android盒子就是我负责

测试的)。做OS的部门都有一个共同的特点——24小时执行Monkey Test。Monkey Test虽然天

生是一个Random的测试工具,但还是一个UI自动化工具。大部分公司也对这个工具做了二次开

发让其可以在Random的同时支持深度或广度遍历,大大提升Random测试的效率。不得不说,

在OTT的测试过程中不仅仅要关注功能,更多的关注还有WiFi的信号、USB的使用、板子的发热

情况以及OS中framework层面的互相兼容和稳定性。那么这个时候我们的压力和性能测试就不

可或缺,虽然富士康工厂中会使用机械臂去进行相关的测试,但大部分公司还是会使用软件层面

的UI自动化工具来模拟测试。面对这类产品和需求,UI自动化就变得不可或缺。但他们不是盲目

地去做UI自动化,他们会制定自己的策略和目标,使用UI自动化手段去检查产品是否超出了某些

质量标准。

在我走访的很多公司中,大部分公司已经开始陆续让开发投入单元测试的怀抱中了,不过效

果并非我们想的那么好。原因无非就两个,其一是大部分的开发的确有着不错的技术,但他们对

单元测试并不熟悉。其二是在移动互联网的项目中往往feature都来不及完成,也没有空闲去再编

写单元测试。单元测试在项目中扮演的角色更多的类似于代码层面的Smoke Test(冒烟测试),

这里讲个笑话,曾经我在测试OTT的时候,一个电子板由于使用时间过长真的冒烟了。此时,功能

层面的Smoke Test,UI自动化会最先用到。他们经常使用UI自动化来做移动互联网应用的Smoke 

Test,这些Smoke Test的颗粒度一般不会很细,主要是保证了应用的主要功能路径可以使用即

可,主要用到的框架有Robotium(Java)、uiautomation(JS)、Calabash(DSL)、Appium

等。框架的详细原理和使用会在本章其他小节中分析,不在这里一一介绍了。由于移动互联网项目

的迭代周期快,需求变化频繁,所以也有很多公司项目组使用Calabash框架进行Smoke  Test,

BDD模式使得需求更好地用例化,同时编写DSL的成本也会比直接编写代码低。Smoke Test必

须结合持续集成一起进行运作才能够真正产生我们要的效果,在这种情况下,UI自动化就很有必

要去做。

在《大话移动APP测试》这本书中我曾经这样说过:“我们在移动互联网中的测试工作几乎是

接近神的工作,为什么这样说呢?因为我们只需要用一个多月的测试时间就要去保证用户几年的使

用质量”,相信这点很多测试人员已经深有体会了。在测试过程中我们可能需要模拟多次的操作来

检测产品到底有没有功能或性能上的问题。比如某大型金融互联网公司中的扫码支付和声波支付,

我们会需要去模拟这样的交互测试几千次以查看功能是否正常,包括监测过程中内存、CPU等数据的

变化从而保证产品的稳定性。曾经出现过两个很典型的问题,但仅仅在一些极限情况下才会出现。

曾经使用Android的Fragment做了一个侧边栏的功能,使用了UI自动化的方式进行了Fragment

93

第2章  移动测试的伪银弹——UI自动化

功能的多次打开关闭。最后惊讶地发现Fragment的侧边栏整个都变成了白屏,整个功能栏都不再显

示了。问题最终定位在内存溢出导致Fragment某些功能无法绘制了。

类似这样的情况也许还有很多,但在测试过程中或者测试用例的设计过程中都很难直接覆盖到

这些极限情况。哪怕我们能够设计出这样的用例,但也很难通过模拟或者人工的方式实现最终的

效果。所以这种情况下,必须通过UI自动化来协助我们(当然,也可以通过机器人,Appium就有

Appium Robot,真的Robot!就如同前几年很多OS或者芯片厂商使用机械臂一样的效果)。在这

种情况下,我们就必须去做UI自动化。

很久以前微软就一直存在一种测试叫做BVT(Basic Verify Testing),每个代码模块都有对应

的少量的单元测试用例进行验收,验收通过之后自动Check  in代码。在移动互联网的研发项目中,

BVT也不可缺少,但不仅仅只是单元测试。也许你们现在还在使用Ant编译打包,也可能已经使用

了Maven和Gradle,但无论哪一种,我们往往都需要在开发人员每次Check  in之后做如下的BVT工

作,当然这一切都应该交给Jenkins。

1)编译打包。在保证远程库的依赖包(Maven、Gradle、Cocoapods等)都是最新的情况

下,进行编译打包,保证开发的代码每次Check  in都能够正常地打出测试或开发包。这里要强调

一点,企业最终发布的包一般不可能都是测试直接编译打包的,而是由专门的开发商负责或者打

包平台负责,此时我们这里的BVT需要从打包脚本或者命令上与最终打包平台的命令脚本保持

一致。

2)执行核心功能用例。编译打包很多时候还不足以满足我们的要求,还要有一些UI自动化来

保证开发人员每次Check  in之后的包的基本核心功能是可用的。由于移动互联网的快速迭代和变态

的需求变化,所以我在之前的实践中选择了BDD框架——Calabash,具体的实践详细可参见本章

的Calabash原理和落地章节。

BVT的存在会让开发人员进入前所未有的紧张状态,他们需要变得对每次代码的Check  in都特

别谨慎,这并不是什么坏事。在移动互联网的项目中,一天可能会有很多次的代码的Check  in,但

并不是每次Check  in测试人员都会去进行测试。一旦某次的测试包出现了无法正常打包或者Crash

等问题的话,团队还要花时间去追溯问题的源头从而进行解决,虽然并不会花太长的时间,但放眼

整个项目,就会浪费很多时间,而BVT的存在可以很好地解决这类问题,在第一时间将问题暴露出

来。在这种情况下,基于Jenkins的UI自动化就很有必要去做。

2.4  你做的是伪UI自动化吗

需要做UI自动化的地方还有很多,上面所说的仅仅是其中很小的一部分。但不得不说的一点

是,其实很多测试人员做UI自动化做了很久,但一直做的只是“伪UI自动化”。以下这些都不能称

为真正的UI自动化。

94

大话APP测试2.0 ——移动互联网产品测试实录

1)通过IDE运行自动化测试用例。

2)没有持续集成平台的支持。

3)项目过程中自动化用例或者平台环境一直需要人为的介入维护。

4)代码没有结构、抽象可言,维护艰难。

在移动互联网时代,要做UI自动化真的会比以往任何时候都困难。

1)我们需要面临不同ROM、不同系统、不同交互的挑战。

2)我们需要面临多台机器挂载之后ADB不稳定的挑战。

3)我们需要面临各种自定义控件和自定义WebView容器的挑战。

4)我们需要面临Hybrid以及各种新技术所实现的不同APP的挑战。

5)我们需要面临因为网络不稳定而出现的各种异常的挑战。

如果真的想要做好一套UI自动化框架,最终的目的就是能够稳定地去执行我们的测试,

从而第一时间给出问题的所在,这才是我们想要的。为了更好地进行界面的解析而要去优化

uiautomatorviewer的逻辑,我们为了保持ADB的稳定而要二次开发ddmlib,为了实时掌握被测机

器的状态和数据又不对USB造成太大的压力,而去编写Agent让消息能够通过网络的方式在PC

和Device之间更好地传输。为了更快速地编写用例和维护,引入了行为驱动、数据驱动以及

Page Object等各种模式。当在一台机器上挂载一台手机时,执行为数不多的用例时的确不会

存在太多的问题,但一台机器这三个维度都增长几倍之后,那么我们需要去解决的问题就变得

极其复杂了。

UI自动化要深入的话涉及的东西太多了,不多解释,大家若想更多了解,可以Google或上我

们的社区Testerhome.com。一个人的能力毕竟有限,所以我才希望每个人都能无私地去奉献自己所

学,这样大家才能一起进步,行业才会更好地发展。

2.5  UI自动化框架

2.5.1  初探Calabash-Android

现在测试行业也有很多的概念产生,比如MBT、ATDD、BDD等。也许大家觉得这些概念在

行业中的使用还不够广泛,但实际上还是有不少企业运用到了项目中去。在BDD中有一个很著

名的框架——Cucumber,但这里不介绍,而是讲解基于Cucumber的移动互联网BDD框架——

Calabash。

Calabash是跨平台的一个移动测试UI自动化框架,支持Android版本的GitHub地址:https://

github.com/calabash/calabash-android。当然,同样的遵循我的原则,在官方WiKi上面描述

的我就不多讲了,不要抱怨我说得不够基础。先来看一下calabash-android的架构图,如下

图所示。

95

第2章  移动测试的伪银弹——UI自动化

在框架图上可看出calabash分成两部分,一部分是Developer computer,也就是我们的PC,

另一部分是Device/Emulator,也就是我们的手机或者模拟器。上图中其他信息如下。

1)Step Definitions:calabash自己封装了一部分通用的步骤,Features可以调用这些通用的

步骤从而完成自己的自动化操作,同时也支持自己自定义的步骤。

2)Features:延用cucumber的features,可以理解为就是界面自动化的测试用例,能调用在

Step Definitions里定义的步骤。

3)Instrumentation  Test  Server:这是一个APK,在calabash运行时可以看到这个Test 

Server的APK每次都会被安装。这个server基于Robotium框架做了封装,这里需要重点提醒的是目

前calabash-android的版本合入的是robotium4.x的jar包,如果要使用最新的5.x的jar包,那么需

要自己重新对calabash修改之后再重新编译。

4)Your APP:这里指的就是你的被测应用,不过使用calabash需要对你的应用做一些修改,

下文会提到。

安装方面的事情我就不多说了,由于是RubyGems安装,所以在各种环境(Windows、Mac、

Linux、虚拟机等)下肯定有很多坑,还请各位读者自己搜索进行相关问题的解决方案。不过我

个人建议大家安装Ruby的1.9.2版本,2.0及以上版本我在安装使用时碰见了各种奇怪的问题,具

体安装步骤可参考https://github.com/calabash/calabash-android/blob/master/documentation/

installation.md。

为了提高Ruby安装源在国内的访问速度,可以使用如下的命令来切换源到淘宝的镜像服

务器。

$ sed -i -e ‘s/ftp\.ruby-lang\.org\/pub\/ruby/ruby\.taobao\.org\/

mirrors\/ruby/g’ ~/.rvm/confi g/db

安装完毕之后可以通过如下的命令查看calabash-android的版本。

~ monkey$ calabash-android version

0.4.22.pre4

$ sed -i -e ‘s/ftp\.ruby-lang\.org\/pub\/ruby/ruby\.taobao\.org\/

mirrors\/ruby/g’ ~/.rvm/confi g/db

~ monkey$ calabash-android version

0.4.22.pre4

96

大话APP测试2.0 ——移动互联网产品测试实录

接着来生成calabash-android的初始化文件夹,在终端输入:

calabash-android gen

可以看到文件夹已经被初始化,文件夹如下显示。

整个目录结构如下。

这样测试环境所要的文件算是准备完全了。在这里使用ContactManager.apk作为被测应用。

这个应用可以在Android的Sample Project里面找到并添加为测试工程。如下图所示。

calabash-android gen

97

第2章  移动测试的伪银弹——UI自动化

添加完之后为了让calabash-android的Test Server和我们的被测试应用能够通信从而实现自

动化,需要在AndroidManifest.xml中添加如下权限。

<uses-permission android:name=”android.permission.INTERNET” />

接着让我们来写第一个DEMO的用例。假设我们的测试用例想做如下操作。

1)打开这个应用。

2)单击 Add Contact 按钮。

3)添加 Contact Name 为 hello。

4)添加 Contact Phone 为 13817861875。

5)添加 Contact Email 为 [email protected]

6)保存联系人。

先打开features文件(这里强烈推荐Sublime Text和Atom这两个代码编辑器),按照如下的代

码来编写features。

Feature: Login feature

Scenario: As a valid user I can log into my app

When I press “Add Contact”

Then I see “Target Account”

Then I enter “hello” into input fi eld number 1

Then I enter “18621519900” into input fi eld number 2

Then I enter “[email protected]” into input fi eld number 3

When I press “Save”

Then I wait for 1 second

Then I toggle checkbox number 1

Then I see “hello”

这样第一个用例就完成了。我们还需要对ContactManager做一下修改,因为如果没有账号的

话单击save按钮会报错。我们需要对ContactAdder类中的createContactEntry方法增加一个非空的

判断,进行如下修改。

ArrayList<ContentProviderOperation> ops = new ArrayList<ContentProv

iderOperation>();

if(mSelectedAccount != null ) {

ops.add(ContentProviderOperation.newInsert(ContactsContract.

RawContacts.CONTENT_URI)

. w i t h V a l u e ( C o n t a c t s C o n t r a c t . R a w C o n t a c t s . A C C O U N T _ T Y P E ,

<uses-permission android:name=”android.permission.INTERNET” />

Feature: Login feature

Scenario: As a valid user I can log into my app

When I press “Add Contact”

Then I see “Target Account”

Then I enter “hello” into input fi eld number 1

Then I enter “18621519900” into input fi eld number 2

Then I enter “[email protected]” into input fi eld number 3

When I press “Save”

Then I wait for 1 second

Then I toggle checkbox number 1

Then I see “hello”

ArrayList<ContentProviderOperation> ops = new ArrayList<ContentProv

iderOperation>();

if(mSelectedAccount != null ) {

ops.add(ContentProviderOperation.newInsert(ContactsContract.

RawContacts.CONTENT_URI)

. w i t h V a l u e ( C o n t a c t s C o n t r a c t . R a w C o n t a c t s . A C C O U N T _ T Y P E ,

98

大话APP测试2.0 ——移动互联网产品测试实录

mSelectedAccount.getType())

. w i t h V a l u e ( C o n t a c t s C o n t r a c t . R a w C o n t a c t s . A C C O U N T _ N A M E ,

mSelectedAccount.getName()).build());

} else {

ops.add(ContentProviderOperation.newInsert(ContactsContract.

RawContacts.CONTENT_URI)

.withValue(ContactsContract.RawContacts.ACCOUNT_TYPE, null)

.withValue(ContactsContract.RawContacts.ACCOUNT_NAME, null).build());

}

if (mSelectedAccount != null) {

// Ask the Contact provider to create a new contact

Log.i(TAG,”Selected account: “ + mSelectedAccount.getName() + “ (“ +

mSelectedAccount.getType() + “)”);

} else {

Log.i(TAG,”No selected account”); }

接着编译出ContactManger.apk文件,把apk放在和features文件夹同一级的目录下,使用如

下命令运行。

calabash-android run ContactManager.apk

来看一下运行的日志。

Feature: Login feature

Scenario: As a valid user I can log into my app #features/

my_fi rst.feature:3

3135 KB/s (556639 bytes in 0.173s)

3315 KB/s (26234 bytes in 0.007s)

When I press “Add Contact” # calabash-android-0.4.21/

lib/calabash-android/steps/press_button_steps.rb:17

Then I see “Target Account” # calabash-android-0.4.21/

lib/calabash-android/steps/assert_steps.rb:5

Then I enter “hello” into input field number 1 # calabash-

android-0.4.21/lib/calabash-android/steps/enter_text_steps.rb:5

Then I enter “18621519900” into input field number 2 #

mSelectedAccount.getType())

. w i t h V a l u e ( C o n t a c t s C o n t r a c t . R a w C o n t a c t s . A C C O U N T _ N A M E ,

mSelectedAccount.getName()).build());

} else {

ops.add(ContentProviderOperation.newInsert(ContactsContract.

RawContacts.CONTENT_URI)

.withValue(ContactsContract.RawContacts.ACCOUNT_TYPE, null)

.withValue(ContactsContract.RawContacts.ACCOUNT_NAME, null).build());

}

if (mSelectedAccount != null) {

// Ask the Contact provider to create a new contact

Log.i(TAG,”Selected account: “ + mSelectedAccount.getName() + “ (“ +

mSelectedAccount.getType() + “)”);

} else {

Log.i(TAG,”No selected account”); }

calabash-android run ContactManager.apk

Feature: Login feature

Scenario: As a valid user I can log into my app #features/

my_fi rst.feature:3

3135 KB/s (556639 bytes in 0.173s)

3315 KB/s (26234 bytes in 0.007s)

When I press “Add Contact” # calabash-android-0.4.21/

lib/calabash-android/steps/press_button_steps.rb:17

Then I see “Target Account” # calabash-android-0.4.21/

lib/calabash-android/steps/assert_steps.rb:5

Then I enter “hello” into input field number 1 # calabash-

android-0.4.21/lib/calabash-android/steps/enter_text_steps.rb:5

Then I enter “18621519900” into input field number 2 #

99

第2章  移动测试的伪银弹——UI自动化

calabash-android-0.4.21/lib/calabash-android/steps/enter_text_steps.rb:5

Then I enter “[email protected]” into input fi eld number 3

# calabash-android-0.4.21/lib/calabash-android/steps/enter_text_steps.

rb:5

When I press “Save” # calabash-

android-0.4.21/lib/calabash-android/steps/press_button_steps.rb:17

Then I wait for 1 second # calabash-android-0.4.21/

lib/calabash-android/steps/progress_steps.rb:18

Then I toggle checkbox number 1 # calabash-android-0.4.21/

lib/calabash-android/steps/check_box_steps.rb:1

Then I see “hello” # calabash-

android-0.4.21/lib/calabash-android/steps/assert_steps.rb:5

1 scenario (1 passed)

9 steps (9 passed)

0m28.304s

就如上文说到的,通过日志能够看到每次运行测试用例之前都会安装两个apk。Calabash的日

志中也分三种颜色。

1)绿色:表示执行成功的用例步骤。

2)红色:表示执行异常的用例步骤。

3)灰色:表示因为各种原因造成没有执行的用例的步骤。

从上面的例子中我们能够看出calabash的日志还是显示得很全面的,包括每个步骤的定义,每

个步骤对应的封装的steps以及最终使用的时间等。不过我相信程序员还是更关心它运作的原理以

及在实际项目中的使用情况。接下来对此进行说明。

2.5.2  解析calabash-android

 首先需要通过上一节中提到的GitHub的地址进行calabash-android源码的下载,然后一个一

个来解决疑惑。

疑惑一:features中的steps原本是定义在什么地方的,又是怎么定义的。

我们下载源码之后可以在/calabash-android/ruby-gem/lib/calabash-android/steps下找到如

下文件夹,其实从文件的命名中不难看出这就是定义步骤的地方。如下图所示。

calabash-android-0.4.21/lib/calabash-android/steps/enter_text_steps.rb:5

Then I enter “[email protected]” into input fi eld number 3

# calabash-android-0.4.21/lib/calabash-android/steps/enter_text_steps.

rb:5

When I press “Save” # calabash-

android-0.4.21/lib/calabash-android/steps/press_button_steps.rb:17

Then I wait for 1 second # calabash-android-0.4.21/

lib/calabash-android/steps/progress_steps.rb:18

Then I toggle checkbox number 1 # calabash-android-0.4.21/

lib/calabash-android/steps/check_box_steps.rb:1

Then I see “hello” # calabash-

android-0.4.21/lib/calabash-android/steps/assert_steps.rb:5

1 scenario (1 passed)

9 steps (9 passed)

0m28.304s

100

大话APP测试2.0 ——移动互联网产品测试实录

我们就拿上一节中使用的step来看看step的编写。我们可以打开enter_text_steps.rb这个文件

来看一下。

Then /^I enter “([^\”]*)” as “([^\”]*)”$/ do |text, target|

performAction(‘enter_text_into_named_fi eld’, text, target)

end

Then /^I enter “([^\”]*)” into input fi eld number (\d+)$/ do |text,

number|

end

performAction(‘enter_text_into_numbered_fi eld’,text, number)

end

Then /^I enter “([^\”]*)” into “([^\”]*)”$/ do |text, name|

performAction(‘enter_text_into_named_fi eld’,text, name)

end

Then /^I clear “([^\”]*)”$/ do |name|

performAction(‘clear_named_fi eld’,name)

end

Then /^I clear input fi eld number (\d+)$/ do |number|

performAction(‘clear_numbered_fi eld’,number)

end

Then /^I enter “([^\”]*)” as “([^\”]*)”$/ do |text, target|

performAction(‘enter_text_into_named_fi eld’, text, target)

end

Then /^I enter “([^\”]*)” into input fi eld number (\d+)$/ do |text,

number|

end

performAction(‘enter_text_into_numbered_fi eld’,text, number)

end

Then /^I enter “([^\”]*)” into “([^\”]*)”$/ do |text, name|

performAction(‘enter_text_into_named_fi eld’,text, name)

end

Then /^I clear “([^\”]*)”$/ do |name|

performAction(‘clear_named_fi eld’,name)

end

Then /^I clear input fi eld number (\d+)$/ do |number|

performAction(‘clear_numbered_fi eld’,number)

end