这两种方法,也是解决static method, final class/method不能mock的主要方式。
2. 尽量写出易于测试的代码
static method、直接new object、singleton、Global state等等这些都是一些不利于测试的代码方式,应该尽量避免,用依赖注入来代替这些方式。
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等),你就会异常怀念那种“命名”方式。如果你没用过的话,那种“命名”方式大概是这样的:
describe Hash do
# 一下是一个测试方法,it后面的字符串就是这个测试方法的“命名”
it "hashes the correct information in a key" do
expect(hash[:hello]).to eq('world')
end
end
这里的关键是,当测试方法失败的时候,这个字符串是要能被加到错误信息里面的。我们做了个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自动帮你生成。
原文转自:http://www.jianshu.com/p/9f7a992fe9ec