我知道你觉得写单元测试很麻烦,所以。。。
我们开源了一个单元测试框架,里面提供了一系列的utility,希望能帮助你更快更轻松的写单元测试,能够少写一点boilerplate code,少一点痛苦,多一点愉悦!
地址在这里:https://github.com/mogujie/natasha
这个project是怎么来的?
蘑菇街目前采用组件化的开发方式,一个app由很多个模块组成,每个模块都有单元测试的部分,然而有很多代码都是类似的。因此,为了减少重复劳动,我们花时间抽出来一个独立的project,专门做unit testing用的。
这个project能帮你做什么?
如前所述,这个project里面主要是一些单元测试都会用到的公共代码,来帮助你更快的做unit testing,减少一些boilerplate code。
说白了就是一些帮助类,里面有些帮助方法。
最核心的是以下几个:
TestBase
TestBase应该是每一个Test Class最顶层的父类,它给你提供的帮助有:
- 一个MockitoRule 成员变量,所以在你自己的Test Class里面就不用每次需要
@Mock
的时候,都定义这个成员变量了。如果你看不懂这里说的什么意思,请看文章: 安卓单元测试(九):使用Mockito Annotation快速创建Mock - 一个
CountDownLatch
,以及相应的await()
和countDown()
方法,方便你使用CountDownLatch
来测试异步代码,不用每次都自己new一个CountDownLatch
对象。默认的CountDown次数是1,你可以用resetLatch(count)
来设置次数。如果你看不懂这里这的是什么意思,请看文章: 安卓单元测试(十一):异步代码怎么测试 - 读取资源文件的方法:
readResource(file_name)
把你的资源文件放在src/test/resources
文件夹下面,然后通过这个方法就能读出来。比如你有一个文件名为:person.json
,放在src/test/resources
文件夹下面,那么readResource("person.json")
会把person.json
的内容读出来,返回String。 - 根据我的经验,一般来说,你的资源文件里面是Json String,经过上面的方法读出来以后,如果你想变成Java Object,那么TestBase里面也有对应的方法:
dataFromResource(file_name, clazz)
,比如上面的例子:dataFromResource(“person.json”, Person.class)
,就会把person.json
里面的内容读出来,使用Gson变成Person类的对象。 - 一系列Assert.assert*的方法,简化你的书写,比如:
-
ae(expected, actual);
等同于Assert.assertEquals(expected, actual);
-
at(boolValue);
等同于Assert.assertTrue(boolValue);
;类似的,af(boolValue);
等同于Assert.assertFalse(boolValue);
-
ann(obj);
等同于Assert.assertNotNull(obj);
;类似的,an(obj);
等同于Assert.assertNull(obj);
-
以上是一些写TestCase最常用到的东西,TestBase给你提供了一些便捷。另外还有一些不那么常用的,这里就不缀述了。如果你觉得自己经常用到一个东西,那么可以看看TestBase里面有没有,如果没有的话怎么办呢?那当然是Fork & PR啦!
ViewTestBase
这个类一般是用来测试Custom View的,你的CustomView对应的TestClass可以继承这个类。它给你提供的辅助有
- 上面提到的TestBase的所以辅助,因为ViewTestBase是继承处TestBase的。
- 一个需要你现实的
createView()
方法,这个方法返回的View就应该是待测的View,你可以通过mTargetView获得这个View的实例。 -
child(viewId)
方法,返回这个待测的View的一个子view -
assertViewVisible(view)/assertViewGone(view)
用来assert 某一个view的visibility是VISIBLE/GONE,这两个方法需要你传一个View对象。类似的有assertChildVisible(view)/assertChildGone(view)
,这两个类只需要你传待测View的子View的id就好了。
ActivityTestBase
顾名思义,这个类是用来测试Activity的,所以你的Activity对应的测试类应该继承这个类。它给你提供的便利有:
- 上面提到的ViewTestBase和TestBase提到的所以便利,因为这个类是继承自ViewTestBase的。
- 一个待实现的
activityClass()
方法,这个方法返回的应该是你要测的Activity的Class。ActivityTestBase会自动创建这个Activity实例,并保存在mActivity field里面,你可以通过这个field,或者是getActivity()
方法获得这个Activity实例对象。如果你要自定义创建这个Activity的Intent,可以overrideactivityIntent()
这个方法。 -
assertToast(text)
assert 弹出了一个toast,内容为text
-
assertEnabled(viewId)/assertDisabled(viewId)
assert id为viewId
的View的状态是Enabled/Disabled。 -
view(viewId)
简化令人厌烦的findViewById(viewId)
-
assertViewHasText(viewId, text)
assert id 为viewId
的View上面的文字含有text
,类似的有assertViewText(viewId, text)
,这个是将text进行是否相等的对比。 -
click(viewId)
触发id为viewId的view的点击事情。 -
assertNextActivity(clazz)
assert 启动了一个类是clazz的Activity。 - 。。。。。。
再说一遍,这不是一个完整的列表,只是列了一些最为常用的。如果有漏掉的,欢迎PR补上!
怎么样使用?
目前项目已经发布到了jcenter,在build.gradle
的dependencies
里面加上
dependencies {
testCompile 'com.github.mogujie:natasha:0.6.3'
}
就OK了。
Enjoy!