在RSpec中编写请求规范的正确方法是什么?

时间:2012-01-29 17:21:28

标签: ruby-on-rails ruby ruby-on-rails-3 rspec rspec2

tl; dr:跳到最后一段

最近我一直在尝试使用RSpec的请求规范来进行更有针对性的测试。

这是我的测试主要看起来的方式:

  • 一般黄瓜功能规范,即用户发表评论,赞成评论,作者获得积分
  • 当模型实际具有某种功能时,
  • 模型规范,即User#upvote(comment)
  • 控制器规范我将大部分内容存根,并尝试确保代码按预期方式运行
  • 查看规范,了解视图中是否存在复杂内容,例如仅在用户尚未投票时呈现 upvote 链接,并且这些链接存在井

问题是当我有一些导致错误的特定场景时,一切似乎都在模型/视图层中工作,我无法重现它。

这迫使我写一个集成测试,我也可以用黄瓜做。一旦我能够实际重现它,问题就出现了,我需要弄清楚它为什么会发生。这通常意味着在测试中玩耍,改变不同的东西,看看会发生什么。

例如,创建一个由尝试upvote的用户拥有的注释,尝试使用过期的会话进行投票等。然而,这些在Cucumber中编写真的很痛苦,因为需要编写一个场景然后指定每一步。

此时,我更喜欢写一个请求规范,因为它更低级别并允许我直接做东西。问题是,我不确定如何正确编写请求规范,或者规则是什么。

这里有一个简单的例子:

visit login_path
fill_in "Username", :with => user.username
fill_in "Password", :with => user.password
click_button "Log in"

VS

post sessions_path(:username => user.username, :password => user.password)

甚至更低级别的内容,如

session[:user_id] = user.id # this actually doesn't work, but the idea is there

这两个例子都实现了同样的目的,他们会记录用户。我知道选择哪一个的答案是基于我需要测试的,但是这不能回答正确的,传统的方式这样做。

我一直试图找到有关请求规范的内容,但它们并没有真正描述过任何地方。 The RSpec book没有涵盖他们,the RSpec documentation也没有说什么。

编写请求规范的正确方法是什么?什么时候我应该使用水豚,只使用Rails的#get#post方法,而不是点击按钮和visit路径?

2 个答案:

答案 0 :(得分:3)

对于请求规范,我认为惯例是坚持测试用户行为和界面交互,这意味着加载页面,填写表单等。网站用户无法设置会话或直接与变量交互所以你也不应该请求规格。

我经常想跳过页面加载并通过在请求规范中发布或设置变量来形成交互(为了速度,特别是重ajax规范),但它确实打破了请求规范的目的。

如上所述,您应该测试其他规范类型中的特定控制器/视图行为。

答案 1 :(得分:0)

首先讲道......

我认为测试作者的自然进展如下:

  1. 控制器
  2. 型号
  3. 请求
  4. 请求,控制器和型号规格的混合。
  5. 我知道我开始先看控制器,因为它更容易掌握。

    然后你进入模型规范,对于非快乐的路径事物......

    然后你意识到rspec实际上并没有呈现视图,所以你开始在Airbrake中看到愚蠢的错误,所以你说,拍摄......我需要测试视图和工作流程。因此请求规格。

    最后,你变老并意识到,所有3个都很重要,应该谨慎使用,但也要相应地使用。我现在正处于第4步......太多的要求规格,你在整个套件中使用中型应用程序需要5分钟。吸。

    回答你的问题:

    我测试工作流程和视图我需要在请求规范中使用capybara“看到”(使用page.should或任何棘手的JS(例如jquery ui选择器)。

    如果我只是需要确保控制器变量被实例化或者为了一个非快乐的路径快速做一些事情,那么在工作流程之外......我使用控制器。例如,在PayPal中向IPN控制器发帖...

    你会惊讶于这涵盖了多少。这使您可以测试模型,以获得所有边缘情况所需的所有打包的东西。

    老实说,我会说使用Fixtures和Test Unit进行集成测试......仍然喜欢它们更好,更快......更强......等等。