BT

虚拟座谈会:TDD有多美?

作者 张凯峰 发布于 2011年2月23日 | 被首富的“一个亿”刷屏?不如定个小目标,先把握住QCon上海的优惠吧!

【编者按】最近酷壳的一篇有关TDD的文章引起了广泛关注,对于TDD一些人有自己不同的见解,为此InfoQ中文站特地邀请了InfoQ内外的敏捷专家特别是有丰富TDD实践经验的人,就TDD为InfoQ的读者分享他们自己的经验和体会。

InfoQ:请介绍你自己,以及TDD的实践经验。

熊节:ThoughtWorks中国公司首席咨询师,曾参与《重构:改善既有代码的设计(中文版)》、《J2EE核心模式(原书第2版)》、《Contributing to Eclipse中文版》等图书的翻译。目前正在从事Ruby on Rails的项目,并致力于敏捷方法与思想的推广。熊节从2003年开始实践TDD,从此以后使用此方法编写每一段交付使用的代码,直至今天。
鲍央舟:OutSofting的敏捷咨询师。在从事咨询工作之前,从事软件工程师的工作。接触、使用过一些TDD的实践,但是由于大环境的原因,没有深入使用。在从事咨询工作之后,和一些有经验的TDD高手做过Pair,也对TDD有了更深入的理解。
滕振宇:独立敏捷教练,InfoQ敏捷社区编辑,国内唯一的认证Scrum教练(Certified Scrum Coach)。从2005年接触到持续集成并开始实践,接下来开始接触并实践TDD以及Scrum等敏捷方法。
田乐:无限讯奇高级开发工程师,工作有7年,是一个前端后端都做的程序员。从07年开始使用TDD。
段念:Google中国高级测试经理,10来年软件开发与测试经验,主要工作方向在软件测试。在某些项目中实践过TDD,ATDD,在推动开发工程师的开发测试过程中对TDD有一些思考。

InfoQ:TDD跟Test是什么关系呢?TDD的T就是Unit Test吗?

熊节:可以是。也可以不是。关键在于,是不是都无所谓。我前两个星期就在干一个用Cucumber+Selenium直接写spec来驱动开发的项目,照样干得很清爽。

关键在于,TDD的T,是什么测试都无所谓。它就是设计。或者如果要把词汇定义得再准确点的话,你脑袋里的那个东西是“设计”,你在写生产代码之前写下来的那段东西是“设计的展现形式”,只不过它恰好是一个可以执行的JUnit或者whatever测试用例。

那么接下来应该问的是:什么是合理的设计的展现形式? 答案是,它应该是无二义的、可执行的设计的验收条件。因此你不仅可以说“我有一个设计”,并且可以说“我把设计记录下来了”,并且可以说“我写的代码是符合设计的”。而这后面两件事(尤其是最后一件事),我没有看到其他任何一种设计方法可以有效地保障。

所以“关注测试而不是设计”这种说法,它不是对不对的问题,它是可笑的。当你说一种设计方法不关注设计,你到底是在说什么呢?或者你不认为它是一种设计方法?那么当你说你使用了一种设计方法但你并不认为它是一种设计方法,你到底是在说什么呢?
鲍央舟:TDD更是一种工作方式,编码观念,而Test是这种观念中的一部分实践。具体说来,TDD的观念是先明确下一步要做的一小样东西,然后恰到好处的实现要做的东西,最后审核所做的质量,以此循环。Test是明确下一步东西后的产出,对实现的正确引导,也是审核将来代码质量的一个工具。按术语来说,TDD的T确实是unit test。Unit test是跟代码质量,编码思路密切相关的。也有ATDD,BDD之类的,与代码的外部功能相关。
:TDD跟测试的关系:
  • 测试是TDD的必然结果。如果团队一直在实践TDD,所有的代码都会有相应的测试,所有的测试其实就是整个系统的脚手架。
  • TDD方式的开发是从写测试开始的。
  • 使用TDD时,功能开发总是实现沟通结束条件,也就是在何种情况下,可以认为功能完成,这个结束条件是以测试体现的。
  • 实践TDD时,写代码只有两种目的:1. 让一个失败的测试通过。2. 在不添加新功能(也就是不需要添加新的测试)的前提下,让代码、结构或者测试更加清晰、整洁、易懂。

狭义上TDD的测试指的是单元测试,但是随着敏捷开发方法的发展,TDD又逐渐延伸发展出了ATDD(Acceptance Test Driven Development)和BDD(Behavior Driven Development)等。每种方法关注于不同的问题。在这里我用Google的敏捷和TDD教练Misko Hevery基于Mike Cohn的测试金字塔延伸出来的金字塔来说明敏捷开发中各种测试的关系。

  • 基于UI的测试,这一部分不可能做测试驱动,因为UI总是在最后完成的,不可能提前。
  • 功能测试,这一部分是关注于系统的业务逻辑,通常是用ATDD和BDD,是集成测试。这一部分保证系统做正确的事情(Do Right Things)。在迭带初期阶段,讨论用户故事的结束条件,用例子来体现,这些例子就形成了自动化的功能测试。
  • 单元测试,这一部分保证系统的每个单元(类和方法级别)的逻辑正确,更关注于正确地做事情(Do Things Right)。
但是这些不同的测试之间也没有明确的界限,每个人有不同的理解或者实现方式,很多人也会先从简单的单元测试着手,然后逐步把单元测试重构组合成集成测试用例。
田乐:TDD是从Test开始的,驱动开发过程的动力是失败的测试,Test是驱动设计的工具。TDD肯定需要有Test,不过Test大部分的时候都不是为了TDD而写的。TDD的Test不是Unit Test,它可以是Acceptance test(ATDD)、Functional test等等。一般来说TDD可以穿透测试的几个水平分类。

Test Category理论我记得以前InfoQ有写。单元测试对应的是集成测试。单元测试一般指对函数级别或者OO环境中的类级别的测试,特点就是没有外部依赖。集成测试是测试组件之间协作的测试,一般都会验证和用户需求有关的一些行为是否可以完成,也可以验证设计的组件协作是否可以完成。大型的系统还会把最顶端的集成测试叫做系统测试。AT或者UAT是从系统的外部行为验证软件的功能是否可以完成,它们在这种分层维度里面应该算系统测试,只是它要求这种系统测试是黑盒的。

功能测试是对应非功能测试的,就是是指验收的场景是否和Use Case有关。还有回归测试,它一般是用来验证曾经发现的缺陷的。

TDD中的测试可以是上面所有分类中的任何一种。
段念:TDD并不是石头里蹦出来的孙悟空,DBC(Design By Contract)可以看作是TDD的前身。在DBC的观点里,设计应该以规约(Contract)的形势体现,规约定义了被开发对象的行为。延续这个观点到TDD,很容易就能理解,TDD中的T,在表现形式上是“测试”,但其实,它更应该被理解为“对被实现对象”的行为限定,也就是DBC中的规约。“测试”只是用来体现规约的形式。

单元测试通常被定义为“对应用最小组成单位的测试”,它的测试对象通常是函数或是类,在对类的设计和实现应用TDD时,为类建立的测试通常与类的单元测试相当类似,因此TDD中的T往往被误认为是单元测试本身。实际上,这两者还是有显著的区别的。首先,TDD中的T描述的是规约,是设计的一部分;其次,TDD中的T并不明确要求T对实现代码的覆盖率;第三,TDD的T的侧重点是“描述被实现对象应该具有的行为”,而不仅仅是“验证该类的行为是否正确”。当然,TDD中的T在形式上是测试,在重构中也可以作为被实现对象的行为验证框架。

单元测试、集成测试、系统测试、用户验收测试是基于传统软件开发过程的划分,在传统软件开发观点中,这几类测试不仅意味这测试对象的不同,同样也以为着不同的测试在开发周期中处于不同的位置。但在敏捷开发中,如果继续使用这几个名词,最多也只能保留它们在测试对象方面的含义。对于TDD来说(ATDD和BDD可以认为是TDD的变体),在不同的测试类别中都可以应用之,唯一的区别在于T面向的对象不同。

InfoQ:你认为实施TDD需要怎样的前提条件?TDD难在哪儿?

熊节:要使用一种设计方法,你就必须(1)会做设计;(2)做设计。它难在有些项目不做设计,有些人不会做设计。
鲍央舟:实施TDD的前提是对TDD实践背后的观念有所理解,也需要有经验者的指导。TDD难在习惯和观念的转变。以前的工作方式已经在大脑和肌肉中固定下来,无法短期更改。另外,在短期可能呈现开发速度更慢的现象,需要管理层也对TDD以及质量有所理解,才能给予正确的支持。
:前提条件很简单,就是了解这种工作方式(可以通过读书,可以通过跟教练一起结对等),然后去坚持。

TDD很难:

  • 关键是人的因素,人的个人修养。类似于健身,人人都知道经常锻炼的好处,但是真正没有几个人去坚持,这需要很高的纪律性。
  • 要了解的东西太多,需要不断学习,如果不了解如何做好的设计,怎样去解耦等等,否则TDD会做得很痛苦。多数人却比较懒散。
  • 大家往往认为老的系统代码太烂,耦合度太高,无从下手。
田乐:前提条件就是需求明确,知道需求的边界,了解如何可以验收。另一方面TDD要经过一些练习。我觉得TDD的一个难点就是把它当作一个推动设计的工具,而不是停留在保证质量(如检查边界条件)这个层面。另外,由于TDD一般是从最外面的抽象开始的,所以我个人觉得TDD最开始的抽象模型选择也是一个难点。
段念:实施TDD是对开发者行为的比较大的改变,在我的经历中,遇到的主要难点应该是改变既有的开发工程师的开发习惯吧。TDD技术本身没有什么特别的要求,任何组织都可以直接应用。

InfoQ:TDD之于需求、设计、代码质量是怎样的关系和影响?

鲍央舟:对于需求来说,TDD更能引导开发人员做出真正符合需求的东西,不会过渡开发。对于设计来说,TDD的实践能帮你清理思路,但不能教会你做好的设计。对于质量来说,TDD保证所有的代码都有测试覆盖,肯定能提高质量。
:需求方面根据2002年Standish Group的报告,我们软件系统中有65%的功能是客户从来不用或者很少用到的。传统意义上大家认为敏捷开发应该让我们的团队开发得更快,生产率更高,这其实是很大的误解。与提高效率相比,使用Scrum,TDD能够帮我们从整个需求中确定真正有用的那35%,而且往往这35%的功能往往实现起来并不是那么困难。因为做得少,所以做得更快。

TDD与设计、代码质量方面,我想引用Keith Braithwaite在XPDay的分享话题“Measure for Measure”。他分析了很多的开源项目,发现有趣的现象,有自动化测试的那些项目,质量要好于没有TDD的项目(参见下图,所有有自动化测试的项目斜率(Slope)都是>2 的,想要了解斜率的具体含义,可以去听Keith的话题分享)

田乐:TDD会让你减少无用功,因为它迫使你从需求验收的角度入手,你必须在进入细节之前找到这个需求的边界,找到那些验收条件。TDD会锻炼自顶向下的的抽象分解能力,这对仅习惯从细节入手的程序员来说很有帮助。TDD可以提高你的代码的可测试性,它的节奏还可以帮助你做到简单设计。还有大家常说的,TDD有助于提高代码的内部质量。
段念:ATDD可以向上直接追朔到需求,使用ATDD方式,可以避免功能镀金,这是TDD技术带来的一个大的好处。在设计方面,TDD并不追求在最开始的时候得到一个完备的设计,而是遵循“够用的设计”的原则,保证开发者可以在短时间内得到可用的设计与实现。“够用的设计”是一个在敏捷环境下非常有效的原则,当然,也有些人反对这个原则,认为随意的设计无法随着应用的复杂性增加则很好的适应。在我看来,由于需求本身的不确定性,很难期望在一开始的时候就能给出保证能满足将来需求的设计,既然这样,不如遵循“够用的设计”的原则,通过重构等方式不断修正和优化设计。TDD对代码质量本身没有明确的关注,但如果开发者自觉地不断应用重构技术消除代码中的bad smell,在组织级别设计强制的code review,以及对单元测试覆盖率给出明确要求,则可以在很大程度上让代码质量保持在高水平上。

InfoQ: 你认为实施TDD容易犯的错误是什么?TDD的不足在哪些方面?

熊节:错误?陈皓同学已经向我们展示了。当你使用一把锤子时,你能犯的最大的错误就是尝试用它把钉子撬出来而不是砸进去。

不足?当你不知道该怎么用最理想的方式来描述你的设计,好吧,不管是因为什么原因,你当然只好退而求其次。你尽可以把设计的复杂和设计能力的欠缺归咎于你用的锤子。反正TDD又不会说话。不过,当你甚至不能为你的设计写出一个测试,你究竟打算用什么方式向别人讲述这个设计呢?或者也跟着退而求其次,反正我已经有设计了你就别管这个设计是什么反正我做出什么你就用什么吧──没错,很多人一直是这样工作的。
鲍央舟:过度编码!写完测试后,代码不止使新测试通过,还实现了很多别的东西。不足只是真正掌握比较难而已。
:容易犯的错误:
  • TDD的名字取得不好,大家往往产生误解,认为只要先写测试,再写代码就是TDD。在很多号称使用TDD的公司,这些测试甚至是测试人员写的(这不就是瀑布里面的V模型么?)
  • 不重构,只要让测试用例通过就结束。对于一个TDD的实践者来说,他往往花很少的时间去实现功能,让用例通过。他会花绝大部分时间去重构,去让代码变得更加容易理解,设计更加清晰。

不足之处:

  • 太需要实践者的坚持,“上士闻道,勤而行之,中士闻道,若即若离,下士闻道,大笑之,不笑不足以为道。”但是往往只有少数人会真正踏踏实实去实践。有些人三天打鱼两天上网,另外一些人会去嘲笑这种做法。
  • 很难去向公司上层以及项目经理去证明其价值。
田乐:我觉得TDD最容易出现的就是节奏问题,由于有的时候coding的非常尽兴,就没有遵循红绿红绿小步前进(baby step)的节奏,而是在没有失败的测试的时候就洋洋洒洒写下去。那样的做法其实就不完全是TDD了。TDD的不足是它不是万能的,不应该是强制的。不是所有的任务都需要TDD,那些临时的可抛弃的代码(如技术可行性试验)不需要TDD。强制的TDD和强制的单元测试一样,因为设计优略不容易量化,TDD也不能用TestCase的数量去量化,没法量化的实践不应该是强制的,否则会流于形式。TDD无法量化也是它被大规模推广的时候的一个不足。
段念:把TDD等同于单元测试,认为TDD只是“提前写单元测试”这种想法应该是很多不太了解TDD的人容易犯的错误吧。如果把TDD放到敏捷开发的大背景下,我倒不觉得TDD有什么明显的不足,但如果单独考量TDD在企业中的实践,TDD技术本身不关注代码的质量应该是一个明显的问题。应用TDD的企业通常需要采用持续的Code Review和Refactory方法保证通过TDD产生的代码的质量。

InfoQ:一般开发者需要多久能掌握TDD呢?请向读者推荐一下TDD的学习资料吧。

熊节:到他们掌握该怎么做设计时──which never happens to most people,请参阅《程序员的思维修炼》。 至于学习资料么,问豆瓣都比问我好。这事情也很悖论:能学会的人,读这些文字的价值约等于0,因为他只需要豆瓣搜索1分钟+阅读1小时──这是他anyway会做的事──就能得到同样的信息;读了这些文字觉得很有用的人,有鉴于Kent Beck那本书出版已经7年了,基本上,他已经没希望了。
鲍央舟:半年!网上一搜可以一大把资料,不过我觉得TDD光看是没用的,一定要和有经验的人pair!
:多久才能掌握TDD呢?这不是一个“敏捷”的问题,因为每个人的学习能力,和对学习的投入程度是不一样的,因此学习的“速度”也不一样,因此很难说需要多场时间。在这里我采用敏捷计划与估计的做法,我们先确定一下范围,然后每个读者根据自己的学习速度,自然就可以算出需要多场时间。

做好TDD需要了解很多的技巧、工具、原则,我想用Ron Jeffries的“敏捷技能的七个支柱”来说明需要掌握的东西。在这七个支柱中

  • 需要掌握“技术卓越”(Technical Excellence)
  • “业务价值”中的“用户故事”及“递增迭带式发布”
  • “自信”中的“持续集成”
  • “产品”中的“易学易用”

所有这些背后都隐含着很多的学习要点,这些要点需要通过读很多书、资料、与专家交流才能掌握。

TDD的学习资料

书:

  • Kent Beck的“测试驱动开发”
  • Martin Fowler的“重构”
  • Bob大叔的“敏捷软件开发原则、模式、实践”和“代码整洁之道”
  • Michael Feathers的“修改代码的艺术”
  • Gerard Meszaros的“XUnit模式”
  • Roy Osherove的“The Art of Test Driven Development”
  • Steve Freeman的“Growing Object Oriented Software Guided by Tests”
  • Eric Evans的“领域驱动设计”等。

视频

  • 到Google去查Kata
  • James Shore的“Let’s Play TDD”系列
田乐:不知道多久可以掌握。学习资料的话Kent Beck的TDD就很好,还有我觉得TDD很适合与设计的方法论一起看,如领域模型驱动设计等(《测试驱动的面向对象软件开发》就结合了这两个知识)。
段念:我们组织中有一些用于帮助开发工程师熟悉TDD的program,根据我的了解,一般的开发工程师可以在1-2周内掌握TDD工作方式,但一般需要更长时间来达到对TDD的熟练掌握和灵活应用。

评价本文

专业度
风格

您好,朋友!

您需要 注册一个InfoQ账号 或者 才能进行评论。在您完成注册后还需要进行一些设置。

获得来自InfoQ的更多体验。

告诉我们您的想法

允许的HTML标签: a,b,br,blockquote,i,li,pre,u,ul,p

当有人回复此评论时请E-mail通知我
社区评论

为什么我支持CoolShell的观点 by Wei Todd

我是TDD的学习和实践者,并且在Agile Tour 2010上做过TDD的报告。我相信自己对TDD的理解是到位的。测试用例作为一种需求(或者设计)的表达形式,这是TDD的核心理念。

但为什么我不赞同把TDD夸得过高呢?原因是TDD的测试强调Test First,而这是有问题的!不能执行的测试用例(TDD先写的测试)和能执行的测试用例有着天壤之别。在实际的软件开发中,你很难在没有执行测试用例的情况下写出真正符合最终需求的测试用例来。比如:你做一个页面,页面的效果需求通常会在真正可以运行之后不断调整。如果片面强调先写出测试用例(即理解需求),再实现,那么实际上隐含了“需求可以在实现之前固定下来”的假设,这是非常不敏捷的!我认为要做到真正的敏捷必须承认“需求无法在用户真正能运行看到效果之前固定下来“。所以,到目前为主,我赞同的方式是快速实现,通过demo方式体验效果,不断优化探索需求,最终固定需求把需求用测试用例表达出来。另外,多数情况TDD还是用于单元测试,那么单元的需求是哪里来的呢?单元的需求来自于更高模块的设计,也就是说高层模块的设计产生了底层模块的需求。而这种内部的设计具有很大的不确定性,在没有进行集成测试的情况下,很难讲这种内部设计(即单元需求)是否合理。实际项目开发通常会在集成运行之后不断调整内部的设计(即影响单元的需求)。那么,如果按TDD,单元的不成熟的单元需求表达为单元测试,实际上推迟了能进行集成测试的时间,对于真正快速弄清需求反而是不利的。

所以,我认为TDD的理念“把测试用例作为一种需求或设计表达形式”没错,但”Test First即可以在实现之前把需求具体化成测试用例“的理念错了,而真正符合实际开发的理念是“需求是在实际运行过程中根据效果不断探索调整得来的,不可能脱离实际运行写出真正符合最终需求的测试用例来”。所以,我们真正应该做的是尽快看到实际运行的效果,而测试作为需求或设计的表达方式是在看到效果,固定需求之后。过度的TDD只会导致迟迟看不到实际运行效果,看到效果需要调整需求又会废掉或改掉一大堆的测试用例。

当然,我不是全盘否定TDD,TDD在某些需求特别固定的场合是适用的。而TDD的先思考外部接口,外部设计的理念也对开发人员有很大益处。我的观点都是从学习实践中来的,有成功的经验有失败的教训,肺腑之言!

Re: 为什么我支持CoolShell的观点 by anchuan qian

1 提高软件质量
每一项功能都有测试来验证
添加新功能或修改bug时,回归测试集保证了不会破坏已有功能
2 测试是可执行的文档
测试是对程序功能和用法的说明,帮助你理解代码
可编译,可运行,保持同步
3 驱动设计,拥抱变化
产生可测试的程序,低耦合的代码,得到好的设计
事先设计 vs 测试驱动
事先设计应该尽量粗线条,尽量将决策时间推后
4 快速反馈,增强信心
问题发现的早,修改得快,成本越低,TDD,缩短反馈周期,降低成本
TDD反馈时间短,能够看到前进的步伐,增强信心

并不是TDD对设计的要求高,是有些团队的设计能力跟不上。还处于温饱阶段,忙于应付代码的外部质量,能把功能做出来就已经很不错了,哪有心思和精力去关注内部质量呢。

Re: 为什么我支持CoolShell的观点 by Wei Todd

这些都是在假设测试用例反映了需求的情况下成立的,这个假设本身不成立。单元测试用例是基于开发人员的假设,实际到了集成环境,发现假设根本不对,测试用例整个作废,那么什么提高软件质量,可执行文档,快速反馈,这些神马不都浮云了?!

Re: 为什么我支持CoolShell的观点 by anchuan qian

你的假设是,开发人员在做开发的时候,已经错误了解了需求,或者是不知道自己在做什么。这是个很有意思的假设。
我以前写了一篇文章《TDD是一道坎》,我给你抄一段:


TDD对开发人员要求很高(Too Difficult To Do)。因为TDD不再是单纯的堆砌代码,TDD是:

1. Test First,也就是在写代码之前先必须完全理解业务,因为如果不清楚自己要做什么(业务没有理解清楚)就根本无法写测试
2. Use it before implement it, 这就更难了,也是我们这里最需要的。实现一个函数之前,先使用它。这就督促我们对代码进行解耦,如果程序之前依赖太多,那么函数就很难被独立使用,换句话说就是写单元测试非常困难。所以,我们也称TDD为设计驱动开发。
3. 提前对代码的功能进行验证,每一块代码都得到事先的验证,并且是自动化可回归。
4. 尽量一次性的把代码写好。TDD要求大家从测试和质量的角度思考问题,尽可能的考虑所有的边界条件和异常分支
5. 支持重构,为代码和架构的演变提供了一张牢固的安全网

Re: 为什么我支持CoolShell的观点 by Wei Todd

>>Test First,也就是在写代码之前先必须完全理解业务,因为如果不清楚自己要做什么(业务没有理解清楚)就根本无法写测试

这显然是不敏捷的,是典型的瀑布思维。真正的需求是必须在实际运行过程中逐步调整得出的,比如:用户让你做一个系统,你完全按照他说的先做了一个拿给他看,他说这不对,那要调,结果导致你一大堆测试用例作废。你说是这个用户错了,还是你错了呢?

Re: 为什么我支持CoolShell的观点 by Wei Todd

>>Use it before implement it, 这就更难了,也是我们这里最需要的。实现一个函数之前,先使用它。这就督促我们对代码进行解耦,如果程序之前依赖太多,那么函数就很难被独立使用,换句话说就是写单元测试非常困难。所以,我们也称TDD为设计驱动开发。

TDD的问题正是根本不可能Use it before implement it。能执行的测试用例和不能执行的测试用例(Test First的用例)是有区别的。你写测试用例来了,不代表你能执行它,不代表你能看到实际运行的效果。

Re: 为什么我支持CoolShell的观点 by X 1073

何苦要追究谁对谁错,如果开发的东西不是客户想要的,改就好了。开发者总可以在给客户提供可见的东西之前自己建立起这东西的“形态”,换句话说总是有东西可以做的。以前很多人用建筑行业和软件行业做比较,我不说这是错,但有些方面肯定不合适。比如,2楼有一堵墙,发现它不太对,“重构”这堵墙很可能是巨大的工作,因为这时候3楼都已经建好了;软件与这个不同,一个函数有问题,需要“重构”,开发者要做的就是“干”掉它,重新写点代码。如果开发过程中有什么东西最不值钱,那就是“代码”了,需要的是开发者的勤奋和勇气而已。

你这种一开始就希求给用户一个“他想要的东西”的基调,就很不“敏捷”。

Re: 为什么我支持CoolShell的观点 by Teng Daniel

瀑布思维是指在做一件很复杂的事情之前,把所有的需求都搞清楚,然后再去开发,而事实上是大家什么都搞不清楚。

而在敏捷中,不追求把整个事情都搞清楚,我只是在把整个复杂的事情抠出一点点最高优先级的事情,然后把这一点点儿事情搞清楚,做出来,这一部分就是Test Case。然后再去找下一点点最高有限级的事情,不断重复。每一步做的事情,方向都是十分明确的。这个一点点事情的粒度,对于ATDD来说可能是未来一两天的事情,对于TDD来说可能是未来几分钟的事情。

这种座谈会真的好亲切呢,有没有!!!有没有!!!有没有!!! by Xiang Ran

- -

Re: 为什么我支持CoolShell的观点 by Cai John

"这些都是在假设测试用例反映了需求的情况下成立的,这个假设本身不成立"
我觉得这里有逻辑问题,要是假设程序员对需求的理解是错的,那么测试用例当然是浮云,问题是,在这种假设下,什么不是浮云呢?最好停下来什么也不要做。
其次单元测试是关于设计的,不是关于需求的。它是设计的一种文本表示,既然开始写代码了,当然假设我理解的需求是对的。至于说“有可能对需求理解错了”,这是敏捷里“短迭代和快速反馈周期”要解决的问题,与TDD何干?

Re: 为什么我支持CoolShell的观点 by Wei Todd

@Cai John
>>问题是,在这种假设下,什么不是浮云呢?最好停下来什么也不要做。
不是停下来不什么都不做,而是少做无用功。尽快集成,不要在自作假设的内部单元测试浪费时间,这就是少做无用功;一旦集成之后能实际运行看到效果,就不再是浮云了,就是实打实的了。

>>其次单元测试是关于设计的,不是关于需求的
设计和需求本身没有明确的界限,如果一个单元连对它的需求都没有,你还设计它做什么?当你设计它的时候你是否要考虑设计应满足需求?实际上,高层模块的内部设计就产生了对底层模块的需求,这就是需求与设计的关系。

>>这是敏捷里“短迭代和快速反馈周期”要解决的问题,与TDD何干?
TDD恰好能妨碍快速反馈。做了一大堆自作假设的单元测试,大大推迟集成测试的时间,导致需求的问题迟迟不能发现,这就是TDD的问题!

Re: 为什么我支持CoolShell的观点 by Cai John

1,如果集成后让end user看效果,发现需求理解错了,TDD当然是无用功。但反过来,如果对了呢?而且在User Story足够小的情况下,需求对的概率远超需求错的概率。
2,如果ATDD的TestCase是有end user自己或者辅助写的,作为UserStory的一部分,需求理解错的几率就又更低了。
3,现实中的确大量存在开发团队自己猜需求的情况,在这种情况下,你对TDD的担忧是成立的。——不过在这种场景下,是TDD错了?还是环境错了?开发团队错了?我认为工具本身没有对错,Context和使用工具的人才是关键。

Re: 为什么我支持CoolShell的观点 by 曹 云飞

看了一下Cucumber,发现Cucumber还能这样用:
Scenario: User is not signed up
Given no user exists with an email of "email@person.com"
When I go to the sign in page
And I sign in as "email@person.com/password"
Then I should see "Bad email or password"
And I should not be signed in
这段文字是关于用户登录的需求描述,同时还是一段实际项目中关于用户登录场景的集成测试“代码” 。
你要快速发现需求,那么在开发前把需求写出来不会太影响进度吧,因为即使你不写下来,你在开发前头脑中总是通过思考要形成这样一些类似的文字的,写出来帮你整理了思维,写的过程本身占用时间不多吧。而这段需求又是可测试的,能够通过测试来检验需求,重构代码的时候还能校验是否影响了需求,这样的TDD是否大大推迟了需求发现呢?也许是工具/语言/能力影响了需求发现的速度。

Re: 为什么我支持CoolShell的观点 by Wei Todd

@曹云飞
我提倡在第一次集成运行测试之前不要写单元测试用例;自动化的验收测试用例则视编写和维护的代价而定,如果代价比较高,则应该适合采用文档和Use Case来描述需求,因为这两种方式比自动化的验收测试更容易维护。编写单元测试一定是在集成以后,这样才能首先得到外部反馈,先尽量保证做正确的事情, 避免做无用功。

你的例子由于不是自动化的验收测试,更接近一种Use Case,这是一种值得提倡的方式。

Re: 为什么我支持CoolShell的观点 by Xiong Jeff

实在看不下去了…

> 你的例子由于不是自动化的验收测试,更接近一种Use Case,这是一种值得提倡的方式。

你那只眼睛看见它“不是自动化的验收测试”啊…麻烦你,Google “cucumber scenario”,点击第一条结果。

所以我一开始就说嘛,能学会的人他不需要看这些文字,不能学会的人他看了也是白看。

Re: 为什么我支持CoolShell的观点 by anchuan qian

>>Test First,也就是在写代码之前先必须完全理解业务,因为如果不清楚自己要做什么(业务没有理解清楚)就根本无法写测试

你的观点好奇怪,为什么这就是典型的瀑布思维?

你都没有搞清楚User Story的需求,就盲目的编程,你这还是敏捷吗?

你不知道有一种东西叫做”界面原型“吗?

还有作为一个开发团队,千万不要”完全按照他说的去做“。你要搞清楚背后的业务目标和价值,不是盲目的按照客户的说法去做

Re: 为什么我支持CoolShell的观点 by Wei Todd

>>也就是在写代码之前先必须完全理解业务,因为如果不清楚自己要做什么(业务没有理解清楚)就根本无法写测试
>>为什么这就是典型的瀑布思维?

因为瀑布思维就是一个阶段一个阶段层层推进,先把需求弄清楚,然后用需求来驱动实现。TDD无法是把需求用测试用例的方式表示而已。真正的需求不可能是这样编写出来的,真正的需求是在实际运行过程中逐步调整完善得出的。因为Test First编写出的测试用例并不是真正的运行效果,也就是说在实现之前无法确定你这个用例本身对不对。

Re: 为什么我支持CoolShell的观点 by Wei Todd

>>你都没有搞清楚User Story的需求,就盲目的编程,你这还是敏捷吗?
User Story和TDD有必然联系吗?不用TDD就是盲目编程不敏捷吗?

>>你不知道有一种东西叫做”界面原型“吗?
“界面原型”是TDD吗?

Re: 为什么我支持CoolShell的观点 by Cai John

实在看不下去了…

> 你的例子由于不是自动化的验收测试,更接近一种Use Case,这是一种值得提倡的方式。

你那只眼睛看见它“不是自动化的验收测试”啊…麻烦你,Google “cucumber scenario”,点击第一条结果。

所以我一开始就说嘛,能学会的人他不需要看这些文字,不能学会的人他看了也是白看。

不能学会,有些是因为悟性差,有些事因为没有倒空自己杯子的勇气。
而且会的人和不会的人,都会把对方认作是“不会”的人,呵呵,Jeff很无奈吧?

Re: 为什么我支持CoolShell的观点 by anchuan qian

文字回复,信息太容易丢失了,估计大家也不会讨论出一个一致的结果。

>>你都没有搞清楚User Story的需求,就盲目的编程,你这还是敏捷吗?
我是想说不管用什么开发方法。当你在开发一个功能之前,一定要拿着”放大镜“搞清楚这个功能的需求,然后再进行编码。

敏捷更是强调一点。敏捷不做详细的需求分析,是指不试图一次做完所有的需求分析。但是在每个迭代之前,都会拿着"放大镜"对每个需求进行详细的分析。

>>你不知道有一种东西叫做”界面原型“吗?
如果你想和客户确认这个功能是不是他想要的,我有一个建议,你可以试试”界面原型“。这样更快速,而不是等功能做出来了再确认,会出现返工的情况。

Re: 为什么我支持CoolShell的观点 by M. Jwo

TDD的问题是在某些公司的首席咨询师这般的人把他当作宗教,神爱世人你不让我爱就是你的错!或是说没看过哪本出版了很久的书就是没希望的一样,还是说cucumber scenario有多啥了不起。
不管是CoolShell还是Wei Todd都没说测试是不好的,甚至都推崇Unit Test等自动化测试,只是不赞成盲目的先写没有用的test case。这篇文章除了那有宗教情节的咨询师外,其他人的论点基本上只能证明auto test case是好的,跟CoolShell还是Wei Todd没有抵触。
那些几年内做了一堆项目的咨询师来说自己多好,殊不知李光耀也没法治理中国,因为人数规模不同!当你面向的是一个三年一期的项目,三、五千个交易画面,后端的流程是不同的资料来源(DB, EAI, Host, SAP...),那些source还几天就会变更一次,甚至要求每个画面要100ms内结束的时候,跟那种简单CRUD画面又是不同的作法。通常的作法是先写好程式,让使用者测试到差不多,等到各方的source资料的需求比较确认的时候才来做test case,而不会作重功。
通常那些咨询师来指导后,不成功是没有完全照他的说法作,成功了是他的方法论太好了!

Re: 为什么我支持CoolShell的观点 by M. Jwo


>>你不知道有一种东西叫做”界面原型“吗?
如果你想和客户确认这个功能是不是他想要的,我有一个建议,你可以试试”界面原型“。这样更快速,而不是等功能做出来了再确认,会出现返工的情况。

我的客户常常想要真的测试过系统后才来改需求!是的功能齐全后才来改功能,界面原型没用。

Re: 为什么我支持CoolShell的观点 by Teng Daniel

我同意John,如果不知道下一步(下一个迭代做什么),那就不如停下来,等一下PO。这其实也是为什么绝大多数敏捷团队失败的原因。

能做的需求必须十分具体,能够具体化到实例,Test Case。

Re: 为什么我支持CoolShell的观点 by Wei Todd

@Teng Daniel
>>我同意John,如果不知道下一步(下一个迭代做什么),那就不如停下来,等一下PO。这其实也是为什么绝大多数敏捷团队失败的原因。
声明一下我们的讨论基础,假设PO已经明确了User Story,所以,从大面讲不存在不知道做什么的问题。而是说在知道User Story以后,我们是采取TDD策略先做一堆单元测试再集成?还是先集成后单元测试?

>>能做的需求必须十分具体,能够具体化到实例,Test Case。
User Story对应集成测试,要自动化起来很多场合都不是那么容易,Web虽然有不少通用的框架,但如果是游戏或者其他比较专的情况怎么办?而且不管是自动化也好,还是写在纸上的手动用例也好,由于其无法执行的特点,比起Use Case对开发的指导来讲没有什么好处。

Re: 为什么我支持CoolShell的观点 by 田 乐

实际的软件开发中,你很难在没有执行测试用例的情况下写出真正符合最终需求的测试用例来。比如:你做一个页面,页面的效果需求通常会在真正可以运行之后不断调整。如果片面强调先写出测试用例(即理解需求),再实现,那么实际上隐含了“需求可以在实现之前固定下来”的假设,这是非常不敏捷的!

我觉得这个说法有点偏激了。TDD也不是对需求的体现,而是对你理解的需求所对应的设计的体现。上面这种说法比较像做ATDD的时候的疑问,因为如果从验收测试驱动,难度会比较大,如何写出不脆弱的验收测试是个坎(这是测试技巧)。但是TDD可以从一个纵向的逻辑模块或者某一个横向分层开始,或者在OO的环境中就是一个类,每个Test都验证自己对设计的下一个期待,驱动设计的进行。如果这个时候发现需求都不清楚,那绝对应该返回去想好需求。

Re: 为什么我支持CoolShell的观点 by 田 乐

“界面原型”是TDD吗?

界面原型是交流工具,减少用户和实现者对“界面”设计的误解,确定大家对这个交互/界面的理解是一致的。在实现阶段界面原型是一个Spec,指导实现和验收。

Re: 为什么我支持CoolShell的观点 by Wei Todd

>>我觉得这个说法有点偏激了。TDD也不是对需求的体现,而是对你理解的需求所对应的设计的体现。上面这种说法比较像做ATDD的时候的疑问,因为如果从验收测试驱动,难度会比较大,如何写出不脆弱的验收测试是个坎(这是测试技巧)。
TDD的测试用例当然是需求的体现,参加Martin Fowler的文章Specification by Example: martinfowler.com/bliki/SpecificationByExample.h...

正常需求/设计的产生本来就是在需求和实现之间相互反馈中逐步明确的,需求和实现直接不存在绝对的谁驱动谁的关系。瀑布试图在初始阶段做出完美的需求分析,TDD和瀑布比没有本质的区别,只不过需求的形式是(验收)测试用例而已,这都不是真正的敏捷。真正的敏捷应该承认“需求的产生依赖于实现的反馈”。虽然TDD试图用测试用例的方式把需求表现得更加精确,更加生动,贴近真实的运行效果,但是无奈先写的测试用例毕竟不等于运行的实际效果,你写出了测试用例不等于你就真实地把运行效果给用户看到了。所以,TDD的测试用例并没有能够在更好地理解需求和做好设计方面比Use Case更进一步。相反,自动化验收测试的开发和维护难度较大,而且除了Web领域,在很多领域没有成熟的技术方案。

>>但是TDD可以从一个纵向的逻辑模块或者某一个横向分层开始,或者在OO的环境中就是一个类,每个Test都验证自己对设计的下一个期待,驱动设计的进行。如果这个时候发现需求都不清楚,那绝对应该返回去想好需求。
单元级别的TDD在实际开发中,尤其是开发的初期更是非常的不靠谱。搞了一堆测试用例满屏绿色,代码覆盖率80%以上,看上去很爽,结果一集成一堆错误。请看InfoQ文章《Mock不是测试的银弹》的描述:
“在使用JMock框架后测试编写起来更容易,运行速度更快,也更稳定,然而出乎意料的是产品质量并没有如我们所预期的随着不断添加 的测试而变得愈加健壮,虽然产品代码的单元测试覆盖率超过了80%,然而在发布前进行全面测试时,常常发现严重的功能缺陷而不得不一轮轮的修复缺陷、回归 测试。为什么编写了大量的测试还会频繁出现这些问题呢? ”

我相信这段描述是真实的,包括我在内的TDD实践者都遇到了这样的情况。为什么会这样?原因是在没有集成之前,各个单元的设计都是基于开发人员的假设,这个设计是未经验证的不成熟的,随时可能变动;基本上,我们在集成中都会发现单元层面考虑不周全或者假设不成立的情况。所以,真正的敏捷不是在集成之前搞一堆开发人员自作假设的单元测试,而是尽快集成,实际运行看到效果,稳定需求和设计,发现单元层面没考虑到的问题。先保证做正确的事(集成或验收测试),再保证正确的做事(单元测试),这是普遍认同的道理,而TDD恰好本末倒置,先单元再集成,倒置大量的无用功,一集成就一堆的单元测试作废或者需要修改。

Re: 为什么我支持CoolShell的观点 by Wei Todd

>>界面原型是交流工具,减少用户和实现者对“界面”设计的误解,确定大家对这个交互/界面的理解是一致的。在实现阶段界面原型是一个Spec,指导实现和验收。

或许你误解我的意思了。我们在质疑TDD,他不用TDD来应招,反而求助于“界面原型”,这是不是见解地已经说明了TDD抵挡不住?

Re: 为什么我支持CoolShell的观点 by anchuan qian

我不是来应召,感化大家信奉TDD的。用不用TDD是你自己和你团队的选择,和我个人没有任何的关系。

我回复,是因为我不赞同你的观点。

TDD可以驱动软件设计:

1、TDD是软件开发和设计方法,并不是说TDD==好的软件设计。我不知道你个人对TDD的期望到底是什么?你期望TDD能帮助你解决哪些问题?

2、你没有搞清楚客户的需求,基于自己的假设就开始编码,搞了一堆测试。然后抱怨TDD不行。所以,我建议你用界面原型先去和你的客户确认。搞清楚做什么之后,再进行编码。因为TDD是不能帮你做需求分析的。

3、我自己做过一个商业产品(我做了3年),从第一天开始整个团队都是用TDD的方式工作,不知道为什么从来就没有出现过:”废掉一大堆测试的情况“

再补充一些观点 by Wei Todd

Test First要求写测试用例时对软件需求有精确的了解。用户需求和外部环境是影响软件需求的两大因素,用户需求是指用户所期望的效果,它从目标的角度影响了软件需求;外部环境是指软件所运行和依赖的外部环境,它从实现基础的角度影响软件需求。而实际开发中我们面临两大问题:1.用户需求在实际运行前的不确定性;2.外部环境在实际运行前的不确定性

用户需求的不确定性是指“需求无法在用户真正能运行看到效果之前明确下来“,比如让你开发一套Wow这样大型的游戏,你能想象游戏的效果是设计者一开始就想好了精确到每一个细节吗?而且,对于游戏这样的产品,测试用例几乎不可能在实现之前写出来,所以即使游戏设计者脑子里已经有了游戏应该是什么样子,他也无法写出自动化的测试用例来。所以,实际上,游戏的设计者通常只能借助文档,草图,Use Case等非精确的方式大致提出需求,在看到效果之后才能逐步地细化和明确。

外部环境的不确定性是指当我们的系统需要和第三方的系统集成时,关于第三方系统行为的假设也无法在实际集成运行前完全确定,比如:你做一套股票客户端系统需要连上交易所系统,尽管通常交易所会有相应的协议,但实际开发过程中,协议会有很多定义不清晰或未定义,甚至有实际行为与协议不符合的地方,这样我们只有先做假设实现,然后在交易所提供的测试环境中去确定。对于像交易所这样非常重视质量的环境都存在协议定义不清或者不全必须在集成测试时才能弄清楚的情况,对于普通的第三方更是可想而知。如果是测试驱动,需要识别出被测系统的边界并模拟出外部环境,你如何去模拟交易所?即使你愿意投入很大的精力去模拟,在最初没有明确其行为的时候你的模拟是没有依据的假设,随时可能在真实集成后被推翻。所以,Test First需要对于被测系统的需求和环境有精确的了解,而由于需求不确定性和外部环境不确定性两大问题,Test First在很多时候都是不现实的。其实,Test First和瀑布式思想没有区别,都强调需求先于实现,而忽略了软件需求的产生是一个在实际运行中不断调整探索完善的过程。TDD无非是把需求分析的结果用测试用例表达,替代传统用文档表达需求,但从宏观上看,TDD和瀑布比是换汤不换药。除了简单情况,不存在脱离实现的需求,你能够在明确了需求之后就实现出一套linux系统吗?既然你根本无法实现一套linux系统,那么这样所谓的需求又有多大的意义呢?所以,能提出什么样的需求不能脱离你的实现能力。需求和实现之间不是简单的谁驱动谁,而是一种相互反馈的关系,这与需求用什么方式表达没有关系。正如瀑布模型无法在初始阶段做出完美的需求分析,TDD也无法在初始阶段做出完美的测试用例,不仅如此,自动化测试用例的开发维护成本还远高于文档。到目前为主,我推崇的方式是快速实现,在实际运行中体验效果,不断优化探索和明确需求和外部环境,当需求和对外部环境的认识达到一个比较稳定的程度才编写测试用例将需求固化下来。

TDD是不是以开发效率换代码质量(原标题:单元测试/TDD的成本和收益)? by Lee Vincent

Re: TDD是不是以开发效率换代码质量(原标题:单元测试/TDD的成本和收益)? by ren jacky

思想和流程都很好。遇到的现实开发,太多都关注是SIN的时间。残酷的现实。

Re: 再补充一些观点 by Yu Chen

Todd,我不觉得TDD有这些问题。我感觉有这几方面:
* TDD不是万能的,他解决的是设计的问题。就像需求搞不清楚不能抱怨Java语言一样,需求搞不清楚也不要抱怨TDD。
* 至于TDD是不是放大了需求搞不清楚的问题,有可能。不过要看比例,以我的经验看,比例不会太高,也就是说问题不大。如果在你的环境下,需求问题的比例很大。前面介绍的界面原型是个很好的方法;找会做的人做需求,说不定更根本。
* 瀑布和迭代的区别在于粒度。本质上做好开发,就要先需求,再设计、编码…如果粒度是整个项目,那就叫瀑布;如果是几个星期以内,那就是迭代。TDD和瀑布确实在一定意义上相似;但是你说做TDD就变成瀑布了,不准确。
* 你说做TDD要模拟整个交易所,我很怀疑你对TDD的了解是不是准确。特别是单元测试,应该隔离其他部分的,不是吗?TDD也没说,除了自动测试,别的测试都不做了。
* 如果对环境不了解,就想办法去了解,认真读资料,技术原型、界面原型等等…在了解之前,就开始做很多后面的工作,确实会有很多浪费的;好的项目管理应该可以避免这类问题大量发生。

熊节已经说的非常清楚了 by jiang guimin

“T,是什么测试都无所谓。它就是设计”。为自己的设计写几行测试代码这实在是必须的一件事情。有了测试在先,并且测试执行起来,快,准,狠那么接下来的代码实现就非常方便。

Re: 为什么我支持CoolShell的观点 by 李 宁

敏捷不就是解决一开始不可能搞清楚业务目标和价值的问题而存在的吗?

如果打算搞清楚之后再去编程,那不就又瀑布了吗?

如果走界面原型而不是开发实际程序,那界面原型对于用户有实际的价值吗?

敏捷的理解 by Yu Chen

敏捷要解决的问题是一开始不可能搞清楚整个项目的需求。这不是说,任何功能点的需求都是搞不清楚的。
敏捷方法是说,我们关注最有价值的点,把他们先开发出来,在这个过程中增进了解,一点点开发。具体到每一个点,开发过程是和瀑布差不多;但是,每次的关注点变少了,容易做好。
界面原型是开发者和用户之间沟通的一个工具。如果你知道有很大的可能,你做的用户不会完全接受,你是选择把他整个后台逻辑做好,让用户否定掉;还是选择只做界面,看看用户会不会否定掉呢?所以界面原型的价值就在于,探讨需求的过程,成本降低了。

毛泽东思想是正确的思想,错误的那部分不属于毛泽东思想 by 半瓶 墨水

看到这么多为敏捷的辩护,让我首先想起这句话:毛泽东思想是正确的思想,错误的那部分不属于毛泽东思想

我想问问敏捷的爱好者们,能不能先给“敏捷”一个定义?

别到时候争论了半天,你跳出来说:靠!这就是敏捷啊!
或者是当别人举出反例,又说:你说的那个,不是敏捷。

如果一个东西就像政治书里面定义毛泽东思想那样循环定义,它本身可能会是自洽的,但他什么都不是,除了名字之外

Re: 毛泽东思想是正确的思想,错误的那部分不属于毛泽东思想 by 吴 能

照熊节的思路回答此问:“这事情也很悖论:能学会敏捷的人,读这些文字的价值约等于0,因为他只需要豆瓣搜索n分钟+阅读n小时──这是他anyway会做的事──就能得到同样的信息;读了这些文字觉得很有用的人,有鉴于敏捷软件开发宣言出来已经10年了,基本上,他已经没希望了。”。

Re: 为什么我支持CoolShell的观点 by Tseng Joseph

"这些都是在假设测试用例反映了需求的情况下成立的,这个假设本身不成立"
我觉得这里有逻辑问题,要是假设程序员对需求的理解是错的,那么测试用例当然是浮云,问题是,在这种假设下,什么不是浮云呢?最好停下来什么也不要做。
其次单元测试是关于设计的,不是关于需求的。它是设计的一种文本表示,既然开始写代码了,当然假设我理解的需求是对的。至于说“有可能对需求理解错了”,这是敏捷里“短迭代和快速反馈周期”要解决的问题,与TDD何干?


这个回复很给力。原来的归因的推断逻辑上不成立。 TDD最重要的价值在于反馈的速度和质量:UT反馈内部质量和how,AT反馈外部质量和what。 如果开发人员理解需求错误的情况下,憋了很长一段时间才发现,很可能就是因为没有反馈“外部质量”的后果,这不是TDD的问题,反而是没有执行好ATDD的问题。

UT对于理解外部需求有帮助作用,但不能完全覆盖,否则也不会提出ATDD和BDD了。

还有一种情形就是设计很差,不重构,导致实现代码和测试代码很多重复,需求稍一变动就难以维护,痛苦不堪。 这种情形也不能归咎于TDD方法,无须多解释。

Re: 为什么我支持CoolShell的观点 by Tseng Joseph

是的。

Re: 毛泽东思想是正确的思想,错误的那部分不属于毛泽东思想 by Tseng Joseph

所以现在大家都倾向于不只提“敏捷”了啊,更多的是讨论具体的实践,能落地讨论,能辨别的。

现在空对空讨论敏捷的人都是借地儿吆喝的人,有个段子就说:让他们全家都敏捷去吧—— 呵呵

Re: 为什么我支持CoolShell的观点 by xu shanchuan

首先,TDD显然不是哪里都可以用的东西,这点是不应该被夸大的,每项技术都有自己的适用情景和适用范围。你说的界面这种东西显然是在不断的改变,TDD这里行不通。
TDD的一个好处是让你在写TDD的时候好好想想你的需求到底应该是个什么样子:这就像某个人说的那样,写是为了更好的思考,你在实实在在写下来你的需求的时候会更详细的想你的需求,何况这种形式的需求之后会反过来验证你做的事情。

Re: 为什么我支持CoolShell的观点 by 好 人

我想说得是这位哥们领导了一个很垃圾的项目的开发,号称敏捷开发,甚至是XP。现在导致了什么情况?这个项目几乎没有任何的需求和其他文档,导致新来的人迟迟不能融入团队,先来的老员工可以利用自己所掌握的业务等其他知识,集体(大部分人)构成了对公司的绑架,我不知道在你领导下的敏捷开发模式有没有你们这些教众所谓的TDD?可笑的公司还给硬性的规定了提高单元测试覆盖率,不达标就扣奖金,然后一帮人就专门抽出时间来写UT,注意,这是为测试覆盖率为奖金整出来的测试代码,是事后整出来的测试代码,这就是所谓的TDD?亚洲第一人领导下整出来的TDD??还有一个叫张什么的,整天张口闭口谈TDD,号称第一高手,可是问他有在项目中实践过没有,回答是没有,难以实现,因为我还没到这个境界!大家注意,这人号称第一高手(是不是第一高手暂且不谈,至少是个有不少工作经验的人,写过书的人),他做不到,你们说可笑不可笑。所以你们这帮人在这里鼓吹TDD,哪怕真有人做到了,那也只是1%的人玩得东西,所以这些JP的敏捷咨询师呀,就不要来忽悠人了。既然这都是自己做不到的事情,盲目崇拜,那你们这些TDD,敏捷的教众跟法轮功教徒又有何区别呢?

允许的HTML标签: a,b,br,blockquote,i,li,pre,u,ul,p

当有人回复此评论时请E-mail通知我

允许的HTML标签: a,b,br,blockquote,i,li,pre,u,ul,p

当有人回复此评论时请E-mail通知我

43 讨论
提供反馈
错误报告
商务合作
内容合作
Marketing
InfoQ.com及所有内容,版权所有 © 2006-2016 C4Media Inc. InfoQ.com 服务器由 Contegix提供, 我们最信赖的ISP伙伴。
北京创新网媒广告有限公司 京ICP备09022563号-7 隐私政策
BT

We notice you’re using an ad blocker

We understand why you use ad blockers. However to keep InfoQ free we need your support. InfoQ will not provide your data to third parties without individual opt-in consent. We only work with advertisers relevant to our readers. Please consider whitelisting us.