单元测试到底值不值得做?

  个人认为如果不做单元测试,则bug的多少存在一个日积月累的累积效果,而一个bug被隐藏的时间的越长,修复这个bug的代价越大。后才修改一个bug的代价可能是在bug产生时修改它的代价的10倍!

  国内软件公司经常看到这种情况:为了追赶进度,绝大多数程序员都把没有经过任何测试的代码提交到版本服务器, 项目经理也不追问,照单全收。结果是在后期,集成花费的时间越来越多,几个技术骨干人员只得日夜加班进行系统集成。好不容易集成完了之后,下发给测试人员测试时,bug的报告成数量级的增长。程序员日以继夜的修改bug。数不清的bug, 修正了一个bug, 更多的bug报告上来,改了一个带来另外一个。甚至还有非常多的bug被 隐藏更深,一直潜伏到生产环境去。项目中,越来越多的人对项目失去信心, 不知道自己写的代码里面还有多少潜伏的“炸弹”没有引爆呢?!于是胆战心惊,于是开始有人想逃离了,有人请假,也有人离职。当项目总算结束时,每一个的内心都清楚,项目太烂了,还有很多的错误还没被测试出来,赶快逃离这个项目组吧。

  其实前期不写单元测试,貌似赶上了进度,却累积了bug,且不利于未来的维护,到项目后期必然出来bug成堆疲于应对的局面。甚至修改一个bug引入另一个bug,而修改一个bug的代价往往是早期的几倍甚至几十倍!与其痛苦的挣扎,还不如去好好想想更好的实践。

  很多人都想着把做的东西整合起来,整体跑起来以后测试比较容易看到结果,例如相互之间存在接口和相互依赖关系的系统。这固然正确,我们常常说测试要占到整个开发周期的1/2或以上, 但事实上后期往往发现这种系统测试耗费的时间比预想的多得多,有的甚至超出项目预期耗费的测试时间的一倍以上,究其原因,很多“小零件”前期并没有好好严密的进行测试来到了总装厂进行总装,这样消耗的时间能不多吗?各个“小零件”中边界条件,异常情况,逻辑分支都存在这样那样的缺陷,导致系统千疮百孔,然后各自开始扯皮推脱责任,这样的系统测试的确难度太大!

  其实前期可能耗费的一点时间来写测试,但能大程度的减少初的bug,能增强底层函数和代码的可靠性,不会使上层出现的bug呈现累积效应。所以单元测试付出的收效随着时间的推移才会逐渐显现出来,也是说单元测试的成本是先高后低,而回报是逐渐增多,尤其是后期维护和升级,只需重新自动化运行单元测试用例进行回归测试,能确保更改的接口正确性。

  如何高效的做好单元测试?

  不管是强迫还是自动养成了自己写单元测试的习惯,有了单元测试的意识,接下来是如何高效的做好单元测试的问题了。

  写单元测试并不是一个微不足道的任务,如果步骤正确,单元测试可以为开发者的生产力和代码的质量带来令人惊讶的提高,他可以帮助你去创建的应用程序含有更少的错误,同时也可以便于其他的开发者去洞察你的代码,但是他也需要在之前承担一个义务,确认遵循一些简单的规则。当方法并不是很好时,单元测试则可能达 到一个相反的结果,从而浪费您的时间,并且使测试过程更加复杂。

  因为单元测试具体实施过程中有很多难点,例如,界面GUI如何做单元测试,网站的界面如何做,写文件的异常如何测,依赖复杂输入的情况如何编造数据,单元测试的粒度如何把握,更新代码时候需要同步更新测试代码和案例等等。

  单元测试的范围/粒度如何把握:

  单元测试基本是围绕函数来进行的。当然你可以用MOCK技术来模拟一些相对复杂的对象和环境。但总体来说,粒度应把握在函数级别,单纯的环境,要和系统测试/集成测试严格区分开来。

  单元测试的时间如何把握:

  如果按照项目时间这样划分:1/3 计划和设计, 1/6 实现, 1/4 组件测试, 1/4 系统测试。则在‘代码实现’中,不仅要包含Coding的时间,而且要包含单元测试的时间,他们的比例大概是1/3的时间做东西, 2/3的时间做检查。这样才能保证“零件质量”。单元测试不是为了增大自己的工作量,而是减少你未来的工作量。否则,从工程学上来说,或者有过真正工程经验的人,都知道其质量保证是掩耳盗铃,终将自食其果。

  哪些函数无需做单元测试:

  这个函数是不是简单到一眼能检查出输出和起征点的错误?如果的确是,那么这个函数不用做单元测试。有些公司和员工为了敷衍了是做一些“伪单元测试”,有点形而上学,根本不是高效的单元测试。

  哪些函数需要做单元测试:

  1. 逻辑或算法复杂,函数内部逻辑或算法很复杂,判断条件、循环、停顿跳转很多,一眼看不出输入什么结果,那么需要做单元测试来验证期望的输出;

  2. 涉及很多对象,单元测试一定要做,因为能够有效的发现和隔离依赖项,有助于更好的解耦;(一个紧耦合的系统的确很难做单元测试,需重构)