架构误区系列 3:单元测试依赖外部环境
单元测试,是大家日常工作中都经常用到的第一层保证软件质量的手段。单元测试是一种白盒测试,从代码逻辑的角度,从开发的角度,去测试代码逻辑是否符合设计。最简单判断单元测试质量的标准就是覆盖率,包括行覆盖率、分支覆盖率、条件覆盖率、条件组合覆盖率等。
同时,单元测试也是 CI(Continuous Integration)重要组成,单元测试的稳定性(获得正确结果的比例)、效率(运行速度)也十分关键。但是由于各种依赖问题,在日常的研发活动中,在这两方面却经常掉链子:上千个 UT 的 case,每次跑都会随机挂几个;跑一次都要一个多小时,一天跑 20 多次才能有一两次稳定的结果。
造成上述问题的原因是什么呢?其实很简单,不是 case 数量过多(不管按照函数、代码行、分支、条件覆盖),一个应用系统有几千个 UTcase 都是正常的现象。最本质的原因就是单元测试对外部环境的依赖过多,从而由于环境不稳定造成 case 稳定性的下降,同时由于依赖中多次的网络交互导致执行效率的问题。
这里其实是一个很大的架构误区,就是没有分清楚单元测试和集成测试的区别。单元测试的目的,是保证系统内部逻辑的争取性;集成测试以及后续的功能测试、验收测试等,才应该来保证系统件交互或者端到端链路逻辑的正确性。
所以,单元测试不应该依赖任何外部环境。给个极端的指标就是:单元测试需要在没有网络的服务器上,达到 100%的通过率。这里有几点原则可以遵循:
对外的依赖,不管是缓存依赖、消息中间件依赖、下游程序依赖,都必须 mock。
对 DB 的依赖,这个是不是也可以 mock?这个可以因每个组织的情况而异。但是,从我的观点来,DB 存储最好不要 mock,因为有从 repository 到 DAO 到 DB Mapping 中间都可能出问题。所以,对于 DB 的依赖,可以遵循两点:a)用 local DB 代替实际的数据库;b)只有测试 repository 的时候依赖 DB,再上层 mock repository。
版权声明: 本文为 InfoQ 作者【agnostic】的原创文章。
原文链接:【http://xie.infoq.cn/article/4e8f0659d53e877926543f1ee】。文章转载请联系作者。
评论