近期因工作需要,分析了一些Android的测试框架,在这也分享下整理完的资料。

Android测试大致分三大块:

  1. 代码层测试
  2. 用户操作模拟,功能测试
  3. 安装部署及稳定性测试

代码层测试

对于一般java代码,采用传统的Junit测试,开发人员通常会编写重要接口和函数的白盒测试代码,不做过多讨论。

但因Android的特殊运行机制(Dalvik虚拟机),其中存在Application、Activity、Service等特殊组件,而这些组件都涉及到生命周期管理的问题。

为了对这些组件进行测试,Google提供了一套针对性的测试框架,AndroidTestFramework

官方教程链接 http://developer.android.com/training/testing.html

官方api http://developer.android.com/reference/android/test/package-summary.html

其中最为常用的就是针对Activity的测试,即ActivityInstrumentationTestCase2<T>类。

继承该类后可通过getActivity()方法获取Activity的一个mock对象,从而实现各种界面元素的测试。代码如下

public class LoginActivityTest extends ActivityInstrumentationTestCase2<LoginActivity> {
LoginActivityTest mActivity;
Button btnLogin; public LoginActivityTest(){
super(LoginActivity.class);//必须实现super(testclass)
} @Override
protected void setUp() throws Exception {
super.setUp();
mActivity = getActivity();
btnLogin = mActivity.findViewById(R.id.btnLogin);
} public void testGetActivity(){
assertNotNull("can't get LoginActivity" , mActivity);
assertNotNull("can't get loginButton" , btnLogin);
}
}
 

需要注意的是,测试代码运行的线程并不是UI线程。因此如果需要对UI元素进行setText或是click之类的操作,需要通过getActivity().runOnUiThread(action)方法执行。代码如下

getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
btnLogin.click();
}
});
 

用户操作模拟,功能测试

虽然AndroidTestFramework可以帮助我们完成各种界面的测试。但是,这些代码的编写非常繁琐。而且在大部分情况下,我们需要的是一个连贯性的,在多个Activity之间存在跳转的业务流程测试。这种测试比较接近传统的白盒测试,只针对可见的UI元素进行操作,模拟用户的行为来完成测试。

Google同样为我们提供了一套专门针对UI元素的测试方案,具体可见http://developer.android.com/tools/testing/testing_ui.html

可是Google的这套UI框架仍然不是很友好。为此,我寻找了一些相对成熟的测试框架来帮助我们。经过一系列分析比较和实际代码测试,在这推荐采用Robotium开源框架做为今后一段时间内的主要业务测试框架。

Robotium介绍

Robotium是一款国外的Android自动化测试框架,主要针对Android平台的应用进行黑盒自动化测试,它提供了模拟各种手势操作(点击、长按、滑动等)、查找和断言机制的API,能够对各种控件进行操作。Robotium结合Android官方提供的测试框架达到对应用程序进行自动化的测试。另外,Robotium 4.0版本已经支持对WebView的操作。Robotium 对Activity,Dialog,Toast,Menu 都是支持的。

源码及相关资料地址:https://code.google.com/p/robotium/

Robotium具有清晰的调用方法、良好的兼容性、完善的文档和大量的实际应用案例,并且支持截屏。最为符合我们目前的实际需求。经实际测试,无需特殊配置即可兼容Jenkins系统。
下面以一段HSA项目中的实际测试代码举例。该测试用例完成从登陆、菜单选取、一直到功能界面输入验证的一个流程。

public class LoginActivityTest extends ActivityInstrumentationTestCase2<LoginActivity> {
Solo solo;
LoginActivity mActivity; public LoginActivityTest(){
super(LoginActivity.class);
} @Override
protected void setUp() throws Exception {
super.setUp(); mActivity = getActivity();//初始LoginActivity
solo = new Solo(getInstrumentation(),mActivity);//初始Robotium的主要入口,solo对象
} public void testLogin(){
//清除用户名EditText内容
solo.clearEditText(0); //输入"userName" 到用户名EditText
solo.enterText(0, "userName"); //清除密码EditText内容
solo.clearEditText(1); //输入"userPass" 到密码EditText
solo.enterText(1, "userPass"); //清除站点EditText内容
solo.clearEditText(2); //输入"siteCode" 到站点EditText
solo.enterText(2, "siteCode"); //点击登陆按钮
solo.clickOnButton("登录"); //检验当前界面为MainListActivity
solo.assertCurrentActivity("Expected MainListActivity activity", "MainListActivity"); //点击动态菜单列表中的第一项,进入下一级子菜单界面
solo.clickInList(0); //检验当前界面为SubMenuActivity
solo.assertCurrentActivity("Expected SubMenuActivity activity", "SubMenuActivity"); //点击子菜单列表中的第一项,进入功能界面
solo.clickInList(0); //检验当前界面为ReceiveActivity
solo.assertCurrentActivity("Expected ReceiveActivity activity", "ReceiveActivity"); //点击界面中的"使用当前人员"按钮
solo.clickOnButton("使用当前人员"); //输入重量
solo.enterText(1, "123"); //输入单号
solo.enterText(2, "21123456798"); //模拟软键盘,发送EditText的ACTION_DONE事件
solo.getCurrentActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
solo.getEditText(2).onEditorAction(EditorInfo.IME_ACTION_DONE);
}
}); //寻找是否有内容为"已扫描1件"的textview, 会自动等待10秒
boolean succ = solo.searchText("已扫描1件")) //判断成功
assertTrue(succ);
}
}
 

可见,Robotium通过一个solo对象来进行各种事件的模拟,代码清晰易懂,并且完全兼容原生AndroidTestFramework

安装部署及稳定性测试

安卓系统最为让人诟病的问题就是碎片化,这点在中国比较明显。大致上,2.3.X 和 4.x 的系统各占半壁江山,此外还存在大量的山寨定制系统。

因此在这推荐两款云端测试工具,Testin和百度云测试。

两个框架测试都很简单,在官网注册账号后上传apk即可,网站会用大量的真机进行安装部署和monkey测试。测试完成后会发送一份测试给注册邮箱。

Testin支持Robotium框架的代码测试,同时上传项目apk和测试apk(相同签名)即可。

Testin地址: http://www.testin.cn/

百度云测试: http://mtc.baidu.com/

其他测试框架

Monkey测试

Android SDK开发包中自带一个monkeyrunner的工具,可用来进行monkey测试。
文档地址:

Robolectric

一款基于JVM运行的Android测试框架,最大特点就是不需要启动模拟器,因此速度非常快!
目前已支持大部分原生SDK功能的测试,支持Resource,但对于一些特殊硬件上的模拟还存在欠缺。期待进一步的完善
示例代码:

// Test class for MyActivity
@RunWith(RobolectricTestRunner.class)
public class MyActivityTest { @Test
public void clickingButton_shouldChangeResultsViewText() throws Exception {
Activity activity = Robolectric.buildActivity(MyActivity.class).create().get(); Button pressMeButton = (Button) activity.findViewById(R.id.press_me_button);
TextView results = (TextView) activity.findViewById(R.id.results_text_view); pressMeButton.performClick();
String resultsText = results.getText().toString();
assertThat(resultsText, equalTo("Testing Android Rocks!"));
}
}

地址: http://robolectric.org/index.html

Google Espresso

Google于2013年10月开源的一款测试框架。据称在Google内部已通过多个项目的实际验证,并可能在未来加入到默认AndroidSDK中。
设计上接近Robotium,主要用于业务端的模拟行为测试。相较Robotium,具有更为强大的UI元素匹配寻找功能和更快的运行速度。
不过经过本人的实际使用,发现该框架的代码编写相对复杂,远不如Robotium来的轻巧。此外,该框架无法运行在默认AndroidTestFramework中(可认为是升级版),且因刚开源,缺少文档和应用案例等资料,导致测试代码编写效率相对低下,故暂时不予采用。
地址: https://code.google.com/p/android-test-kit/wiki/Espresso

Mockito

一款用于Mock测试的主流框架
地址: https://code.google.com/p/mockito/

  List mockedList = mock(List.class);
when(mockedList.get(0)).thenReturn("first");
System.out.println(mockedList.get(0));

总结

如无意外,接下来一段时间内,Android项目会采用以下的方案搭建测试框架:

  • 代码级: AndroidTestFramework + Junit
  • UI业务模拟: Robotium
  • 安装部署: Testin
  • CI: Jenkins

有兴趣的同学也可关注下Robolectric和Espresso两个框架的进展。

 
分类: Android

Android开源测试框架学习的更多相关文章

  1. [转]Android开源测试框架学习

    近期因工作需要,分析了一些Android的测试框架,在这也分享下整理完的资料. Android测试大致分三大块: 代码层测试 用户操作模拟,功能测试 安装部署及稳定性测试 代码层测试 对于一般java ...

  2. Android 开源项目及其学习

    Android 系统研究:http://blog.csdn.net/luoshengyang/article/details/8923485 Android 腾讯技术人员博客 http://hukai ...

  3. Android接口和框架学习

    Android接口和框架学习 缩写: HAL:HardwareAbstraction Layer.硬件抽象层 CTS:CompatibilityTest Suite,兼容性測试套件 Android让你 ...

  4. android开源项目框架大全:

    android开源项目框架大全: 1.多页切换TabHost9 高仿网易云音乐客户端的Home页面切换Tabhost 高仿网易云音乐客户端的Home页面切换Tabhost,并且三角形是透明的,实现方式 ...

  5. karma + phantom + mocha + sion + chai + nightwatch + selenium2(webdriver) 测试框架学习

    第三方的教程传送门 https://segmentfault.com/a/1190000004558796 karma # github https://github.com/karma-runner ...

  6. Android开源日志框架xlog

    版权声明:本文为xing_star原创文章,转载请注明出处! 本文同步自http://javaexception.com/archives/144 xlog的优点 在开发过程中,避免不了要使用日志组件 ...

  7. Android Junit测试框架

    对应用进行单元测试: 使用Junit测试框架,是正规Android开发的必用技术.在Junit中可以得到组件,可以模拟发送事件和检测程序处理的正确性. 1.配置指令集和函数库: (1)配置指令集,指定 ...

  8. C++测试利器--google test开源测试框架

    资料 偶然发现了google的测试框架gtest,马上试了下,效果挺不错,特别是对于写c++的人来说,方便很多.以前自己写c++的模块,通常是写好了模块后再另外定义些函数,然后在函数里面写测试用例来测 ...

  9. 简析Android 兼容性测试框架CTS使用

    一.什么是兼容性测试? 1)为用户提供最好的用户体验,让更多高质量的APP可以顺利的运行在此平台上 2)让程序员能为此平台写更多的高质量的应用程序 3)可以更好的利用Android应用市场 二.CTS ...

随机推荐

  1. linux遇到 软件包系统已损坏 怎么解决

    软件包系统已损坏检查您是否使用了第三方源.如果是就禁用它们,它们常常导致问题. 然后在终端中运行以下命令:apt-get install -f 如果遇到以上问题 输入以下命令可以解决 sudo apt ...

  2. 运用node的文件系统模块批量修改文件名

      如果我们需要大批量修改一个文件中的名称,比如,删除文件名中的副本时,就可以借助node的文件系统模块,快捷快速的完成. 首先建立一个js文件(changeName.js),代码如下: // 引入f ...

  3. BigInteger和BigDecimal大数操作

    有时候可能会碰到需要计算非常大的数,比如7777777777777777777777777*3333333333333333333333333333,这样的计算需要显然不能用之前的方式来进行.我们不能 ...

  4. js 一个自写的 监测类

    自从认识了jQuery后,很多页面加载入口,都放在document.ready里面.但是有时候这个觉得ready加载太慢, 这个[监测类 ]就开始产生了 效果类似这个. 每10毫秒检查一次,直到加载了 ...

  5. [SQL入门级] 上篇被移出园子首页,那这篇咱就'薄利多销'

    这个系列的博文知识回顾sql知识作的记录,温故而知新.上一篇内容达不到知识分享的层级被移出园子首页,对不住各位看官,内容简单了些.下面咱就记录多一些的基础知识,薄利多销: 控制用户权限 • 创建用户 ...

  6. C# 中的委托和事件(转载)

    引言 委托 和 事件在 .Net Framework中的应用非常广泛,然而,较好地理解委托和事件对很多接触C#时间不长的人来说并不容易.它们就像是一道槛儿,过了这个槛的人,觉得真是太容易了,而没有过去 ...

  7. 手机APP功能测试经验分享2016.06.06

    1.登录时,Android和IOS同样的操作,提示信息不一致: 2.注册等页面切换成横屏容易不兼容.把内存卡去掉,再发送图片.音频.视频容易出错. 3.Android和IOS同样的功能,同样的原型图, ...

  8. 去除表单自动填充时,-webkit浏览器默认给文本框加的黄色背景

    input:-webkit-autofill { -webkit-box-shadow:inset 0 0 0 100px #2B2B35 inset; -webkit-text-fill-color ...

  9. Welogic中的JMS

    WebLogic JMS 概述 企业消息传递系统使得应用程序能够通过消息的交换与其他系统之间进行通信.消息是包含协调不同应用程序之间通信所需信息的请求.报告和/或事 件.消息提供了提取级别,使您能够从 ...

  10. C语言----------链表的简单操作

    #include <stdio.h> #include <malloc.h> typedef struct node{ //定义节点类型 char data; //数据域 st ...