单元测试实践

接受测试驱动开发也已经有些时光了,仍然只能依靠ide来创建一些测试对象,即使偶尔自己写几个测试用例,也是环境相关、依赖多多的实例,为什么我们的代码就需要单元测试呢,部分是自己的想法,部分是与几个朋友讨论收获的,浏览了<>之后不免想记录下自己的想法了。
自从有了代码就有了单元测试,就是最简单的debug调试也算作单元测试的一部分吧;测试驱动开发是在单元测试滞后产生的一种软件开发的方法学。只要有单元测试,它本身就含有驱动软件设计和代码重构的思想在里面。我们为了代码能够被单元测试,在设计阶段我们就会考虑怎么测试代码,同时测试用例也是代码的第一个用户;我们也需要为了测试了对代码进行重构。
1.单元测试的验证性:任何代码都是有一定缺陷的,单元测试能够尽量的发现代码中的问题和缺陷,验证了设计、业务逻辑、一些相关的特殊领域对象(一些Javabean等),保证了代码的完整性。从功能上对代码进行了验证,至少证明代码不存在功能上的问题。
2.单元测试的探索性:对于单元测试同样我们首先有一个测试列表,这个测试列表精心设计和长期习惯的积累,可能它就存在你的脑子里面。对于列表中的测试点,我们只测试可能出错的点;象那些不依赖于环境能够被间接的测试的点我们没有必要一定去测试。对于那些必要的测试点中,同样有业务逻辑的测试、模拟异常条件测试、对于预期的测试,需要我们良好的设计来实现它。在这个测试列表之外的是为测试区域,我记得哲学上有一个道理,一个圆越大,那么它与未知世界接触的区域就大。我们是不是也在做这种用例呢?单元测试就是尽可能保证我们所知道的每一个区域是“安全”的。
3.单元测试促使设计:
代码==è单元测试==è重构==è单元测试回归
首先我们对于代码进行单元测试,无论代码如何,设计如何,要保证现在代码是能够被单元测试的,这时候代码遇到了它的第一个用户:单元测试。代码如何被测试,考验代码的适应性和对变化的承受力。只有不断的重构才能使得测试更简洁。这里需要我们对于代码的重构设计成竹在胸,23个设计模式是不可或缺的方法。
4.测试用力是代码的使用手册:代码如何使用,可能客户不能很快知晓,测试用例就是一个demo,只要客户按着测试用例一样使用我们的代码,保证我们的代码一定能够被正确的使用。
4.单元测试的回归性:测试过的代码、功能等,不能证明随着时间的推移,在频繁构建之下,永远是好的。回归测试保证了在当前的测试用例之下当前的代码的良好性,是一张代码质量的协约书。谁都能“误”以为代码满足了编写者的设计意图。如果代码不能通过单元测试了,可能就是被损坏了。保证了重构中系统的完整性和一致性,随着代码的不断递增,通过机器自动保证代码测试无需人来参加。
5.防止衰退,减少调试:利用测试的回归性来进行代码的衰退,使得自动测试必须存在,他是我们代码的“守护神”(如果你也想为你的代码增加一个神,就从单元测试开始吧)。在代码、测试、重构的过程中,也是不断调试程序的过程,良好的单元测试能帮助我们发现错误和定位错误,逻辑单元测试本身就是一个细粒度的测试。
6.团队协作的可能:在一个团队,成员之间是互相信任的。我们通过什么来保证代码的可信任,单元测试让我们的代码是可以依赖的。有了单元测试的习惯,你不会在代码没有测试之前就提交它。模块之上的功能测试也是很粗糙的,对于代码的逻辑和集成性还是心有余而力不足。
突然想到,单元测试存在一块充满地雷的区域上的排雷器一样。我们验证什么地方有雷,什么地方没有;我们探索那些未知的区域;通过不断的排雷来评估这个区域的安全性;利用回归的探测来证明有没有新地雷扔到已测地区。