接上篇:https://developer.aliyun.com/article/1228059?spm=a2c6h.13148508.setting.21.4a864f0e4FO91p
十、 相关观点
1. 《Java开发手册》规范
1) 好的单元测试必须遵守AIR原则
单元测试在线上运行时,感觉像空气(AIR)一样感觉不到,但在测试质量的保障上,却是非常关键的。好的单元测试宏观上来说,具有自动化、独立性、可重复执行的特点。
• A:Automatic(自动化)
• I:Independent(独立性)
• R:Repeatable(可重复)
2) 单元测试应该是全自动执行的,并且非交互式的。
测试用例通常是被定期执行的,执行过程必须完全自动化才有意义。输出结果需要人工检查的测试不是一个好的单元测试。单元测试中不准使用System.out来进行人肉验证,必须使用assert来验证。
3) 单元测试是可以重复执行的,不能受到外界环境的影响。
单元测试通常会被放到持续集成中,每次有代码check in时单元测试都会被执行。如果单测对外部环境(网络、服务、中间件等)有依赖,容易导致持续集成机制的不可用。
正例:
为了不受外界环境影响,要求设计代码时就把SUT的依赖改成注入,在测试时用spring这样的DI框架注入一个本地(内存)实现或者Mock实现。
4) 编写单元测试代码遵守BCDE原则,以保证被测试模块的交付质量。
• B:Border,边界值测试,包括循环边界、特殊取值、特殊时间点、数据顺序等。
• C:Correct,正确的输入,并得到预期的结果。
• D:Design,与设计文档相结合,来编写单元测试。
• E:Error,强制错误信息输入(如:非法数据、异常流程、业务允许外等),并得到预期的结果。
2. 为什么要使用Mock?
根据网络相关资料,总结观点如下:
1) Mock可以用来解除外部服务依赖,从而保证了测试用例的独立性。
现在的互联网软件系统,通常采用了分布式部署的微服务,为了单元测试某一服务而准备其它服务,存在极大的依耐性和不可行性。
2) Mock可以减少全链路测试数据准备,从而提高了编写测试用例的速度。
传统的集成测试,需要准备全链路的测试数据,可能某些环节并不是你所熟悉的。最后,耗费了大量的时间和经历,并不一定得到你想要的结果。现在的单元测试,只需要模拟上游的输入数据,并验证给下游的输出数据,编写测试用例并进行测试的速度可以提高很多倍。
3) Mock可以模拟一些非正常的流程,从而保证了测试用例的代码覆盖率。
根据单元测试的BCDE原则,需要进行边界值测试(Border)和强制错误信息输入(Error),这样有助于覆盖整个代码逻辑。在实际系统中,很难去构造这些边界值,也能难去触发这些错误信息。而Mock从根本上解决了这个问题:想要什么样的边界值,只需要进行Mock;想要什么样的错误信息,也只需要进行Mock。
4) Mock可以不用加载项目环境配置,从而保证了测试用例的执行速度。
在进行集成测试时,我们需要加载项目的所有环境配置,启动项目依赖的所有服务接口。往往执行一个测试用例,需要几分钟乃至几十分钟。采用Mock实现的测试用例,不用加载项目环境配置,也不依赖其它服务接口,执行速度往往在几秒之内,大大地提高了单元测试的执行速度。
3. 单元测试与集成测试的区别
在实际工作中,不少同学用集成测试代替了单元测试,或者认为集成测试就是单元测试。这里,总结为了单元测试与集成测试的区别:
1) 测试对象不同
单元测试对象是实现了具体功能的程序单元,集成测试对象是概要设计规划中的模块及模块间的组合。
2) 测试方法不同
单元测试中的主要方法是基于代码的白盒测试,集成测试中主要使用基于功能的黑盒测试。
3) 测试时间不同
集成测试要晚于单元测试。
4) 测试内容不同
单元测试主要是模块内程序的逻辑、功能、参数传递、变量引用、出错处理及需求和设计中具体要求方面的测试;而集成测试主要验证各个接口、接口之间的数据传递关系,及模块组合后能否达到预期效果。
后记
《西江月·百途》
代码编辑已毕,谁能担保无遗。
单元测试解难题,查验流程合理。
质量提升效益,百途扛起旌旗。
俊杰志士聚一席,共创高德佳绩。
——谨以此词献给高德的《百途度量平台》。