http://david.heinemeierhansson.com/2014/tdd-is-dead-long-live-testing.html
Update:
DHH:
Kent Beck: RIP TDD
Model 测试先写还是很方便的,View 和 Controller 测试先写就有点头疼了。
其实最关键的是:要有测试,也就是 Long live testing.
稍看了下里面的链接的 pdf,感受到了一些观点: 1、系统测试的性价比最高。 2、过度追求覆盖率会伤害到设计与开发。 3、单元测试只在必要的时候做。 4、review 比单元测试更重要。
个人感觉测试就是规范,是质量的保证,对大团队大项目来说更重要,但你付不付得起代价是另一回事。 dhh 应该是反对把 tdd 或 unit test 的重要性绝对化。
Give Capybara a spin today, and you'll have a good idea of where we're heading tomorrow.
D 大神钦点 Capybara 啦!
我就觉着 tdd 并不是最适合的,我在开发的时候,大部分 code 的最终结构和刚开始理解问题是写下的很不同的,除非是超级明白人或者资深工程师,看到问题后对于 class,method 会用到哪些都成竹于胸,用 tdd 是一种不错的方法,而我在工作时候大部分时间都是在处理新问题,用 tdd 反而做许多无用工。
当然自动 test 是很重要的,不指望能真正测出什么 bug 来,真正一套完整的测试是能让你每次加新功能时候确保和以前的 code 没有冲突
肉测的胜利!!! @lgn21st @hpyhacking 好吧文章我只看完第一段。。。。
TDD 目前只在写 lib 还有修 bug 时候用,因为目标十分明确,而且通过用例来描述问题比用文字简单、清楚多了... 业务方面,在允许错误的场景下,还是倾向肉测,首先写代码的时候可以保证业务逻辑的正确,业务变动相对频繁,而且刷新页面明显比修改代码然后重新跑的效率要高,并且业务变动频繁的话,维护测试用例也是额外成本
话说 KnewOne 在 0 测试的情况下,也顺利从 rails 3.2 升级到 4 了,最近又升级到 4.1
DHH 的 Keynote 里提到,很多人只求测试的 coverage,ratio 和 speed,做测试驱动的“设计”。还举例了 model 中 DI 和 controller 中 command pattern 的代码。
这样的设计往往本末倒置;很多宣扬这些模式的文章确实是这么弄得,把本来很简单的逻辑搞得让人摸不着北。这样的例子很好找,twitter 搜一下 DHH 跟人打的口水架就能搜出一堆。
应该要问另一个问题,开发过程中哪些因素对质量更重要?时间有限的话,花在哪里更有效用? 领域知识、领域建模、需求调查、详细设计、框架、编程、review、交流、测试(各种测试)、文档等等
试译末段:
但首先请深呼吸。我们现在正在驱赶一批神圣的奶牛前往屠宰场。这是痛苦和血腥的。测试先行开发是如此的成功,以至于它已经交织在了很多程序员的身份之中。测试先行开发不只是关于他们做什么,而是关于他们是谁。为了从测试先行开发下面逃离出来,作为一个社区,我们有很多严肃的反编程工作要做,并且这将需要一些时间。
我们能做的最糟糕的事情莫过于简单冲进另一个“测试宗教”。我现在就可以想像出一些“我们仅要系统测试!”的金牛犊。请不要去那里。
是的,对我来说,测试先行开发是死了。但是,与其在其坟墓上舞蹈,或是进行苟延残喘的荒谬嘲弄,我宁愿向它带来的贡献致以敬意。它标志着我社区历史上的一个重要阶段,但现在是时候继续前行了。
TDD 并不是看上去的那么美 http://coolshell.cn/articles/3649.html
TDD 到底美还是不美? http://coolshell.cn/articles/3766.html
Test-Driven Development?别逗了 http://coolshell.cn/articles/5531.html
看文章之前,有多少人在坚持 TDD? 看完文章之后,是不是多了个理由不 TDD?
当 TDD 成为一种教条,也不要让 TDD is dead,成为另一种教条。
该写的时候就写。
TDD 就是土豪把玩的玩艺儿,就跟任志强说的一样,过道摆一花盆,啥用也没有,就要这劲儿
我也搞测试,一般按实际情况走,Coffeescript+QUnit,但是不搞 TDD
我写测试的根本目的是 节省时间,提高编程和维护效率。
至于是是 UT 还是 TDD/BDD,都不重要了。
但是人肉测试,偶然为之还行,总靠人肉是不可行的。
@jasl 哈我在幻腾智能也是这么做的,不过我是一边升级一边重构,目前线上同时跑着睿 3 和睿 4 两个系统,通过 NGINX 分辨路由分配给不同的部分处理,谓之阶梯式升级
@xdite 文中提到的翻译很不错: http://blog.littlelin.info/posts/2014/04/26/tdd-is-dead-long-live-testing
但其实这里很多人只看标题的话,以为 DHH 是对测试开炮。但这里 TDD 指的是测试先行,大量的 mock/stub,严格的 unit test(要求代码足够 isolated)去指导软件设计。
这个 DHH 讲的东西,我觉得对于国内的 rails 开发团队来说,应该不会有太大的反应。因为国内的团队写 test 的气氛不是很浓,甚至很多人都不会去写 test(在我待过的团队,认识的开发人员来说)。
I think that's the direction we're heading. Less emphasis on unit tests, because we're no longer doing test-first as a design practice, and more emphasis on, yes, slow, system tests.
If your TL;DR of my talk and post on TDD was "great, I don't have to write tests!", your comprehension skills are inadequate. Level up.
system test 成本高因为 slow,有了并行测试和 cloud 环境,system test 的速度可以成倍加快,功能测试的部分可以解决,但自动化 (capybara)+could 环境下并发测试 (并保存截图),还是不能对 UI 的兼容性放心,对浏览器,mobile 兼容性要求高的项目,测试的成本还是很高。
#47 楼 @lilu 我写那个是没看文章的时候回复的 首先,我在贡献代码的时候一定会写测试 但是在业务系统上测试什么、怎么测试,我个人的认识或者说功力是无法给自己满意解答的
例如,主要业务并不复杂的系统,人脑是可以穷举出各种情况并加以肉测的,何况我作为设计和实现者 此时编写测试我认为我们可以从中获益两点:1、接手系统的开发者可以通过测试了解业务 2、对模块进行改动的时候可以保证功能的正确性
但这里同时引入了一个问题,我们是不是会去追求 100% 的覆盖率?我认为不会,但如果不做到 100% 的覆盖的话,通过测试了解业务其实是个坑,因为测试不完全,为了驾驭代码最终还是要去阅读理解代码,流程其实在网站上体验一次就可以了解了,开发者不会用自己的系统本身就很失败,通过测试了解业务其实并不一定是最明智的方式,至于了解函数的作用,应该是通过编写 rdoc 这样的文档。至于第二个优点,由于测试不会覆盖完全,其实并不能通过测试说明功能的正确性的。例如之前遇到一个需求,我的方案需要重构所有页面的路由从_path 改为_url,这时候很容易出问题,测试的好处凸显,但是,我们除非为每个页面都编写测试,否则仍然可能出现问题。
而各种异常情况和边界值,我认为是很稳定的,不会因为模块变动而变动,在重构过程中只要保证接口不变还有接口的设计目标不变就可以保证最终行为的不变,所以只要保证最初版本各种情况的正确,今后升级问题不大。并且,这种巨大升级并不常见。
综上,所以我目前在业务为主、变化频率较快的系统上推崇肉测
当然,我对任何东西的看法从来都是动态的,所谓穷则思变,如果肉测解决不了问题,那么拥抱自动化测试甚至是 CI 都是自然的
#47 楼 @lilu 话说新来的实习没有任务的时候我给过他一个工作:把网站每个页面每个链接都点开一遍,构建一张网站地图,把每个业务,比如购物、发布评测的业务流程整理进去,因为了解 Rails 的 convention,再把对应 Controller 的 Action 映射到这张地图上去
这样我认为有一个好处:1.完全了解各项业务了 2.从用户的视角去体验,对于哪里好用,哪里不好用也有了感性的认识 3.知道每个业务每个步骤对应了哪块代码,如果接到有关任务,可以快速定位
这种情况下,理想情况下,扩展、变动或者新功能与已有系统交互时,应当会有牵扯到到哪些代码的认识,也就知道要注意什么、测试什么了
当然,最终会不会出问题,还是看人
#57 楼 @psvr
rake routes
就可以完成 提高效率的有效方式就是少走弯路,业务代码首先无聊其次没营养,这样学习不浪费精力,何况代码数万行后了解整个系统运作几乎不可能。这里也是 Rails 的优势,通过 Convention 降低学习成本,构建好代码地图遇到问题就能够做到快速定位问题即可。
至于#58 没有证据表明测试和减少潜在问题有正相关性,例如 Rails 的 CounterCache 的测试用例就是错误的,实现也就只能是表面上正确。所以能够降低这个观点不成立。 至于你说不会 100%,我得承认具体问题具体分析,因为我不是反对测试,而是认为很多项目因为业务和工程上的特性可以变通的方式避免编写测试并且减少重构时发生问题。如果一个项目完全可以这么做,我认为写测试的必要是 0,肉测即可
#60 楼 @simlegate 少年,脑洞不要开太大,升级之前我早在半年前就用几个项目预演过了,唯一遇到棘手问题还是 Mongoid 当时处于 alpha 版有 bug,正好赚个 PR
难度多大、花费时间多少、无不无聊 看人,你能力够强、经验够丰富 没什么做不到的 世界上毕竟还是有 Linus 这种代码一次成型的大神的
Kent Beck 对 DHH 的回应->https://www.facebook.com/notes/kent-beck/rip-tdd/750840194948847
@jasl 毕竟大牛和经验丰富的人都是少数。 听你这话就好像只要努力没有什么事儿做不成。那结果能做成事的毕竟还是少数。 要是只是升级个博客,要什么测试代码,人肉足以。 如果能把节约点时间,做其他事,难道不是一件好事?
#65 楼 @simlegate 努力没什么事儿做不成,我不赞同,更重要的是方法要找对,然后才是努力
测试为什么不能解决问题我已经叙述过了,回头看我帖子,另外别忘了,RSpec 升级之后过去的用例集也要重构的,这工程可真不比升级系统小
#65 楼 @simlegate 至于怎么找到方法,原因则很复杂,运气、个人经历、知识积累、经验等等都有可能
另外就是,人是会随项目成长的。面对问题来解决问题,然后总结,什么样的问题是常见问题,什么是跟场景有关,Rails 其实就是前者常见问题解决方案的集合。
def iframe_handler @iframe_handler ||= DashboardIFrameHandler.new(@application_interaction_timeout) end
想知道这个 ||= 是做什么用的啊?谢谢各位!
#70 楼 @diorbrand 简单的可以这么理解: a ||= b
为 a = a || b
具体请看:http://www.rubyinside.com/what-rubys-double-pipe-or-equals-really-does-5488.html
这篇,Test-induced design damage,讲得就比较具体了:"you do not let your tests drive your design, you let your design drive your tests!"
先测还是后测、system testing 还是 unit testing、重视不重视覆盖率等问题有一个非常重要的前提:你的需求来自哪里,交付给谁
DHH 的客户是自己,是在做自己的产品,所以 DHH 需要 design driven,这和 test driven 是两种思维模式。
但对于“传统”一点的软件公司或者外包团队,你需要保证你交付的功能符合一定的标准,单元测试和覆盖率可以从一定程度上提供“保证”或者“信心”。
Life is short,你要看好你在哪条路上,如果你要做 NB 的 consultant,好好钻研 TDD,给客户提供 100% 覆盖率的测试将是一面金字招牌;如果是另外一条路,那就尽量保证足够的 system testing,不要苛求 100% 的覆盖,多留精力在其他事情上。
看 3 大牛的讨论情况好象是 TDD 没挂。TDD 里的 mockist 派系容易问题;TDD 和设计不是替代关系,就好象选画笔不能替代绘画风格一样;TDD 不是 silver bullet,不同目标的代码采用 TDD 的代价不一样,会取舍才是问题关键。