学习TDD:TDD的好处

上一篇 / 下一篇  2012-06-21 10:12:47 / 个人分类:杂谈

TDD的全称是Test Driver Development,测试驱动开发。就是开发要以测试为驱动。编码之前,测试先行。代码都没有,我如何测试,我连要测的对象都没有啊?这好像是个问题。

2d `6W\.V4z {p0  TDD的哲学为我们解答了这个问题:先编写测试用例(没有代码之前这些测试用例一个也通不过),然后再写代码让这些测试用例通过。更进一层的讲就是:编写足够的测试用例使测试失败,编写足够的代码是测试成功。我们编码的目的更加明确的。51Testing软件测试网$D,j$B'}"Z

51Testing软件测试网7cir(_,d

  TDD是大名鼎鼎的极限编程的一个最重要的设计工具之一(另一个是重构(Refactoring),这是它的荣誉,下面我列举几点它实际的好处。

e Fd5XC051Testing软件测试网 P*VL F2tr

  TDD带来的好处有:

.Bt QlhtA051Testing软件测试网9Z'S#Mh0ZA1i;qs!f

  1、你会更加站在用户的角度去看你将要完成的产品,你要尽可能想到用户所有进行的操作。而不是从程序员的角度想用户应该会如何去使用我们的产品。51Testing软件测试网_?Y%_}/~v'n#U

-W,N)j"p?D5{0me0  2、测试用例是在对功能进行测试。在写代码之前先写测试用例,可以对我们编写代码提供指导性的参考。防止我们漏掉一些功能。51Testing软件测试网"t!\O1zNun

51Testing软件测试网F)ZB5X5DAwL\

  3、它使我们对自己代码有了信心,因为我们事先设计好的所有测试用例都Pass了。

H [7Z"o D*M.if0

wd)Px(la%P7r0  4、如果在更改代码后测试用例不能通过,我们可以根据不能通过的测试用例精确的定位问题,并轻而易举的解决的这个bug

u}(N2eIa0

^w5e9y7Q0   5、哈!我们的一整套完备的测试用例在这里替我们把关(把的什么关?),我们就可以十分安全的使用极限编程的另一个最重要的工具——重构。重构改变的是 代码的内部结构,而不会改变外部接口功能。知道在做重构时测试用例是把的什么关了吧!很明显,测试用例是保证我们在进行重构时,不会影响到代码的外部接口 功能。所以我刚刚说,我们进行的重构是十分安全的。

l)c$M DNR0

[3e*bI0u0  6、基于第5点,我们找到了重构的信心,必要时候你还可以痛痛快快的并且满怀信心的对代码做一场大的变革。这样我们的代码变得干净了,扩展性、可以维护性以及易理解性纷至沓来。51Testing软件测试网`nW1gl:b

.Bk6_m5XM,l0  TDD有这么多好处,但它也不是免费的午餐,它需要我们有设计完备的测试用例的能力(这项能力是长期理论与实践的结合体),否则你将会吃了亏编写了一大堆测试用例,却没测到点子上。可怕的是,你还对你“测试通过”的糟糕的代码满怀信心。

+{|wd nbm+Dsz0

%s{W PCf"C8I0  TDD的主旨是高效,可能这个高效不是非常高的开发速度。

BJ+S7@R;G2LYnTF0

$p'Z c!?qI[0  通常的软件开发过程是先写功能,然后再写测试。甚至有时候只进行某些方面的测试,或者有省事的就略去了某些细小功能的测试,或者是忘了对这些模块的测试。

Iw6Y,so5DJ"q051Testing软件测试网7bs+c*p SAX

  这些看起来对软件影响不大,但是似乎有点过于自信了。因为我们是人,不是神,所以难免会出一些这样或那样的错误,而这些小的问题在项目整合起来以后进行排错是非常令人头疼的。

}#\(sse-e-W0

E!Xa.uo0   TDD的思想是以测试推动开发进程。因为我们在软件开发之前,每个程序单元的功能都已经确定了。程序员在理解完整个程序需求以后,直接进行开发,有可能 会因为种种原因考虑不很周全,似乎功能实现的没有问题了,但是其中却可能隐藏着非常可怕的Bug。TDD促使开发人员先根据程序单元的功能编写测试代码, 就像是先建一个模型,然后向里面浇注合适功能的代码。最后满足所有的测试验证了,才能正常通过测试,这个程序单元才算完成。51Testing软件测试网&Bh([3_Y)aB)\

s;@n7s0KLPSm0  这样消除了开发人员主观性的对程序单元健壮性的评估,更客观的验证每一个程序单元的功能实现以及可能出现的Bug。

wSa g[)} p-N051Testing软件测试网([ l*Fg)U}W4x

  当然,这些操作都需要有大量的代码支持,所以费事是在所难免的,但是这点“费事”与健壮性非常强的代码相比,有些人还是偏向于使用TDD。

[ IX/e ~g1K%x"V/o0

mf{b ~9e^)\0  首先站在客户方代码的立场,可以获得更好的api。51Testing软件测试网G&v9zR([p s:IX%O f

b2Bg+M3doe| FT0kG0  其次可以改善软件质量,支持重构。

FC\6`` mKst"x2AV0

&Vg|0h$q'Md0  其三,大幅减少debug时间。

,@4[ v$MOJZQNe0

:[ScxG T_'^&i0  前期投入大,后期能大幅缩短开销,将问题发现在最源头

#E!u?;?(@2D051Testing软件测试网.V_aMojOTK

  提供明确的目标51Testing软件测试网OL'g;j.{.Q*|

51Testing软件测试网~C5T%rn$J

  你很清楚, 一旦结束(测试通过), 你的工作就完成了(假设你的测试写的很好). 测试代码会为代码建立一个自然的边界, 使你把重点集中在当前任务上. 一旦测试通过, 就有确切的证据证明你的代码能工作. 相对于人工的测试用户界面或者比较日志文件中的结果,  在一个xUnit框架中运行自动化测试, 速度要快几个数量级. 大多数xUnit测试的运行只需几微秒, 而且大多数采用TDD的人都会一天运行数次测试. 在许多开发小组中, 将代码上传配置库前, 必须成功地通过测试。51Testing软件测试网TIgm?3r:f h#u

R^$sw_.f8h0  提供文档51Testing软件测试网 ~L,@,f q-|2w#X

FC/`*V(C6cNM g3\0  你是不是经常遇到看不懂的代码? 这些代码可能没有任何文档说明, 而且开发代码的人可能早就走了(或者去度假了)。 当然看到这种代码的时间往往也很不合时宜, 可能是凌晨3点, 也可能有位副总在你旁边大声催促着赶快解决问题, 这样要想花些时间来愿作者的意图就更困难了。 我们见过一些好的单元测试文档, 它们会指出系统要做什么。 测试就像原开发人员留下的记号, 可以展示他们的类具体是怎么工作的。

GYr7fkh~0

9B J V:S4^d0  改善设计

$P,g ex*d4L [\.E0

B6lWk(F2c"l5Xh0  编写测试能改善设计。 测试有助于你从界面的角度思考, 测试框架也是代码的客户。 测试能让你考虑得更简单。 如果你确实遵循了“尽量简单而且行之有效”的原则, 就不会写出篇幅达几页的复杂算法。 要测试的代码通常依赖性更低, 而且相互之间没有紧密的联系, 因为这样测试起来更容易。 当然, 还有一个额外的作用, 修改起来也会更容易!51Testing软件测试网h5X?;\CN6Qz+Je

51Testing软件测试网3m3jAL"|Hl

  鼓励重构

:[c3~*J(\;Ym051Testing软件测试网[KS El%}E

  利用一套健壮的测试集, 你能根据需要进行重构。 你是不是经常遇到一些不知是否该修改的代码? 种种的顾虑让你行动迟缓, 过于保守, 因为你不能保证所做的修改会不会破坏系统。 如果有一套好的单元测试集, 就能放心的进行重构, 同时能保证你的代码依然简洁。

e-`p*n0m4`i2|051Testing软件测试网#dFp,t^3Q Bu'P

  提高速度

E-y1A K|gG1Q0

W O)v|C#A2WN0  编写这么多测试会不会使开发速度减慢呢? 人们经常会以速度(或开发开销)作为反对进行TDD和使用xUnit框架的理由。 所有的新的工具都会有学习曲线, 但是一旦开发人员适应了他们选择的框架(通常只需要很短的时间), 开发速度实际上会加快。 一个完备的单元测试集提供了一种方法对系统完成回归测试, 这说明, 增加一个新特性之后, 你不必因为怀疑它会不会破坏原系统而寝食难安。

[hT#Qo051Testing软件测试网-n2ub9YfAo%Z:h

  提供反馈

9`sG1Q4N['{0

"^B%EzU7B f0  单元测试还有一个经常被忽略的优点, 即开发的节奏。 尽管看上去好像无关紧要, 但通过测试之后你会有一种完成任务的成就感! 你不会成天地修改代码而没有任何反馈, 这种测试-代码-测试的方法会鼓励你动作幅度小一些 通常修改一次代码的时间仅仅几分钟而已。 这样你不会一下子看到冒出一大堆新的特性, 而只是让代码每次前进一小步。51Testing软件测试网W8B i7j-?8^7S"~

51Testing软件测试网"| S R2fuiFc-J

  TDD所带来的好处是否被过度的夸大?51Testing软件测试网fH1sz8^k,|A,s

51Testing软件测试网_4Y)INp1jYR

  当需要进行测试时,我信守下面的经验主义的做法:51Testing软件测试网2L(N H2H-FvG g3g

51Testing软件测试网2xrN X;d%WQp9EI H\D

  ● “先测试”还是“后测试”并不重要,只要你是在测试。

}l`7jL#_ X0

__i+Xh,IT_lL L0  ● 在你的开发过程中尽可能早的考虑测试。51Testing软件测试网&Ix(p;^ F;T

51Testing软件测试网l0{A/v oHns

  ● 不要让某个框框限制了你的行动。例如,不要轻信那些人告诉你的、要写出“尽可能简单的能够运行的程序”—也就是所谓的YAGNI—的话。如果你的经验告诉你,未来你会用到这个额外的类—虽然现在用不着,你应该相信你的判断,加上这个类。51Testing软件测试网{.K~/fJ/@3~

%mc:y WXTr't0  ● 记住,功能测试是真正对用户有意义的测试。单元测试只是为你—开发者—服务的。属于奢侈品。如果你有时间去写单元测试,那最好了:当你的程序出现问题时,它们能帮助你省去很多时间。但如果你没有时间,你要确保功能测试能覆盖到你的产品里用户所期望的所有功能点。51Testing软件测试网r jC1p M

51Testing软件测试网,A.t Lx(a

  ● 如果你没有做驱动测试开发,不要有任何的不安。有太多的因素都能导致这种开发方法在众多的项目和个人开发习惯中水土不服(有很多因素那些TDD极端主义者们永远都不会提)。51Testing软件测试网1X0A(GW`'dt

M0sKhGF X"y!rn0  TDD( 测试驱动开发) Overview

/aZ.Q)xo,@s[R051Testing软件测试网_$J7_"a#\l8U

  第一篇技术博客,希望有人支持,您的关注是我的动力。。。51Testing软件测试网 [ W#X.d T];Zc3c

51Testing软件测试网3g!nkjt!w'l"hg1?

  本文主要是基于本人的开发经验,概叙一下TDD,也就是测试驱动开发。我比较喜欢用问题方式来写,语言水平有限 希望读者看得懂且有帮助51Testing软件测试网+_npD S?{

s|4b$T q0  TDD这个东西 你一般用了之后会上瘾:) 它可能改变你以后的编程习惯

] ?c)n&zDG0

Pjd:a'b1Rv0e(b ?%r0  什么是TDD

9fLP ],uxh.s1ym051Testing软件测试网%O@SyV/p4n5W

  故名思意就是用测试的方法驱动开发。简单说就是先写测试代码,再写开发代码,和传统的方式是反的。51Testing软件测试网6tsMhkz1V'M

为什么要用TDD51Testing软件测试网D8{0rtY)Nw)f3L NWgE

  用TDD的方法可以使代码干净(代码重构的结果),测试覆盖率高(先写测试的结果),软件做集成测试的时候一般问题会比较少。51Testing软件测试网/ipB D egU

51Testing软件测试网)L gS4g*k.a[;J]

  而且你敢改人家的代码,看到有fail的test case 证明你有改错人家的东西,看到所有的test case都过了的话,你也很有信心说,我没有改错,或程序不会因为我的改动而挂掉。

e A8~m q3xg0

z,z Q]'M0  什么时候TDD51Testing软件测试网.t9D\j;@(N M

bo6lx H"kR ~+V0  TDD是在Unit Test,  也就是单元测试时用的方法。51Testing软件测试网1jE%L-e6f|wW,j^}

51Testing软件测试网t2|0p(uh4hqw/_ fX

  什么地方TDD

!`uGA.pt051Testing软件测试网 |+t3s:SE%p N0Q@,\{)@

  我觉得写任何代码都可以用TDD吧

T3p k8_v#x{0K6PT0

8LEy} Of0  怎么做TDD(关键5步)

8_R9tu7Kg3oi051Testing软件测试网N.IN)L6|-P$o(d.C2R^

  1、加入一个新的测试

_x2PW"z#x-_J051Testing软件测试网/^"[6cNZT

  2、运行下新加的测试,看到它失败(因为你还没写功能代码)51Testing软件测试网]|S;s R%A{ l3_ dd ]

51Testing软件测试网dW_^Vg

  3、对开发代码做很小的修改,目的就是让新加的测试通过 (注意这里的目的)

%q-v^%Z8e ^2gWOi;B0

r or!}8X Zq0  4、运行所有的测试(test case),然后看到所有测试都通过了 (看到测试都变成绿色,一般都会小开心一下)51Testing软件测试网'su.kHtL6z

51Testing软件测试网Sk@ Zjh$z

  5、移掉重复的代码,对代码进行重构 (既包括功能代码,也包括测试代码。特别注意红色的字串 一般会有重复,还有一些代码可以抽出来变成公用方法,测试代码中同样的初始化和还原测试环境的代码,可以放到intilize和cleanup中去)

ITRgKWxO%ddK051Testing软件测试网A0w}We/o

  而外还有一些步骤也是可以加入的,比方

BaD/Hs4Rl3[051Testing软件测试网x;h_gK0q+USC

  ● 在写测试代码前,先从需求出发,准备一个Test list (需要测到的功能的列表)。忘掉你该怎么实现,那是后面的事情51Testing软件测试网'lG4_#S ZyRg

51Testing软件测试网R{:z$f j8FY

  ● 每测完一个就用横线划掉

pg#MO#M#a9`051Testing软件测试网6Sy8U5l)o2B$[:P}0D

  ● 如果发现有漏掉的test 就加到这个列表中(列表测完你的功能也就完成了)51Testing软件测试网3ISZ+A(L|

51Testing软件测试网3Lw+XWB

  TDD的好处,和不足的地方

:j@ N[,bT;]b051Testing软件测试网.V$q9C:]i@#R

  好处

H@9{(d1GSAxM051Testing软件测试网|ye4lYO\-\NA

  ● 测试代码都是从客户需求出发的,不是重实现出发的。测试更关注于对外部的接口。

0D'{k+^ TRI7qle0

U(PL9RX+?5mEF0  ● 软件的需求都被测试代码描叙得很清楚,可以减少很多不必要的文档(有些时候写文档时间比开发时间多多了, 需要一个专门写文档的,而且用的机会很少。这里我很喜欢敏捷开发中说的:Just enough)51Testing软件测试网r7xsVV!W^

51Testing软件测试网mt\$l/s1w[ ^

  ● 每次都是很小的步骤,这样你就很集中注意解决一个问题。葛优说的:步子迈大了容易扯着蛋,步子大想的就多,容易忽视些东西, 容易出错。小而简单就是美

/Zc:Yk"tJr/K051Testing软件测试网+q ST%JB2a

  ● 可以优化设计。如果有做过测试驱动开发的会发现,为了更好的,更容易的做单元测试。它逼着你面向接口编程和使用一些设计模式,自然设计就灵活了,耦合性也低

&J3p N(`xt051Testing软件测试网;}U#EP@7On SG$}l

  缺点51Testing软件测试网bI$I"|O#T?A#B J)\

4[1XF9eNF0OP0  ● 有时候开发代码可能只有几行,可是测试代码可能比真正的代码要多很多。而且花时间想怎么测试。51Testing软件测试网y ogw#C

51Testing软件测试网yG7?l4{W

  ● 可能不适合时间很紧的软件开发,更适合于产品和平台的开发

1dB[ U8[1^f y1O051Testing软件测试网0jdySl RRD

  怎么学习TDD最好51Testing软件测试网'Q.s _0FR7^^

zY(z1K$~m0  我觉得最好且最快的方式就是 XP中提到的结对编程,一个有TDD经验的坐在“后面”,指导另一个不大熟悉的人,两人一起来完成一个类或模块的功能

jSB/Z2[)f0

#A0v2f I0Z#oQ1|0  几个关键点51Testing软件测试网 MR})QD@| lm

:u!@t^QeZ`\Q0  ● 记得你是做单元测试,不是集成测试,你要测得仅仅是你的类的功能,不要去测别人类的功能,一定要知道测到什么程度就好了,剩下的可能是别人需要测的

&aL\;f4z.u\4l0

:jR F)Q9egL1D i0  ● 每次都是一小步,目的只是用最简单的方法让新加的test case过掉而已51Testing软件测试网3sJh.Ku

;|D:jxl*[Q&pM0  ● 在改/加任何功能代码前,一定要先想是不是要改或加test case。51Testing软件测试网{f I+]#~*Mh

%O6xH M%]Q#o0  ● 测试驱动产生的单元测试代码是代替不了集成测试的,它还是单元测试51Testing软件测试网V d%N}`jH)U+m

51Testing软件测试网X;M,Z!C&?x`0D

  ● 测完记得清理测试环境,还原到测试之前的样子

{ cLmh7x0

TAG:

 

评分:0

我来说两句

Open Toolbar