3. 不要重复你的unit test
比如说你使用了一个builder模式来创建了一个类,这个builder有一个validator,来validate一些参数情况。那么这种情况,builder跟validator分开测,用各种正确的错误的参数情况去测试validator,然后测builder的时候,就不用遍历各种有效的跟无效的参数去测试了。
因为如果这样的话,到时候Validator的逻辑改了,那么针对Validator的测试跟针对Builder的测试都要修改,这个其实是重复的。这里只需要测试这个builder里面有一个Validator就好了。
4. 公共的单元测试library
如果你们公司也是组件化开发的话,抽出一个公共的单元测试类库来做单元测试,里面可以放一些公共的helper、utils、rules等等,这个可以极大的提高写单元测试的速度。
5. 把安卓里面的“纯java”代码copy一份到自己的项目里面
安卓里面有些类其实跟安卓没太大关系的,比如说TextUtils、Color等等,这些类完全可以把代码copy出来,放到自己的项目里面,然后其他地方就用这个类,这样也能部分摆脱android的依赖,使用JUnit而不是Robolectric,提高运行test的速度。
6. 充分发挥JUnit Rule的作用
JUnit Rule 是个很强大的工具,然而知道的人却不多。它的基本作用是,让你在执行某个测试方法前后,可以做一些事情。如果你的好几个测试类里面有很多的共同的 setup、teardown工作,你可能会倾向于使用继承,结合@Before、@After来减少duplication,这里更建议大家使用 JUnit Rule来实现这个目的,而不是用继承,这样可以有更大的灵活性。
比如,为了方便测试Activity的method,我们有一个ActivityRule,在跑一个测试方法之会启动target Activity,然后跑完以后自动finish这个activity。
其中一个比较有趣的用JUnit Rule实现的功能,是实现类似于 BDD 测试框架的命名方式。做单元测试的时候,你经常需要为同一个方法写好几个测试方法,每个测试方法测试不同的点。为了让命名更具可读性,我们往往会把名字写的很长,在这种情况下,如果用驼峰命名的话,需要不断切换大小写,写起来麻烦,可读性也不高。如果用下划线的话,写起来也很麻烦。如果你使用过BDD的一些框架(比如 RSpec 、 Cucumber 、 Jasmine 等),你就会异常怀念那种“命名”方式。如果你没用过的话,那种“命名”方式大概是这样的:
这里的关键是,当测试方法失败的时候,这个字符串是要能被加到错误信息里面的。我们做了个JUnit Rule来达到这个效果。做法是结合一个自定义的annotation,这个annotation接收一个String,来描述这个测试方法的测试目的。在Rule里面将这个annotation读出来,如果测试没通过的话,把这个描述性的String加到输出的error message里面。这样在批量运行的时候,一看就知道没通过的测试是测什么东西的。而测试方法的命名则可以比较随意。达到的效果如下:
如果运行失败,得到如下的结果
关于JUnit Rule的使用,大家可以自行google一下,也不难。
7. 善于利用AndroidStudio来加快你写测试的速度
AndroidStudio有很多feature可以帮助我们更快的写代码,比如code generation和 live template 。这点对于写正式代码也适用,不过对于写测试代码来说,效果更为突出。因为大部分测试代码的结构、风格都是类似的,在这里live template能起非常大的作用。此外,如果你先写测试,可以直接写一些还不存在的Class或method,然后alt+enter让 AndroidStudio自动帮你生成。
8. 不要追求完美
刚开始的时候,不用追求测试代码的质量,也不用追求完美,如果有些地方不好写测试,可以先放放,以后再来补,有部分测试总比没有测试好。 Martin Fowler说过
Imperfect tests, run frequently, are much better than perfect tests that are never written at all.
然而等你熟悉写测试的方法以后,强烈建议先写测试!因为如果你先写了正式代码,那你对这写代码是如何work的已经有一个印象了,因此你往往会写出能顺利通过的测试,而忽略一些会让测试不通过的情况。如果先写测试,则能考虑得更全面。
原文转自: http://www.infoq.com/cn/articles/mogujie-android-unit-testing