TDD,也就是 Test Driven Development--测试驱动开发,其实是一种开发方式的巨大提高。它
提出了一种新的开发方式:以测试为驱动。在此,我仍然想引用一个曾经看过的ThoughtWorks的
一个人的Blog中的一句话:“什么是TDD?TDD就是把你的需求用测试给描述出来。”这句话一下
子让我明白了TDD的意义,并且被我个人奉为TDD中的经典 :)

    归根到底,TDD的实质仍然是以需求来驱动开发,只是,TDD中把需求进一步写成了测试,那
就成了测试驱动开发了。

    这么做的好处是什么?我想至少有以下这么几条:

    1、你的代码是可测试的。
    2、你的代码完全反应了需求。
    3、通过测试驱动,会规范你的代码和结构,甚至架构。

    不错,我承认,TDD会带来成本的提高。因为我们要写测试,所以必然要花费时间。那么这部分
的成本谁来买单呢?客户吗?这很难,因为毕竟大部分的客户已经在软件的本身就和你讨价还价

了,你还想让客户再为测试来买单?

    让老板买单?老板恐怕要为此付出加班费。舍得,还是舍不得?这似乎又变成了一个哲学的问
题。

    自己来买单?也就是自己白加班来做这些事。值得,还是不值得?这似乎又是一个职业态度的
问题。

    如果单从理论上,每种买单方式都可以写厚厚的文字去论证,不过这么做其实并没有很大的意
义,我还是从实践中说起。

    就说最近的两个项目。一个是公司的移植项目,从一个专有的framework移植到structs;另一个
是我帮助朋友做的一个国内的小项目。第一个项目,我说了不算;第二个项目,我的意见起主导
作用。

     移植项目的团队中一共有10个人。我使用了Selenium这个工具。但因为是移植的项目,所以
TDD的概念也就无从谈起。不过,每移植一个功能之前,我都是先按照旧系统的操作,使用
Selenium来编写测试类。在功能移植完毕之后,我在新系统中去跑我的测试类。

    因为需要测试的内容非常多,所以,我的测试方法也是越写越多,其中不停的重构和修改,也
总结了一些简单的测试方式。

    是的,最开始,我花的时间确实比别人多一点,多多少呢??一个测试方法,我相信我用10分
钟就足够写好了。重构?我想1,2个小时足够了。

    而且,我每次修改完一个功能,我可以运行全部的测试,这样,我就知道我的修改对以前的改动
是不是造成了负面的影响。

    一个月下来,我能运行的测试类有140多个,需要注意的是,我并非写了140个测试方法,因为
有的测试类是通过继承来实现的,这是因为有许多画面,可能就是商品种类不同,剩下的都相同。

    这样,每次系统改动的时候,我只要把这些测试全运行一次,就知道我负责的模块是不是有问
题。

    那么其他人呢?他们仍然在手动测试,每次一个更新,他们都要手动去测试每一个地方,而且
不能保证测试到了每一个地方。

    那么我来计算一下成本吧!就算我那140个测试方法都是单独的,每个方法我需要10分钟,
那么我需要 1400 分钟,1400/60 = 23.3 个小时。也就是说,一个月下来,我只需要多付出23.3个
小时。

    那么收益是多大呢?一个月后,我只需要20分钟就可以知道系统是不是存在错误,而他们却
需要几个小时,而且未必准确。

    再来说说那个国内的项目。那个项目我要求了使用TDD的方式,因为这是一个从零开始的项
目。在实现一个功能之前,首先编写测试方法,确定了这个功能要实现什么目标,如果有错误,
该提示什么样的错误信息。

    根据经验,一个测试方法大概需要10-20分钟,到目前为止,大概完成了25%,一共有40个测试
方法,那么成本就是 400/60 = 6.7 个小时。收益呢?目前只要做了任何一个改动,只要跑一遍测
试,就可以知道系统是不是存在问题。

    我通过了2个实践的例子来说明TDD的优势,其实归根到底,TDD从开发方面,节省了我们的
测试资源,从用户方面,保证了产品的质量,从老板的角度来说,其实是用小的成本换来大的收
益---为什么这么说?小的成本其实就是测试方法的编写,大的收益就是产品质量的保证,以及更
好的产品,吸引来更多的客户。

    但是,就是这么一点点的成本,或许是再稍微多一点的成本,让很多公司望而止步。很多人仍然
认为这些成本可以省掉。因为理由很充分:你看那么多公司,不是仍然效益很好,顾客很满意吗?
其实如果深入到那些公司内,就会发现:维护的项目是多么的糟糕,每次Release,如何保证这次
的改动不会造成影响?除了让QA的人测试大量的case,还有别的办法吗?

    “我们修改了一个bug,但同时又创造了一个新的bug。”这个神话不是我们自己创造的吗?

    我想TDD还有漫长的道路需要走下去,需要更多的时间来获得人们的认同,只是目前的情况,
只能是TDD,想说爱你不容易!

    如果你是一个准备购买软件的客户,那么你可以毫不犹豫地要求软件开发商使用TDD的方式,
因为你应该知道这样做其实是在保护你的利益。

    如果你是一个老板,那么你应该立刻要求下属学习并实践TDD,如果客户不买单,那么你应该
买单,因为你应该相信,微小的成本会换来更好的软件,更好的软件会迎来更多的客户。

    如果你是一个开发人员,那么你应该立刻学习并实践TDD,如果你的客户和老板都不准备买
单,那么就自己买单。你应该相信,微小的付出,会换来更多的价值!

评论
kozyan 2008-05-01
stevenwang 写道
这个论题我喜欢。
早想写一点文字,来纪念我TDD的失败的经历。
那是在对日外包公司工作的时候,做了一个J2ee的项目。
由于刚学会JUnit,于是就大胆的实践一下TDD神通。
结果很惨,写了N多的TestCase之后,速度没有任何提高,反而浪费巨大时间。
最后应该是通宵加班才算完成。
通过这次失败的经历得出一个结论:TDD不适合中国国情。
--------------------------------------------------
关于程序员提交代码,我遇到一个公司,他们的程序员基本不测试,甚至不编译就提交。以测试代替debug非常严重,原因是编码时间安排的很紧张,编码就很难按时完成,当然没时间测试了。而且领导非常在乎你编码的速度,而忽略bug数量,因此大家约定俗成尽快完成代码,让测试人员累去吧。
呵呵,这就是企业文化。好玩儿吧。



呵呵,本人才學會一點點TDD,覺得非常好用!不過你說"TDD不适合中国国情。"我不同意這種說法,最多只能說不適合你的使用情況!
我覺得TDD在絕大多數的情況下可以使用,除了應對多線程的測試(可能還有其它的個案).
另外,TDD确實增加了開發時間,但減少了維護時間;大家想想看,你們是在開發時花的時間多還是維護的時間多!
mikecaodan 2008-02-27
写的真不错,不过我们公司现在上的都是老系统,象TDD,也只能远观了,要用TDD的项目去做软件,我觉得首先就要把项目定位到TDD,然后再分析,设计,让TDD的思想在项目中扎根.
stevenwang 2008-02-20
这个论题我喜欢。
早想写一点文字,来纪念我TDD的失败的经历。
那是在对日外包公司工作的时候,做了一个J2ee的项目。
由于刚学会JUnit,于是就大胆的实践一下TDD神通。
结果很惨,写了N多的TestCase之后,速度没有任何提高,反而浪费巨大时间。
最后应该是通宵加班才算完成。
通过这次失败的经历得出一个结论:TDD不适合中国国情。
--------------------------------------------------
关于程序员提交代码,我遇到一个公司,他们的程序员基本不测试,甚至不编译就提交。以测试代替debug非常严重,原因是编码时间安排的很紧张,编码就很难按时完成,当然没时间测试了。而且领导非常在乎你编码的速度,而忽略bug数量,因此大家约定俗成尽快完成代码,让测试人员累去吧。
呵呵,这就是企业文化。好玩儿吧。
ds3783 2007-10-24
gigix 写道
sigh……
话是这么说没错啦……不过您给的那一组实践……这个成熟度它就很成问题亚……


呵呵 ,这个的确是,不过也是没有办法的事情,慢慢来一切都回好的
ds3783 2007-10-24
另外一点,我觉得有一点没有说太清除,就是测试与调试之间区别。
程序员的调试是与设计相关而不是需求相关,所以严格意义上不算测试的说。
测试是从需求得出来的,而不是从设计得出来的,代码通过了调试后只能证明满足设计要求,但设计如果不满足需求,同样测试会挂。
gigix 2007-10-24
ds3783 写道
gigix 写道
扯淡
这个只跟你的团队定什么规矩有关
再说了,新开发的程序处理多少异常情况,跟check in的代码会不会break build,根本就两码事

的确是两码事,但和软件最终产出的成熟度是息息相关的哦

sigh……
话是这么说没错啦……不过您给的那一组实践……这个成熟度它就很成问题亚……
ds3783 2007-10-24
gigix 写道
扯淡
这个只跟你的团队定什么规矩有关
再说了,新开发的程序处理多少异常情况,跟check in的代码会不会break build,根本就两码事

的确是两码事,但和软件最终产出的成熟度是息息相关的哦
gigix 2007-10-24
ds3783 写道
抛出异常的爱 写道
汗。。你不测一下就有胆子把代码上传么SVN么?还要不要饭碗了?


程序员的测试主要有以下几个层次:
1.代码编译通过,配置文件配置正确,即使出现bug,也影响范围也是与本次提交代码相关的,不影响系统其他功能或特性。
2.代码相关的业务能够正常跑,能够实现用例文档中基本流,并保证结果正确。
3.能够处理大部分异常流,并能够给出相应的错误提示或结果符合设计要求。
4.能够通过功能测试和压力测试。

要求从1-4 等于对程序员水平要求的从低到高,一般程序员的要求能够达到第二条即可,剩下两条由测试部门负责验证,并以缺陷的方式提交给开发
另外,在不能达到第二条要求的代码仅仅允许在每个程序员自己的开发流/分支上提交,集成流/ROOT分支上的代码就永远能够保证满足要求2.
当然,还可以考虑用三层流来实现即:开发流/测试流/集成流,开发流的代码满足要求1,测试流的代码满足要求2、集成流的代码满足要求3或4.

扯淡
这个只跟你的团队定什么规矩有关
再说了,新开发的程序处理多少异常情况,跟check in的代码会不会break build,根本就两码事
ds3783 2007-10-24
抛出异常的爱 写道
汗。。你不测一下就有胆子把代码上传么SVN么?还要不要饭碗了?


程序员的测试主要有以下几个层次:
1.代码编译通过,配置文件配置正确,即使出现bug,也影响范围也是与本次提交代码相关的,不影响系统其他功能或特性。
2.代码相关的业务能够正常跑,能够实现用例文档中基本流,并保证结果正确。
3.能够处理大部分异常流,并能够给出相应的错误提示或结果符合设计要求。
4.能够通过功能测试和压力测试。

要求从1-4 等于对程序员水平要求的从低到高,一般程序员的要求能够达到第二条即可,剩下两条由测试部门负责验证,并以缺陷的方式提交给开发
另外,在不能达到第二条要求的代码仅仅允许在每个程序员自己的开发流/分支上提交,集成流/ROOT分支上的代码就永远能够保证满足要求2.
当然,还可以考虑用三层流来实现即:开发流/测试流/集成流,开发流的代码满足要求1,测试流的代码满足要求2、集成流的代码满足要求3或4.


BTW:编译不通过的代码偶也见过,不过第二天自动部署的日志一眼就看出来了。这种问题有几种情况:1.程序员疏忽。2.项目中某个程序员没有按照设计做。3.两个程序员改了同一个文件并且先后提交的时候发生了冲突,合并时给弄错了。
gigix 2007-10-23
抛出异常的爱 写道
汗。。你不测一下就有胆子把代码上传么SVN么?还要不要饭碗了?

这种事情么……
我以前还见过编译不通过就上传的呢
抛出异常的爱 2007-10-23
汗。。你不测一下就有胆子把代码上传么SVN么?还要不要饭碗了?
ds3783 2007-10-23
抛出异常的爱 写道
人工测试不是程序员应该去作的事。他们的本职就写代码,如果写代码就能测试,为什么不呢?

个人认为测试(包括人工、自动)都不是程序员应该做的事情,但实际情况是程序员也是人本身的水平、能力或者工作状态都会影响到代码的质量。
所以程序员只要要在写完之后做自己的代码检查,或者单元测试,当然TDD中的测试根据情况融入程序员自己写的符合需求或设计测试也未尝不可
gigix 2007-10-23
liufanjavaeye 写道
觉得又要吵起来了,而且每次都少不了gigix,难道别人的话就那么让你火大

讨论得很好阿,你干嘛又觉得要吵起来?
liufanjavaeye 2007-10-23
觉得又要吵起来了,而且每次都少不了gigix,难道别人的话就那么让你火大
抛出异常的爱 2007-10-23
人工测试不是程序员应该去作的事。他们的本职就写代码,如果写代码就能测试,为什么不呢?
ds3783 2007-10-22
cnfree 写道
TDD又不是万试万灵的,像GUI这一块根本无法使用TDD,TDD只能用在Model以及单元逻辑这一部分,但是简单的逻辑没有问题,不代表复杂的逻辑组合没有问题,而这一点TDD能否做到?实际上最后还是要靠常规的测试体系来保障软件的开发。软件开发始终还是需要靠需求来驱动。TDD决不是神。


首先,测试非要自动化么??
人工不行么?
虽然Kent给我们举的例子是自动化测试的,但是我们不能人工做么?
当我们人工发现一个错误的时候,再把这种情况做成自动化测试脚本(利用RFT或者Robot),用于今后的回归测试,至少是图形化界面测试的一种方案。
另外,测试的的粒度是与需求、设计都有关系的,对一个比较复杂的用户界面设计,那么我们至少要为它准备3个测试。
ds3783 2007-10-22
从表明看来TDD会增加工作量,会影响开发的进度和效率。
但实际上TDD会让人少走很多弯路,尤其是真正写代码的程序员,从而从另一方面降低了软件开发的成本。
测试不仅仅体现对程序的要求,同时也是对开发人员传达用户的需求。
cnfree 2007-10-19
gigix 写道
cnfree 写道
Java这个行业,作GUI的就不多,现在多数都是WEB应用,更不用说TDD来搞这个玩意。

第一,我一直认为web也是GUI
第二,如果你所说的GUI仅仅局限于desktop applications,请google "abbot"


Yes, Web的事件相应相对较少,逻辑也比较简单,更容易测试,而且工具也比较多。这是大家共知的。此处我提到的是desktop applications。我不知道别的语言开发是不是也这么多的提到TDD,毕竟Java在国内的应用我想基本上都是WEB开发,采用TDD绝对是一个不错的解决方案。
gigix 2007-10-19
cnfree 写道
Java这个行业,作GUI的就不多,现在多数都是WEB应用,更不用说TDD来搞这个玩意。

第一,我一直认为web也是GUI
第二,如果你所说的GUI仅仅局限于desktop applications,请google "abbot"
cnfree 2007-10-19
gigix 写道
cnfree 写道
TDD又不是万试万灵的,像GUI这一块根本无法使用TDD,TDD只能用在Model以及单元逻辑这一部分,但是简单的逻辑没有问题,不代表复杂的逻辑组合没有问题,而这一点TDD能否做到?实际上最后还是要靠常规的测试体系来保障软件的开发。软件开发始终还是需要靠需求来驱动。TDD决不是神。

谁告诉你GUI不能TDD?
谁告诉你复杂的逻辑组合不能TDD?
谁告诉你有了TDD就不要“常规的测试体系”?
谁告诉你有了TDD就不是“靠需求来驱动”?
谁说过TDD是神?

自说自话倒也罢了,说的还都是些废话。


Maybe我说的都是废话,我不知道有那个公司的GUI界面用TDD来开发,也许是我见识浅。不管怎么说,用TDD来开发GUI,成本都是非常昂贵的,而且就Mockup的设计上来说,GUI上的变动是最大的。甚至自动化软件来测试GUI的行为都非常昂贵,当然这只是我自己的个人经验。某些时候自动化测试GUI的成本比手工测试成本要高许多,这些软件一般需要拿到当前需要测试的控件对象,但由于Java操作的并不是原生Window控件,并且都是封装过的,很容易出错。比如一个菜单,一个Eclipse的编辑器,都很难侦测。不信的话,你可以用翻译软件看看能不能侦测到Eclipse的编辑器上的东西。如果你没有用TDD做过GUI开发,你就不要张口说瞎话,做过再说。Java这个行业,作GUI的就不多,现在多数都是WEB应用,更不用说TDD来搞这个玩意。我不是反对TDD,但TDD的确是有局限性的。纸上谈兵是靠口才,但软件开发还是靠实践。
发表评论

提醒: 该博客已发表在公共论坛,博客所有留言会成为论坛回贴,留言请注意遵守论坛发贴规则

您还没有登录,请登录后发表评论

yananay
搜索本博客
我的相册
D35bafa8-5bf0-475f-aa06-16f3080557a1-thumb
tdd
共 3 张
存档
最新评论