可以想象,当你投入大量精力,使用Robolectric、Mockito等框架模拟出一个将数据库数据发往后台的单元测试并通过测试用例后,用户却因为切换网络等小概率场景触发了Bug,你会不会感叹我要这单测有何用?类似Android这种终端环境,其边际收益递减的临界点往往更容易达到,引入单元测试犹需谨慎。
结合上面的分析,哪些场景不适合做单元测试已经显而易见了,When is unit testing inappropriate or unnecessary? [duplicate]中一个高票回答做了如下总结:
- The code has no branches is trivial. A getter that returns 0 doesn't need to be tested, and changes will be covered by tests for its consumers.
在Definition of brittle unit tests中也有详细总结,都有一定参考价值。
此外,有了适合单元测试的场景并不代表就有适合单元测试的代码。在TDD模式中,测试先于开发,所以开发部分的代码接口往往需要经过良好的设计和定义,最好能解耦各个模块,如此开发代码将能够完美匹配测试代码。但这种开发模式往往对开发经验、设计能力要求很高。能都达成此境界的已经是TDD的行家了。然而事实是对于没有单元测试经验的开发人员而言,往往没有意识到自己写的代码“不可测试”。以下面伪代码为例:
object processObject(Object object) {
if (object == objectA) {
log.i('error 1 ....')
return object;
}
if (object == objectB) {
log.i('error 1 ....')
return object;
}
.....
return object;
}
开发人员在Debug的时候,能根据log信息快速定位问题,但对于测试来说就十分不友好了:返回值都一样。如果想要领会单元测试的优越性,短期的镇痛与适应似乎是不可避免的。
本文没有讨论TDD的各种优势,也没有讨论单元测试的最佳实践,是个人的一些总结,讨论的是单元测试的一些局限之处,或许有不足、有遗漏,又或者完全错误,欢迎拍砖。譬如,在stackoverflow上有一个关于是否值得做单元测试的问题就因为其争议性而被关闭回答,而又因为有其存在的历史意义而被一直锁定(locked)
原文转自:https://www.jianshu.com/p/1980c944e31c