计算机世界里软件产品通常是由模块组合而成的,模块又可以分成诸多子模块,子模块还可以继续往下拆分,拆分到最终的子模块是由不可再分的程序单元组成。
对于这些程序单元的测试,即称为单元测试。本期未名企鹅极客栏目,研发工程师给大家分享的是一些单元测试的基本原则。
单元测试的粒度要根据实际情况判定,可能是类、方法等,在面向对象编程中,通常认为最小的单元就是方法。
在很多人看来,快速完成业务功能开发才是王道,如果开发工程师说需要额外的时间来写单元测试,并因此延长项目工期,估计有些项目经理就按捺不住了。其实单元测试是一件有情怀、有技术素养、有长远收益的工作,它是保证项目质量和效率的重要手段之一。
单元测试的好处
(包括但不限于以下几点):
1、提升软件质量
优秀的单元测试可以保障开发质量。在研发过程中执行测试用例,运行失败的的单元测试能帮助我们快速排查和定位问题,使问题被带到线上之前完成修复。越早发现的缺陷,其修复成本越低。
2、促进代码优化
在编写单元测试的时候,会不断重新审视自己的代码,白盒的思考代码逻辑,更好地对代码进行设计,甚至想方设法的优化测试用例的执行效率。
3、提升研发效率
编写单元测试表面上占用了项目研发时间,但磨刀不误砍柴工,在后续的联调、集成、回归测试阶段,单元测试覆盖率高的代码通常缺陷少、问题易修复,有助于提升项目整体研发效率。
4、增加重构自信
代码重构往往是牵一发而动全身的,有时候只是简单地修改一个字段名称,就会引起一系列的错误,但是在有单元测试保障的前提下,可以放心的进行重构。
单元测试需要遵循的基本原则
1、自动化
单元测试应该是全自动执行的。测试用例通常会被频繁的触发执行,执行过程必须完全自动化才有意义。如果单元测试需要人工介入检查,那么他一定是不及格的。单元测试中不允许使用System.out来进行人工验证,而必须使用断言来验证。
2、独立性
为了保证单元测试稳定可靠且便于维护,需要保证其独立性。用例之间不允许互相调用,也不允许出现执行次序的先后依赖。
3、可重复性
单元测试时可以重复执行的,不能受到外界环境的影响。
4、测试颗粒度要足够小
编写单元测试时要保证测试粒度足够小,这样有助于精确定位问题,单元测试用例默认是方法级别的。单元测试不负责检查跨类或者跨系统的交互逻辑,那是集成测试需要覆盖的范围。
5、测试应该快速
理论上, 任何代码提交前都应该完整跑一遍所有单元测试,保持测试代码执行快能够缩短迭代开发周期。
6、BCDE原则
B:Border,边界值测试,包括循环边界、特殊取值、特殊时间点、数据顺序等。
C:Correct,正确的输入,并得到预期的结果。
D:Design,与设计文档相结合,来编写单元测试。
E:Error,单元测试的目标是证明程序有错,而不是程序无错。为了发现代码中潜在的错误,我们需要在编写测试用例时有一些强制错误信息输入(如:非法数据、异常流程、非业务允许输入等)来得到预期的错误结果。
7、使用覆盖率工具
覆盖率工具能回报你测试策略中的缺口。使用覆盖率工具能更容易地找到测试不足的模块、类、和函数。多数IDE都给出直观的指示,用绿色标记测试覆盖了的代码行,而未覆盖的代码行则是红色。这样就能又快又容易地找到尚未检测过的if或catch语句。
8、测试覆盖率的模式有启发性
查看被或未被已通过的测试执行的代码,往往能发现失败的测试为何失败的线索。
9、立即修正失败的测试
每个开发人员在提交前都应该保证新的测试用例执行成功, 当有代码提交时, 现有测试用例也都能跑通。
10、100%测试覆盖率不是目标
100%的覆盖率并不能确保没有缺陷——它只能保证你所有的代码都执行了,不论程序的行为是否满足要求。与其追求代码覆盖率,不如将重点关注在确保写出有意义的测试。
总结
单元测试的好处不言而喻,同时我们也要摒弃诸如:单元测试是测试人员的工作,单元测试代码不需要维护等常见误解。
未名企鹅内部也存在这样一种共识:对于开发工程师来讲,编写并维护单元测试不仅仅是为了保证代码的正确性,更是一种基本素养的体现。
文 / haiyi
编辑 / TiK
关于未名企鹅
未名企鹅以“连接健康”为使命,致力于提供生命健康领域的大数据产品和解决方案,帮助客户实现数据驱动的业务增长。
未名企鹅中的“未名”代表北大,寓意人文精神,生命健康领域正是体现人文关怀的产业;“企鹅”象征科技,未名企鹅的创始团队毕业于北大,技术力量来自腾讯,公司以未名企鹅命名是希望以人文情怀加上科技力量来推动生命科学行业数字化发展。
未名企鹅,数 · 智 · 未来
领取专属 10元无门槛券
私享最新 技术干货