TDD已死之论战

公司最近组织了一次关于TDD的培训,从而引发了同事关于TDD的一些讨论,这让我想起了一年前DHH(Ruby On Rails之父)那篇有名的文章《TDD is dead. Long live testing.》,突然想聊一下关于TDD的一些事情。

DHH的观点

如果不想费劲看英文的话,可以看一下台湾同胞翻译的这篇译文,翻译得很好。其实在国内外早就有一些对TDD质疑的看法,比如《TDD并不是看上去的那么美》《TDD到底美不美?》等,这些都是对TDD的一些独立思考,是否软件开发过程是一定要使用TDD?使用了TDD是否就一定能让我们的开发变得更好更快?DHH在一开始也是觉得TDD挺好的,但在尝试TDD的过程中发现TDD并不是那么好实施且容易破坏设计,文章中有几个观点我是比较赞同的,下面我逐一说一下。

TDD不是一个标准

TDD是极限编程的一个工程实践,通过先写测试用例再写功能代码的方式来完成软件功能的开发,TDD的好处在网上一搜就可以找到很多,但是一些以敏捷布道为职业的人夸大了TDD的作用,他们会说如果不做TDD就不是敏捷开发,甚至以会不会TDD、用不用TDD来衡量是否一个工程师是否优秀。这种做法是不妥的,TDD就像一项技术、一种框架、一类语言一样,工程师有权利选择使用它也可以不使用。

大家在看Martin Flow、Kent Beck、Uncle Bob使用TDD的时候可能会觉得很厉害,但这并不是TDD很厉害,而是那3位大师很厉害,任何一种招式到了高手手里都是一件很厉害的武器,就像金庸小说下的虚竹用少林基本功就可以对抗鸠摩智这样的高手道理一样。所以我们不应该以会不会用不用TDD为标准来衡量工程师,术业有专攻,就算是在现在使用比较少的ASP、.NET开发工程师里面也有很多优秀的人,更不用说世界上最好的语言PHP了,虽然PHP网站的漏洞很多,但就是这些网站让人们对网络安全更加重视了不是吗:)

系统测试越来越方便

DHH还说道TDD让开发多了很多像Mock、Stub之类的东西,让代码更加不容易维护,其实可以使用更高粒度的系统测试来代替单元测试。对于这点我也是比较赞同的,在硬件效率越来越高,带宽越来越大,框架越来越轻量级的今天,一些系统级的测试(比如连接网络,读取数据库,访问第三方系统)的测试也会变得跟单元测试一样快。

在TDD中使用Mock技术也是有一些历史原因,在以前的企业级开发中,数据库用的是Oracle,web容器用的是Weblogic等比较重量级的中间件,使用这些中间件一个是速度慢,另外一个是配置困难,如果要在单元测试里面连接数据库启动web服务的话,一个测试用例的编写和运行都要耗费大量时间,所以就有了很多对中间件Mock的技术,让开发人员在测试中使用假冒的中间件服务,已达到快速测试的目的。

但在技术日新月异的这个时代,Nosql,内存数据库,轻量级web容器等慢慢成为开发的主流,而且硬件资源越来越好,网络速度也越来越快,这让一些系统测试可以运行得跟单元测试一样快,而写系统测试最大的好处就是不用写那么多Mock的代码,不需要把代码隔离的那么厉害,测试案例不会太多太杂。

我自身的TDD体会

我以前也是比较喜欢TDD的,并尽量要求自己在工作中使用TDD的方式来开发,但现在并没有要求自己一定必须使用TDD的方式开发,在大部分开发工作中我还是先写功能代码,然后再写单元测试。我觉得一个比较适合TDD的场景是修复BUG,当测试人员向你提交一个BUG的使用,你可以先写一个测试用例来让你的BUG重现,这样测试案例运行肯定会失败,然后在修复你的BUG让测试用例通过,然后再重构代码,这样就完成了一个TDD的过程,而且也保证了你的BUG以后不会再出现。

另外我觉得一个好技术的标准还包括其学习曲线要低,让人容易学会,如果花费大量时间还不能学好的技术可能本身就存在一些问题,抑或者是与人们的习惯相差太大而不能被普遍接受。但不管怎样,如果没有使用过TDD的人就说TDD不好也是不对的,“没有实践就没有发言权”,要证明TDD不够好还是先用TDD写写代码吧,或许能在使用TDD的过程中发现一些对自己有用的东西呢。

Comments