使用Robolectric进行Android单元测试

原创 2016年08月29日 14:44:30

单元测试在很多人认为是一件很麻烦的事情,然而,某一天,读了小创关于Android单元测试的一篇文章,让我鼓起了对于这个麻烦事情的勇气。

I’ve found that writing good tests greatly speeds my programming, even if I’m not refactoring. This was a surprise for me, and it is counterintuitive for many programmers…
–Martin Fowler 《Refactoring: Improving the Design of Existing Code》
<

你没有看错,这位大师竟然说能提高你的开发进度!我读书不多,不要骗我!

Martin Fowler在《重构》里面还解释了为什么单元测试可以节省时间,大意是我们写程序的时候,其实大部分时间不是花在写代码上面,而是花在debug上面,是花在找出问题到底出在哪上面,而单元测试可以最快的发现你的新代码哪里不work,这样你就可以很快的定位到问题所在,然后给以及时的解决,这也可以在很大程度上防止regression(相信QE和QA们一定很喜欢哈哈。。。),这也是个大部分程序员和测试都很痛恨的问题。

既然能提高开发速度,那我就要研究研究了!

为什么要做单元测试?

我们在写单元测试时,为了测试某个功能或某个api,首先得调用相关的代码,因此我们留下来的便是一段如何调用的代码。这些代码的价值在于为以后接手维护/重构/优化功能的人,留下一份程序猿最愿意去阅读的文档。

为什么Android 的单元测试不好做?

我们知道安卓的app需要运行在delvik上面,我们开发Android app是在JVM上面,在开发之前我们需要下载各个API-level的SDK的,下载的每个SDK都有一个android.jar的包,这些可以在你的android_sdk_home/platforms/下面看到。当我们开发一个项目的时候,我们需要指定一个API-level,其实就是将对应的android.jar 加到这个项目的build path里面去。这样我们的项目就可以编译打包了。然而现在的问题是,我们的代码必须运行在emulator或者是device上面,说白了,就是我们的IDE和SDK只提供了开发和编译一个项目的环境,并没有提供运行这个项目的环境,原因是因为android.jar里面的class实现是不完整的,它们只是一些stub,如果你打开android.jar下面的代码去看看,你会发现所有的方法都只有一行实现:
throw RuntimeException(“stub!!”);
而运行unit test,说白了还是个运行的过程,所以如果你的unit test代码里面有android相关的代码的话,那运行的时候将会抛出RuntimeException(“stub!!”)。为了解决这个问题,现在业界提出了很多不同的程序架构,比如MVP、MVVM等等,这些架构的优势之一,就是将其中一层抽出来,变成pure Java实现,这样做unit testing就不会遇到上面这个问题了,因为其中没有android相关的代码。
好奇的童鞋可能会问了,既然android.jar的实现是不完整的,那为什么我们可以编译这个项目呢?那是因为编译代码的过程并没有真正的运行这些代码,它只会检查你的接口有没有定义,以及其他的一些语法是不是正确。举个简单的例子:

public class Test {
    public static void main(String[] argv) {
        testMethod();
    }
    public static void testMethod() {
        throw RuntimeException("stub!!”);
    }
}

上面的代码你同样可以编译通过,但你运行的时候,就会抛出异常RuntimeException(“stub!!”)。当我们的项目运行在emulator或者是device上面的时候,android.jar被替换成了emulator或者是device上面的系统的实现,那上面的实现是真正实现了那些方法的,所以运行起来没有问题。
话说回来,MVP、MVVM这些架构模式虽然解决了部分问题,可以测试项目中不含android相关的类的代码,然而一个项目中还是有很大部分是android相关的代码的,所以上面那种解决方案,其实是放弃了其中一大块代码的unit
test。 当然,话说回来,android还是提供了他自己的testing
framework,叫instrumentation,但是这套框架还是绕不开刚刚提到的问题,他们必须跑在emulator或者是device上面。这是个很慢的过程,因为要打包、dexing、上传到机器、运行起来界面。。。这个相信大家都有体会,尤其是项目大了以后,运行一次甚至需要一两分钟,项目小的话至少也要十几秒或几十秒。以这个速度是没有办法做unit
test的。 那么怎么样即可以给android相关的代码做测试,又可以很快的运行这些测试呢?

写好单元测试的意义

我们经常讲“前人种树,后人乘凉”,然而在软件开发中,往往呈现出来的却是截然相反的景象,我们在绩效和指标的驱使下,主动或被动的留下来大量坏味道的代码,在短时间内顺利的完成项目,此后却花了数倍于开发的时间来维护此项目,可谓“前人砍树,后人遭殃”,讽刺的是,砍树的人往往因为优秀的绩效,此时已经步步高升,而遭殃的往往是意气风发,步入职场的年轻人,如此不断轮回。所以,为了打破轮回,从一点一滴做起吧,“树”的种类众多,作为任意一名普通的软件工程师,种好单元测试这棵树,便是撒下一片荫凉。

闲话说了这么多,下面介绍神器RoboLectric,此框架使用Android.jar,所以可以和使用测试驱动Android应用,测试只需要几秒就可以在JVM中完成,减少了devlik麻烦的工作量。
官网为:robolectric

以下以Android Studio 为例

1,环境搭建:

Gradle配置: 在build.gradle中配置如下依赖关系

dependencies {
testCompile 'junit:junit:4.12'
testCompile 'org.robolectric:robolectric:3.0'
}

通过注解配置TestRunner

@RunWith(RobolectricGradleTestRunner.class)
@Config(constants = BuildConfig.class)
public class SampleActivityTest {

}

请注意,您必须指定 constants 字段指向由编译系统产生的 buildconfig.class。robolectric使用 constants 计算使用的工具类建设项目当输出路径。没有这些配置,robolectric将无法找到您的资源或资产

在官方教程中,如果build with android studio2.0以上,可以不用设置TestArtfact ,因为编译器会默认设置,对于以下,可以按照 File Menu -> Settings -> Build, Execution, Deployment -> Build Tools -> Gradle -> Experimental.进行相关设置。

*这里要特别说明一下:假如你使用linux或者Mac电脑,需要设置一下默认JunitTest配置。Android Studio默认不设置工作目录的模块测试。可以通过编辑运行配置完成,默认-> JUnit和改变工作目录的价值module_dir美元美元。

这里写图片描述

官方对于Roboletric有一个比较比较成熟的案例在github上面,地址如下DEMO

版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

robolectric完全解析

官网地址:http://robolectric.org介绍:在android设备上跑测试用例太慢了,编译、部署、启动app要花费很多时间。Robolectric是一个单元测试框架,测试是运行在jvm上...

Android Robolectric 测试框架探究

由于工作工作需要,对Android的测试框架做了个初步的研究,这里记录下,也会记录若干参考资料和例子,方便自己以后回顾。本文主要记录了Robolectric框架的探究过程。1 简介通过实现一套JVM能...

Robolectric环境搭建——运行RobolectricSample示例工程

Robolectric简介 在android平台上运行单元测试用例需要真机或模拟器,从构建、部署、到启动应用程序通常需要好几分钟,这对于TDD来说太慢 了,也许尝试过在IDE上直接运行测试用例,但得到...

Android单元测试之 Robolectric3.0+

1、添加环境(Android Studio2.3+) // robolectric testCompile 'org.robolectric:robolectric:3.3' testCompile...

Android Studio使用Robolectric对android程序实现单元测试

关于Robolectric的单元测试

使用Robolectric对Android应用进行单元测试

介绍Robolectric主要从框架简介、框架优点、框架可行性分析,框架环境配置、框架演示、框架参考资料方面进行介绍!...

Android测试框架之Robolectric

要开始一个新项目了,奈何测试部门人不够了,只能自己写测试了。。Robolectric是封装了junit4的测试框架,我对测试不怎么了解,只有大学上的软件测试课的基础,只知道什么是白盒测试,黑盒测试,集...

Android单元测试框架Robolectric3.0介绍(二)

一 闲话单元测试 我们经常讲“前人种树,后人乘凉”,然而在软件开发中,往往呈现出来的却是截然相反的景象,我们在绩效和指标的驱使下,主动或被动的留下来大量坏味道的代码,在短时间内顺利的完成项目,此后却...

使用Robolectric做Android单元测试

首先谈谈,为什么要进行单元测试呢?理论上说,多了单元测试这一环节意味着要付出额外时间,如果开发周期不变,那么编写代码的时间必须相应缩短。这岂不是作为程序猿的我们自己给自己找麻烦,吃力不讨好吗?讲真的,...

单元测试从Mockito到PowerMock再到Robolectric的详细解析

单元测试从Mockito到PowerMock再到Robolectric
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:使用Robolectric进行Android单元测试
举报原因:
原因补充:

(最多只允许输入30个字)