应用宝基于Robotium自动化测试(上)

1. 背景目的

应用宝项目组采用FT(Feature Team)模式,整个项目组分为多个FT,而每个FT又同时有多个需求分支在并行运作着,几乎每天都有多新特性合入主干,项目节奏快、变更频繁,且又希望能够短周期内快速地对外发布新版本,做到快速交付、持续交付。

为了支撑项目组的这种研发模式,测试侧需要在FT分支上及主干上做大量的测试,而其中在FT分支的rebase测试、合流后验证、主干灰度测试等等阶段还包括大量的重复性测试,因此有必要在这些环节加入自动化测试,以持续验证新特性未破坏原有系统。

2. 框架选择

如表1所示,对比了目前业界常用的几个可用于Android端的自动化测试框架:

表1.Android自动化测试框架对比

框架

Robotium

Espresso

UIAutomator

Appium

支持的API版本

All

8,10,15 >=

16 >

All

成熟度/活跃度

成熟/活跃

成熟/Google

较成熟/活跃

较成熟/活跃

支持的语言

Java

Java

Java

Almost Any

WebView/X5 WebView

支持/支持

不支持

不支持

支持/支持

UIAutomation

API >=18, 支持结合UIAutomation

API >=18, 支持结合UIAutomation

不支持

未知

用例执方式/adb依赖性

adb shell am

同Robotium

adb shell uiautomator runtest

Client Server发送命令模式

主要优点

1.通过id识别控件,手机适配好 2.基于Instrumentation,执行速度快、稳定性好 3.可使用Android及被测工程的API

同Robotium

跨应用支持好

1.不需要对被测应用进行修改 2.脚本支持多种语言进行编写 3.支持跨平台,可用于IOS、Android

主要缺点

1.测试apk签名需要与被测apk一致 2.跨应用能力弱

同Robotium

1.只支API>16 2.需要被测控件有 android:hint等属性

1.API4.2以下只支持Selendroid方式 2.一台MAC机只能运行一个Instrument实例

执行速度

4星

4星

4星

3.5星

稳定性

4星

4星

3.5星

3.5星

通过对比可以发现不同的测试框架各有优缺点,且基本都不能独自满足所有的测试场景,正所谓菜刀、牛刀、剪刀、指甲刀,刀刀皆有自己的用途与适用场景,我们需要根据项目情况及实际的使用场景来选择最适用的工具。

Robotium基于原生Android Instrumentation扩展而来,因此基于Robotium的测试既可以使用Robotium本身的API,还可以使用Android原生的丰富API,可扩展性更强,且基于Robotium的测试在执行速度、稳定性上有一定优势,而应用宝在手机端只有Android版本,也没有跨平台的需求,综合考虑,因此选择了Robotium框架。

3. 环境搭建

3.1 基础环境搭建

测试工程使用了Robotium,采用了的是Android Junit工程,因此需要搭建基础的Android开发环境,包含JDK、Android SDK、Eclipse+ ADT插件 + SVN插件等等开发工具,具体可搜“Android开发环境搭建”搭建基础环境。

3.2 导入测试工程

(1) 使用Eclipse导入项目;

(2) 配置Build Path;

(3) 配置keystore;

在实际项目中,如果是自家的项目,显然是不希望对被测App进行重签名的,有如下原因:

a) 每日进行测试的包众多,一一进行重签名影响效率;

b) 如微信、应用宝等应用做了签名防护措施,重签名后将导致应用部分功能不可用甚至直接无法启动。

测试工程需要与被测工程签名一致,因此测试工程需要将keystore配置成应用宝的签名。Window——Preferences——Android——Build,如图1所示,点击Browser,选择应用宝的debug.keystore签名,配置完成后,用Eclipse调试时,测试工程打出的apk即是应用宝的签名了,可以测试应用宝对外发布的任何包。

图1.Eclipse中配置自定义签名

(4) 配置编码

新导入工程后,工程可能有许多红点,此时工程任意有注释的java文件,如果注释为乱码则是因为编码不一致导致。此时需要将工程编码设置为utf-8。也可右键选择测试工程,仅设置该工程为UTF-8编码。

3.3 Eclipse设置

工欲善其事,必先利其器,测试工程使用Eclipse作为IDE,而为了编写代码可以更高效,有必要进行一些提高效率的设置。

(1) 配置输入联想

为了提高测试用例的代码编写效率,很有必要配置输入联想,在Eclipse中Preferences——Java——Editor——Content Assist配置输入联想。

图2 Eclipse中配置代码自动提示

其中,Auto activation triggers for java中默认只有.符号,即输入.时才会有代码联想出来,为了充分利用代码联想功能,需要在该输入框中把abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ这26个字母及.号输进去,这样,当键入.号或26个字母时,就会有自动提示,提高代码输入效率。

(2) 配置Eclipse的JVM参数

Eclipse的JVM默认设置参数较小,因此可能造成各种卡慢现像,而我们的开发机配置一般较高,可以通过调整JVM参数充分利用机器资源提高Eclipse运行的流畅度,修改Eclipse安装目录下的eclipse.ini文件即可,具体可参考如下配置(修改-vmargs参数后面的配置):

-vmargs

-Dosgi.requiredJavaVersion=1.6

-Xms2048M

-Xmx2048M

-Xmn656M

-XX:PermSize=512M

-XX:MaxPermSize=1024M

-XX:+UseParallelGC

-XX:CMSInitiatingOccupancyFraction=85

-Xverify:none

-Xnoclassgc

-XX:+CMSClassUnloadingEnabled

-XX:+CMSPermGenSweepingEnabled

-XX:+DisableExplicitGC

(3) 关联源码

a) 关联内引用jar包的源码

导入测试工程后,libs下的Robotium和Uiautomator两个jar使用了properties配置,默认就已关联上了sources目录下的源码,如图3所示:

图3.Eclipse中配置关联private jar

b) 关联外引用jar包的源码

关联外引用jar包的源码,这里主要关联Android SDK中的源码,右键android.jar,进入Java Source Attachment选项,关联sdk中的源码,如图4所示:

图4.Eclipse中配置关联外引用的jar

至此,不论进入的是Android SDK还是Robotium中的class类,均可以查看到其源码实现。

4. Robotium

4.1 Robotium介绍

Robotium对外主要提供以下几个类:

By: //Web元素的选择器

Condition: //接口类,用于等待

RobotiumUtils: //工具类

Solo: //对外提供各种API

Solo.Config: //Solo配置类

SystemUtils: //系统级工具类

TimeOut: //Solo配置类

WebElement: //Web元素的抽象类

其中Solo类是主要对外提供各种API的类,Solo类采用中介者模式,持有com.robotium.solo包下的其它类的的实例对象,当我们调用Solo类中的API时,实则大多数是转而调用com.robotium.solo包下其它类的方法。com.robotium.solo包下主要有以下类:

Getter: //提供控件获取相关API

ActivityUtils: //提供Activity相关API

Asserter: //提供断言相关的API

Clicker: //提供模拟点击相关的API

ScreenshotTaker: //提供截图相关的API

Scroller: //提供滚动相关的API

Searcher: //提供控件搜索相关的API

ViewFetcher: //提供控件过滤相关的API

Waiter: //提供控件等待相关的API

WebUtils: //提供Web支持相关的API

Robotium为了简化测试用例的编写,将以上的这些类都置为了protected,对外只提供Solo类,因此,在编写测试用例时,主要实例化Solo类即可

Robotium为一款支持黑盒测试也支持白盒测试的自动化测试框架,简单易用,提供了获取控件、发送点击事件、断言等等API。

主要API如表2所示:

表2.Robotium主要API

返回值

方法及说明

View

getView(String id) 根据id获取控件

ArrayList<View>

getCurrentViews()获取当前界面或弹框中所有的控件

ArrayList<T>

getCurrentViews(Class<T> classToFilterBy, View parent)获取父控件parent下所有控件类型为classToFilterBy的控件

void

clickOnView(View view) / clickLongOnView(View view)点击指定的view控件 /长按指定的view控件

void

clickOnScreen(float x, float y) / clickLongOnScreen(float x, float y)根据坐标x,y点击屏幕 / 根据坐标x,y长按屏幕

void

enterText(EditText editText, String text)在指定的editText中输入文本text

void

typeText(EditText editText, String text)在指定的editText中键入文本text

void

drag(float fromX, float toX, float fromY, float toY, int stepCount)从起始x,y坐标滑至终点x,y坐标;通过stepCount参数指定滑动时的步长

void

scrollToTop() / scrollToBottom() / scrollUp() / scrollDown()滚动至顶部 / 滚动至底部 /向上滚动屏幕 / 向下滚动屏幕

boolean

waitForView(int id) / waitForText(String text)等待指定控件出现 /等待指定文本出现

boolean

waitForActivity(String name)等待指定的Activity出现

void

takeScreenshot(String name)截图,图片名称为指定的name参数,图片默认路径/sdcard/Robotium-Screenshots/

void

finishOpenedActivities()关闭当前已打开的所有的Activity

void

goBack() / goBackToActivity(String name)点击返回键 / 不断地点击返回键直至返回至指定的Activity

ArrayList<WebElement>

getCurrentWebElements(By by)通过By根据指定的元素属性获取当前WebView的所有WebElement元素

void

clickOnWebElement(By by)通过By根据指定的元素属性点击WebElement

void

clickOnWebElement(WebElement webElement)点击指定的WebElement

void

assertCurrentActivity(String message, String name)断言当前界面是否为name参数指定的Activity,若不是将抛出一个带有message提示的Throwable异常

通过如上API文档也可以发现,Robotium框架提供的API是有限的,且也只是使用了一小部分Android的API封装而成。使用Android、Java丰富的类库我们可以开发出微信、手Q、应用宝等等众多App,同样地,我们也可以使用这些丰富的类库去扩展测试框架。

因此,选择Robotium测试框架,不只是选择的一个测试框架,而是选择的一种测试模式,即基于Android、基于Junit的测试模式。

4.2 Native控件获取与处理

(1)uiautomatorviewer

可以使用%ANDROID_HOME%\tools目录下的uiautomatorviewer.bat工具直接获取当前界面的控件结构及其id。

注:uiautomatorviewer只有在Android较高版本(4.3及以上)才能直接获取控件id值。

图5 Uiautomatorviewer查看控件

(2)处理唯一id的控件

如果当前界面该控件id是唯一的,则处理起来很简单,如下:

Button loginBtn = (Button) solo.getView("loginBtn");

solo.clickOnView(loginBtn)

(3)处理id相同的控件

在Android中,列表ListView采用的是Adapter形式,所以列表中的控件id 都是相同的。此时,需要先获取节点控件的父视图,通过父视图再查找相应的子视图。

(4)控件过滤

测试过程中最常见的方式就是控件过滤

API:getCurrentViews(Class<T>classToFilterBy, View parent)

例如想获取某一个区域内的所有文本:

ArrayList<TextView>textViews = holo.getCurrentViews(TextView.class,parentView);

其中parentView为父视图,获取parentView下所有的TextView

4.3 WebView控件获取与处理

WebElement元素获取可以通过Chrome Mobile Emulation模式获取。安装有较新版本Chrome浏览器,按F12即可进入Chrome Mobile Emulation模式。

输入H5页面链接,如:http://xxx.xxx.xxx/index.html

图6.Chrome按F12

如图6所示可以看到’电视剧’拥有class=”classify classify-tv”的唯一属性。

对于有些无法通过PC浏览器打开的H5页面,可以通过Chrome DevTools连接手机端直接进行调试。

使用DevTools需要以下前置条件:

(1)PC端需要安装Chrome 32及以上版本;

(2)USB线连接手机设备;

(3)用于browser debugging:需要Android4.0及以上版本,并安装有Chrome Android版本;

(4)用于app debugging:需要Android4.4及以上版本,并将WebView设置为可调试。

需要注意的是:PC端中的Chrome版本需要高于手机端中的Chrome版本。

App中将WebView设置为可调试,可使用如下代码设置:

if(Build.VERSION.SDK_INT >=Build.VERSION_CODES.KITKAT){

WebView.setWebContentsDebuggingEnabled(true);

}

DevTools详情介绍可参见官网:

https://developer.chrome.com/devtools/docs/remote-debugging#reverse-port-forwarding

然后,在Chrome浏览器地址栏中输入“chrome://inspect/#devices

打开应用宝,进入含有WebView的页面,例如进入娱乐TAB,如图7所示,可以看到出现了可以inspect的页面,点击’inspect‘按钮即可对该页面进行调试,如图8所示,展示了该页面的元素。

图7.Chrome中使用DevTools

图8.DevTools点击inspect后展示页面元素

知道了元素的属性后,即可调用相应API获取WebElement对象,通过By方式获取:getCurrentTxWebElements(By by);By方式支持通过classname、id、textcontent等方式,如:

holo.getCurrentTxWebElements(By.className(className));

获取到了相应的WebElement对象后,即可对Web元素进行操作:

clickOnWebElement(By by)

clickOnWebElement(WebElement webElement)

waitForTxWebElement(By by,int timeout,booleanscroll)

4.4 断言

(1)Assert中的断言

使用junit.framework.Assert包中的断言:断言条件的true或false、是否为空等等。如图9所示:

图9.Assert中的断言

(2)ViewAsserts中的断言

使用android.test.ViewAsserts包中的断言:包括断言控件是否左对齐、右对齐、父视图是否包含某子视图等等。

图10 ViewAsserts中的断言

5.跨应用(结合UiAutomator2.0)

2015年3月AndroidDevelopers团队宣布了UiAutomator2.0版本的发布,这个版本最重要的就是UiAutomator终于可以基于Instrumentation了,使用Instrumentation test runner即可运行UiAutomator,反过来,也即在基于Instrumentation的test中也能使用UiAutomator。因此测试工程可同时使用Robotium和UiAutomator进行更丰富地测试。

新版的UiAutomator随Android Support Repository发布,可通过SDK Manager下载,以2.1.0版本为例,位于如下所示的路径中:

%ANDROID_HOME%\extras\android\m2repository\com\android\support\test\uiautomator\uiautomator-v18\2.1.0

新的测试支持库基本都是基于AndroidStudio库,文件以aar结尾而非jar结尾,本小节为方便在Eclipse中介绍需要将aar转化成jar。

如图11所示,使用压缩工具打开uiautomator-v18-2.1.0.aar文件,里面的classes.jar文件即是可用于Eclipse的UiAutomator jar包。提取出该classes.jar文件并重命名为方便记忆的jar包文件,导入至使用了Robotium的测试工程即可。

图11.解压aar文件

如图12所示,应用宝在通知栏中开启了快捷工具栏,测试此功能时需要开启通知栏,并点击工具栏中的按钮,这样的操作仅通过Robotium框架是无法完成的,此时就可以结合UiAutomator来实现。

图12.应用宝快捷工具栏

UiAutomator发布2.0版本后,可以通过传入Instrumentation对象获得UiDevice对象。UiDevice.getInstance(instrumentation);

通过UiDevice对象可以完成点击Home键、打开通知栏,并通过UiDevice的findObject方法可以根据文本、资源id等等查找控件,并通过UiObject对象完成点击操作。

使用的findObject方法得到的为UiObject对象,此外也可以通过By的方式获取UiAutomator中的UiObject2对象,例如:uiDevice.findObject(By.res("com.tencent.android.qqdownloader","entry_text_1")).click();

UiAutomator2.0还有许多更丰富更强大的功能,这里就不再一一介绍,总之,通过与Instrumentation结合可以方便地在测试工程中完成跨应用的操作,进行更丰富地测试。

注:更多测试用例、测试报告、持续集成相关内容,请见下文《应用宝基于Robotium自动化测试(下)》

本文分享自微信公众号 - 腾讯移动品质中心TMQ(gh_2052d3e8c27d)

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2016-05-26

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏更流畅、简洁的软件开发方式

【开源】QuickPager ASP.NET2.0分页控件——使用示例、基本应用和查询功能

    myPage分页控件发出来之后,虽然开源了,但是没有给一个简单一点的 demo,真是漏掉了一个很重要的部分。     先说明一下使用myPage分页...

258100
来自专栏Danny的专栏

机房收费系统(VB.NET)——超详细的报表制作过程

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/huyuyang6688/article/...

31030
来自专栏偏前端工程师的驿站

JS魔法堂:定义页面的Dispose方法——[before]unload事件启示录

前言  最近实施的同事报障,说用户审批流程后直接关闭浏览器,操作十余次后系统就报用户会话数超过上限,咨询4A同事后得知登陆后需要显式调用登出API才能清理4A端...

36490
来自专栏有趣的django

一个完整的Django入门指南(二)

第三部分 Introduction        In this tutorial, we are going to dive deep into two f...

74270
来自专栏前端布道

Angular开发实践(六):服务端渲染

Angular Universal Angular在服务端渲染方面提供一套前后端同构解决方案,它就是 Angular Universal(统一平台),一项在服务...

657100
来自专栏破晓之歌

完全媲美sublime的编辑器-Atom 原

前端可视化插件神器,配合谷歌浏览器一起使用。本质是监控文件修改,实时刷新浏览器,需要安装livereload插件和node.js插件,全局刷新

96930
来自专栏CRPER折腾记

Vue 折腾记 - (10) 给axios做个挺靠谱的封装(报错,鉴权,跳转,拦截,提示)

不推荐完全copy过去,可以看看我是如何针对我这边业务; 做的一个axios的封装及实现的思路

56320
来自专栏数据小魔方

R语言笔记之——常用数据导入方式简介

因为之前旁听过几节R语言的课程,再加上自己练习数据可视化的需要(特别是可视化包——“ggplot2”),学了些R语言的皮毛。 总觉得基础没打牢,好高骛远、急于求...

35470
来自专栏mukekeheart的iOS之旅

iOS学习——iOS项目Project 和 Targets配置详解

  最近开始学习完整iOS项目的开发流程和思路,在实际的项目开发过程中,我们通常需要对项目代码和资料进行版本控制和管理,一般比较常用的SVN或者Github进行...

61170
来自专栏石奈子的Java之路

原 Intellij idea2017编辑

38160

扫码关注云+社区

领取腾讯云代金券