介绍怎么做单元测试的书很多,这里主要解答:为什么单元测试。
客观来说,单元测试和使用版本控制系统(GIT,SVN)是一样重要的。
为什么单元测试如此重要,但你却感受不到。首先要知道,代码的终极目标有两个,第一个是实现需求,第二个是提高代码质量和可维护性。
单元测试是为了提高代码质量和可维护性,是实现代码的第二个目标的一种方法。(注:代码的可维护性是指增加一个新功能,或改变现有功能的成本,成本越低,可维护性即越高。)
任何一个伟大的程序员都是从最简单的代码开始写起的,假设你的第一个程序是Hello World,任何一个语言实现这个程序都只需要不到5行代码。这个程序需要单元测试吗?
我们看看这个程序是否实现了软件的两个目标:
1.需求很简单,输出Hello World,这个程序完全满足需求。
2.只有5行代码的“软件”无论是代码质量,还是可维护性,都相当高,你想要把Hello改成Hi真的很轻松。
既然我们已经实现了代码的目标,要不要使用单元测试是无所谓的,同样这么简单的代码也没人会使用GIT或SVN。
代码量:5行
接下来你写了一个相对更复杂的程序,一个简单计算器。这个程序实现了数字的加减乘除,整个程序共写了大概50行代码。这个程序需要单元测试吗?
1.需求是对数字进行加减乘除,这个程序满足了需求。
2.你的代码风格很好(你已经了解到代码风格很重要),你使用了缩进,良好的变量命名,逻辑也清晰,代码的质量和可维护性仍然相当高,如果你想增加一个“求x的平方”功能,你轻而易举就可以做到。
这个时候让你去写单元测试,你仍然会觉得那纯粹是浪费时间。
代码量:50行
你想要做一个真正的实用系统,给学校开发一个图书管理系统。 你相信这个系统的代码量比起计算器会很多(可能会有1000行)。你从书上看到有这样一些方法可以简化你的开发工作:
1.工具库(类似你家里的工具箱),使用工具库带来的好处是非常明显的,假如你要实现“返回一个数字数组中的最大值”,你只需要使用某个工具库的Max()函数,只需要1行代码,而不是10行代码自己实现。
2.MVC框架,虽然比起工具库更复杂,需要花更多时间学习,但MVC框架带来的好处也非常明显,轻而易举调用数据库(Model),实现简单的UI界面(View),实现了类似“书名为空的书不允许添加到数据库”的一些逻辑(Controller)。
你最终很好的实现了这个系统,基于MVC模型,你的代码被很好的分割成了很多小的独立的模块:4个Controller,2个Model,4个View。并且在工具库的帮助下,代码量得到了缩减,每个模块大概只有50行代码(等同于一个简单计算器的代码量)。这个系统需要单元测试吗?
1.你实现了对图书的添加、删除、修改、借阅,你很好的满足了需求(校长表扬了你)。 2.得益于框架与库的使用,你的代码被很好的模块化了,每个模块都像一个“简单计算器”那样简单,增加新功能,或修改现有功能似乎也没有什么大麻烦,虽然会出现一些小bug,但很快就修复了,代码质量和可维护性都比较高。
既然你又实现了代码的目标——“完成需求,高代码质量和可维护性”,那好像也没“单元测试”什么事,毕竟写它要浪费额外的功夫,而且也没感觉到有多少好处。
代码量:500行
你被一家IT公司雇佣了,你通过了面试,进入了一个即将开启的项目——为一家大的电商公司做一个库存管理系统。
项目初期一切都很顺利,技术上和你做过的图书管理系统差不多。首先你了解了客户的需求,然后根据他们的需求,使用你已经掌握的MVC框架和一些库,实现了他们的需求。
你写了30个Controller, 50个Model,50个View,每个模块的代码都达到了大概150行,总代码达到了惊人的20000行!
你觉得自己很了不起,能hold住这么多代码,这完全是得益于你的高智商,以及工作努力。客户很满意,老板也很满意,你的自我感觉也很不错。
并且你发现了比单元测试更好的东西,面向对象编程(OOP),或函数式编程(FP),无论是哪一种,你发现你可以把一个模块里的150行堆砌在一起的代码再提取成1个对象的15种方法,或者15个独立的函数(具体怎么提取,你得看相关的书籍),OOP或FP像MVC模型一样,成功的把你的代码分割成了更小的组成部分,每个方法或函数里代码都只有10行左右,你几乎回到了“Hello World”时代。
你需要单元测试吗?(你能保证你的系统没有BUG吗?)这个复杂系统是由1950个函数和方法组成,如果想要确定系统整体没有BUG,就等同于确定组成这个系统的1950个函数和方法没有BUG。
而单元测试就是做这个事情的,显而易见,如果你写了单元测试,并且每个函数都通过了,你就可以骄傲的说:这个系统没有BUG!(当然这是代码的角度,而非功能和产品的角度)
虽然,从绝对的角度说,单元测试很重要,但是,从相对的角度来讲,小的代码量,简单固定的需求,个人开发,一锤子买卖等等都会让单元测试显得不那么重要,并且你一直开发的很舒服,这就是为什么有的人感受不到单元测试的重要性(这种情况下的确也许不用写单元测试)。
记住,单元测试的威力更多不是体现在新代码的编写上,而是对已有代码的更改。但程序员的智慧是有限的,系统的复杂度却是无限的,随着更大挑战的到来,当系统的复杂度超过了你的逻辑,记忆能力,你必须依靠别的工具来帮助你减少问题。
如果你现在在做一个较大的项目,这个项目的需求很多,所以你一直在开发,你遇到了这样的痛苦状况:
1.客户总能在使用中找出BUG;
2.每次代码的改动,都会导致一些意想不到的BUG出现。这个时候,单元测试可以挽救你。