我知道你觉得写单元测试很麻烦,所以,蘑菇街开源了一个安卓单元测试框架

字数 1398阅读 1459

我知道你觉得写单元测试很麻烦,所以。。。

我们开源了一个单元测试框架,里面提供了一系列的utility,希望能帮助你更快更轻松的写单元测试,能够少写一点boilerplate code,少一点痛苦,多一点愉悦!
地址在这里:https://github.com/mogujie/natasha

这个project是怎么来的?

蘑菇街目前采用组件化的开发方式,一个app由很多个模块组成,每个模块都有单元测试的部分,然而有很多代码都是类似的。因此,为了减少重复劳动,我们花时间抽出来一个独立的project,专门做unit testing用的。

这个project能帮你做什么?

如前所述,这个project里面主要是一些单元测试都会用到的公共代码,来帮助你更快的做unit testing,减少一些boilerplate code。
说白了就是一些帮助类,里面有些帮助方法。
最核心的是以下几个:

TestBase

TestBase应该是每一个Test Class最顶层的父类,它给你提供的帮助有:

  1. 一个MockitoRule 成员变量,所以在你自己的Test Class里面就不用每次需要@Mock的时候,都定义这个成员变量了。如果你看不懂这里说的什么意思,请看文章: 安卓单元测试(九):使用Mockito Annotation快速创建Mock
  2. 一个CountDownLatch,以及相应的await()countDown() 方法,方便你使用CountDownLatch来测试异步代码,不用每次都自己new一个CountDownLatch对象。默认的CountDown次数是1,你可以用resetLatch(count)来设置次数。如果你看不懂这里这的是什么意思,请看文章: 安卓单元测试(十一):异步代码怎么测试
  3. 读取资源文件的方法:readResource(file_name)把你的资源文件放在 src/test/resources文件夹下面,然后通过这个方法就能读出来。比如你有一个文件名为:person.json,放在src/test/resources文件夹下面,那么readResource("person.json")会把person.json的内容读出来,返回String。
  4. 根据我的经验,一般来说,你的资源文件里面是Json String,经过上面的方法读出来以后,如果你想变成Java Object,那么TestBase里面也有对应的方法:dataFromResource(file_name, clazz),比如上面的例子:dataFromResource(“person.json”, Person.class),就会把person.json里面的内容读出来,使用Gson变成Person类的对象。
  5. 一系列Assert.assert*的方法,简化你的书写,比如:
    1. ae(expected, actual); 等同于Assert.assertEquals(expected, actual);
    2. at(boolValue);等同于Assert.assertTrue(boolValue);;类似的, af(boolValue);等同于Assert.assertFalse(boolValue);
    3. ann(obj);等同于Assert.assertNotNull(obj);;类似的,an(obj);等同于Assert.assertNull(obj);

以上是一些写TestCase最常用到的东西,TestBase给你提供了一些便捷。另外还有一些不那么常用的,这里就不缀述了。如果你觉得自己经常用到一个东西,那么可以看看TestBase里面有没有,如果没有的话怎么办呢?那当然是Fork & PR啦!

ViewTestBase

这个类一般是用来测试Custom View的,你的CustomView对应的TestClass可以继承这个类。它给你提供的辅助有

  1. 上面提到的TestBase的所以辅助,因为ViewTestBase是继承处TestBase的。
  2. 一个需要你现实的createView()方法,这个方法返回的View就应该是待测的View,你可以通过mTargetView获得这个View的实例。
  3. child(viewId)方法,返回这个待测的View的一个子view
  4. assertViewVisible(view)/assertViewGone(view)用来assert 某一个view的visibility是VISIBLE/GONE,这两个方法需要你传一个View对象。类似的有 assertChildVisible(view)/assertChildGone(view),这两个类只需要你传待测View的子View的id就好了。

ActivityTestBase

顾名思义,这个类是用来测试Activity的,所以你的Activity对应的测试类应该继承这个类。它给你提供的便利有:

  1. 上面提到的ViewTestBase和TestBase提到的所以便利,因为这个类是继承自ViewTestBase的。
  2. 一个待实现的activityClass()方法,这个方法返回的应该是你要测的Activity的Class。ActivityTestBase会自动创建这个Activity实例,并保存在mActivity field里面,你可以通过这个field,或者是getActivity()方法获得这个Activity实例对象。如果你要自定义创建这个Activity的Intent,可以override activityIntent()这个方法。
  3. assertToast(text) assert 弹出了一个toast,内容为text
  4. assertEnabled(viewId)/assertDisabled(viewId) assert id为viewId的View的状态是Enabled/Disabled。
  5. view(viewId) 简化令人厌烦的findViewById(viewId)
  6. assertViewHasText(viewId, text) assert id 为viewId的View上面的文字含有text,类似的有assertViewText(viewId, text),这个是将text进行是否相等的对比。
  7. click(viewId) 触发id为viewId的view的点击事情。
  8. assertNextActivity(clazz) assert 启动了一个类是clazz的Activity。
  9. 。。。。。。

再说一遍,这不是一个完整的列表,只是列了一些最为常用的。如果有漏掉的,欢迎PR补上!

怎么样使用?

目前项目已经发布到了jcenter,在build.gradledependencies里面加上

dependencies {
    testCompile 'com.github.mogujie:natasha:0.6.3'
}

就OK了。

Enjoy!

推荐阅读更多精彩内容