咨询下行情, 由于公司系统基本不写测试(原因:一个人写/维护,小项目基本无须长期维护)
只有给自己写一些东西的时候先上测试代码,不过一直用自带的 test/unit 或者 minitest 就好了,一则比较简洁,二则语法比较对口味,三则基本需求也都能满足,四则学习成本比较低
但是主流好像都在用 rspec,大家都用这个?有坚持用 minitest 的么?介绍个理由?(没时间自己写了去体会,所以偷懒先问下)
#3 楼 @as181920 场景实际上处处都在,BDD 和 TDD 的差别关键不在于方法(很多方法都是共通的),而是在于理念,或者更通俗的说是“视角”,也就是你如何看待被测试的项目的。
我个人的观点是 BDD 是从 TDD 延伸出来的更具针对性的、特化的测试理念,所以 BDD 本身也可以完成传统的 TDD 的功能(RSpec 写 TDD 没什么问题啊)。这种理念的特征就是它更加关注代码的“行为”胜于关注代码的“内部逻辑”。
我们用 TDD 测试类和方法的时候,往往不太关心方法与方法之间或类与类(模块与模块)之间的交互(这是一种行为,它比方法的内部实现关注的层面略高一些),只需要保证内部返回结果符合预期就可以了,传统的 TDD 倾向于分离,避免耦合带来的复杂性和干扰。
但是 BDD 则更关注于系统内部模块之间(甚至是和外部接口之间)的交互过程,以 RSpec + Capybara 为代表的 DSL 的应用更有助于开发者描述这些行为,而且是从“应用”的角度而不是“内部实现”的角度。这一点和项目的规模并没有直接的关系,小项目往往也会有比较复杂的交互行为和业务逻辑。
当然了,RSpec 本身也可以覆盖系统由外向内的各种层级,但测试目标的粒度逐渐缩小的时候,它的使用方法也越来越接近传统的 TDD,所以用 RSpec 配合 MiniTest 也是一种选择(如果你更喜欢 MiniTest 简洁的风格)。
我的水平有限,也不知道讲清楚这个意思了没……总之,我的感受是,当我使用 MiniTest 这类测试框架的时候,我更偏向于程序员的角色;而使用 RSpec 的时候,则偏向于应用的设计者或是使用者,而 RSpec 在“由外向内”层层深入的时候,我的角色也逐渐从“设计/使用者”向“代码编写者”过渡,这种感觉非常自然舒服。
RSpec 为什么会很受欢迎,我想这是因为在国外,Developer 和 Programmer 是两种不同的概念,尽管他们做的事情有很大部分的重合之处,而 RSpec 很好地满足了 Developer 的进阶需求,是的他们能够从“产品”,而不仅仅是“代码”的角度来描述、设计、实现目标应用。
允许牛角尖的话,如果进一步问, 1,BDD 是更关注于系统内部模块之间的交互过程,如果用 minitest 的代码去写会有什么问题? 2,RSpec + Capybara 为代表的 DSL 的应用更有助于开发者描述这些行为,主要体现在哪些方面
瞎猜: 1,rspec 用的关键词是否更贴合人描述行为的用语?如果用纯程序人员抽象的角度使用这些关键词,是否两个框架的差异就没有多少?
不准确的经验: 1,如果涉及到页面行为的测试,Capybara 是带来很多方便的功能
#8 楼 @as181920 这些问题若是扯起来就长篇大论去了,我建议三件事情吧:
第一、读一读 The RSpec Book 的书,里面有一部分对于测试驱动开发理念的讲述,特别是 BDD 特点讲述挺好的,比我说的专业;
第二、推荐你看看 Gary Bernhardt 的 DAS 系列视频:https://www.destroyallsoftware.com/screencasts,此人使用 RSpec 作为日常使用的测试框架,但是他很少讲 BDD(不是不讲这个理念,而是不怎么讲这个词),因为在他看来,无论是 BDD 还是传统的 TDD,事实上都应该是 TDD——测试 驱动 开发,重要的不是“测试方法论”而是“驱动”,BDD 只是一种驱动方式,它的“视角”和传统的 TDD 有区别。
第三、找两个规模差不多,质量都比较好的项目,一个用 MiniTest,一个用 RSpec,你亲自去比较一下,体会一下作者在写测试的时候大概是一种什么思路,是什么“视角”。
对于你的瞎猜,我是比较同意的,如果你让别人来看你写的测试,RSpec 会比 MiniTest 更易读和更易理解(前提是看的人对两种框架都不了解,或者了解的程度差不多)
最后,Capybara 是很好的,然而以前在 RSpec 里的用法并不够 BDD,比如说以前 Capybara 可以用在 Integration Test 里,但这个并不太贴 BDD 的理念。所以后来 RSpec 和 Capybara 联手做了 Feature Spec,这个东西就是一个 Cucumber 的简洁的替代品,也是从这个时候开始 RSpec 才真正的践行了 BDD 的精髓,即 outside-in。在以前,outside-in 的最外层只有 Cucumber 实现的比较好,RSpec 的 request spec 则是用“程序员”的语法来描述“用户”的行为。当然,这一点在今天得到了比较好的处理,喜欢 RSpec 的人终于可以不依赖 Cucumber 了(当然一起用也可以)
纠正一句话,不是“涉及页面行为的测试”,而是“涉及应用行为的测试”,因为用户使用你的应用也不一定所有的交互都是在页面上完成的。
举个例子:
我们在 request spec 的时代,这样写请求:
get root_path
现在在 feature spec 里,配合 capybara 这样写:
visit "/"
实际上二者是等价的,你看 Capybara 的 API 里有讲到这一点。但这并不仅仅是写法上的区别,也不单纯是为了用 DSL 套上一层壳,更重要的是,当你写 feature spec 的时候,visit "/"
这样的 API 将驱动你以用户的角度来观察你的应用行为,你脑子里的描述是:
当用户在浏览器里访问我应用的顶层 URL 的时候
而不是:
当浏览器向
root_path
发出GET
请求的时候
这种理念上的切换会更有助于设身处地的为用户着想,为应用的“行为”而不是“内部实现”着想,这是非常“讨好”开发者的一种举措。
再者,同样的这个例子,你让一个外人(比如项目的客户或直接用户)来看,哪一个他更容易看懂和理解?这是显而易见的。
或许有些程序员会对这一点貌似“换汤不换药”的差别嗤之以鼻,但这就是我说的 Developer 和 Programmer 的区别。RSpec 并不是要阻止你去写程序化的测试代码,它是一种完善,它提供另一种途径,仅此而已。
rspec 还是有点好处的
it "..."
测试的描述可以更清楚,而且不会因为意外方法重名而把前面的测试丢了
before :each
和 before :all
容易记住
可以选择 彩色输出 (-c), 文档输出 (-f d), 编辑器专用输出 (-f textmate), 还有 nyancat formatter...
should ==
把哪个是 expect, 哪个是 actual 分得很清楚,还可以少写一些括号 (assert_equal({}, output)
就不能省括号)
==
是最自然不会写错的,如果一段时间没写代码,就会忘记是该写 assert_equal
还是 assert_equals
了...