.NET : 单元测试到底给我们带来什么
前两天在讲VSTS方面的课程时,我再一次讲到并强调了单元测试。席间,有同学不太了解为什么要做单元测试。当然,这是一个根本性的问题,绝大多数的朋友都或多或少曾有过这样的疑惑吧。
我还是要总结一下,单元测试的作用
1. 给开发人员带来自信心
2. 确保代码是符合需求的
我们日复一日地写各种各样的代码,一个接着一个地编写各种类型,以及实现他们内部的各种方法,而且很多时候我们又会回过头去修改某些方法。这种修改可能是因为某个一时的灵感,但就在这样的关口,却很容易出现问题:我相信没有人真的都能记住每个方法之间的关联的,例如修改A方法的时候,是不是会影响到其他的方法呢?
很显然,我们需要一定的辅助手段,来给我们这样的信心:假设我改了该方法,其他方法不会有问题。而且即便有问题,我也能很快发现。
这应该就是第一个好处:开发人员显然需要这样的信心支持。
另外一方面就是说,因为编写单元测试用例一般都是结合功能需求去写的,那么如果说所有的测试用例都是通过的,我们就可以说,我们的代码是符合需求的。
如果再结合代码覆盖率达检查,就能够进一步地剔除那些多余的代码。
有一个小故事,说的就是单元测试给开发人员带来的好处,供参考
有一次——或许就是上个礼拜二——有两个开发者:Pat 和Dale。他们面临着相同的最后期限,而这一天也越来越近了。Pat 每天都在着急地编写代码,写完一个类又写一个类,写完一个函数又接着写另一个函数,还经常不得不停下来做一些调整,使得代码能够通过编译。
Pat 一直保持着这种工作方式,直到最后期限的前一天。而这时已经是演示所有代码的时候了。Pat 运行了最上层的程序,但是一点输出也没有,什么都没有。这时只好用调试器来单步跟踪了。“Hmm,决不可能是这样的”,Pat 想,“此时这个变量绝对不是0 啊”。于是,Pat 只能回过头来看代码,尝试着跟踪一下这个难以琢磨的程序的调用流程。
时间已经越来越晚了,Pat 找到并且纠正了这个bug;但在这个过程中,Pat 又找到了其他好几个bug;如此几次过后,bug 还是存在。而程序输出那边,仍然没有结果。这时,Pat 已经筋疲力尽了,完全搞不清楚为什么会这样,认为这种(没有输出的)行为是毫无道理的。
而于此同时,Dale 并没像Pat 那么快地写代码。Dale 在写一个函数的时候,会附带写一个简短的测试程序来测试这个函数。这里没有什么特殊的地方,只是添加了一个简单的测试,来判断函数的功能是否和程序员期望的一致。显然,考虑如何写,然后把测试写出来,是需要占用一定时间的;但是Dale 在未对刚写的函数做出确认之前,是不会接着写新代码的。也就是说,只有等到已知函数都得到确认之后,Dale 才会继续编写下一个函数,然后调用前面的函数等等。
在整个过程中,Dale 几乎不使用调试器;而且对Pat 的模样也有些困惑不解:只见他头埋在两手之间,嘀咕着各种难听的话语,咒骂着计算机,充血的眼球同时盯着好几个调试窗口。
最后期限终于到了,Pat 未能完成任务。而Dale 的代码被集成到整个系统中,并且能够很好地运行。之后,在Dale 的模块中,出现了一个小问题;但是Dale 很快就发现了问题所在,在几分钟之内就解决了问题。
现在,是该总结一下上面这个小故事的时候了:Dale 和Pat 的年纪相当,编码能力相当,智力也差不多。唯一的区别就是Dale 非常相信单元测试;对于每个新写的函数,在其他代码使用这个函数并对它形成依赖之前,都要先做单元测试。
而Pat 则没有这么做,他总是“知道”代码的行为应该和所期望的完全一样,并且等到所有代码都差不多写完的时候,才想起来运行一下代码。然而到了这个时候,要想定位bug,或者,甚至是确定哪些代码的行为是正确的,哪些代码的行为是错误的,都为时已晚了。