【问题标题】:What's a proper way of writing request specs in RSpec?在 RSpec 中编写请求规范的正确方法是什么?
【发布时间】:2012-02-21 17:29:42
【问题描述】:

tl;dr:跳到最后一段

最近我一直在尝试使用 RSpec 的 request specs 来做一些更有针对性的测试。

这是我的测试的主要外观:

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

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

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

例如创建一个评论,该评论归试图投票的用户所有,尝试用过期的会话进行投票等。然而,用 Cucumber 编写这些真的很痛苦,因为需要编写一个场景,然后指定每个步骤。

在这一点上,我更喜欢写一个请求规范,因为它更底层并且允许我直接做一些事情。问题是,我不确定如何正确编写请求规范,或者规则是什么。

这里有一个简单的例子:

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

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 也没有说什么。

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

【问题讨论】:

  • 集成(又名请求)规范应该模仿用户的行为,所以我通常坚持使用 Capybara 的助手(访问/填充,点击等...)。但是,这并不是冻结和规则被打破(故意)。见relishapp.com/rspec/rspec-rails/docs/request-specs/request-spec。请注意,我不使用 Cucumber。
  • 我在测试控制器的行为时使用标准的 get/post 请求测试。例如,当我说某些内容应该只显示给管理员时。在我的规范中,我对管理员进行身份验证并验证该选项是否在正文中。我不点击/访问。我唯一一次使用点击和访问的东西是当视图中有一些逻辑时,比如 jquery。否则,视图代码应该是微不足道的。因此,在您支持自己的评论示例中,我将使用帮助程序构建用户,为该用户构建评论,然后发布请求说 /upvote 并说“它应该返回 403”
  • 我使用模型/视图/控制器测试来测试代码,水豚(或黄瓜和..)来测试用户交互(或所有组件的集成)。我可以使用请求规范来测试路由/控制器集成),我认为这就是它的目的,但在我看来它不是必需的。如果您没有集成测试,您需要的请求测试。例如,如果你只写一个只有机器交互的 api,那么你可以使用解决方案 II,否则我会使用解决方案 capybara。

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


【解决方案1】:

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

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

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

【讨论】:

  • 我个人认为在身份验证测试的上下文之外直接设置用户记录没有问题。如果您有身份验证,您可能必须登录才能执行几乎所有操作,而且虽然很小,但渲染登录表单和提交它的开销会随着时间的推移在您的其他测试中增加。
【解决方案2】:

先讲道....

我认为你是测试作者的自然发展:

  1. 控制器
  2. 型号
  3. 请求
  4. 请求、控制器和模型规范的混合。

我知道我首先开始查看控制器,因为它更容易掌握。

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

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

最后,随着年龄的增长,你会意识到,这三个都很重要,应该谨慎使用,但要相应地使用。我现在正处于第 4 步……请求规范太多,而您正在为一个中型应用程序上的整个套件花费 5 分钟。糟透了。

回答您的问题:

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

如果我只需要确保控制器变量已实例化或通过帖子快速执行不愉快的路径,工作流程之外的事情......我使用控制器。例如,POST 到 paypal 中的 IPN 控制器...

您会惊讶于这涵盖了多少。这样一来,您就可以对模型进行测试,以获得所有边缘情况所需的全部内容。

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

【讨论】:

    猜你喜欢
    • 2017-03-26
    • 1970-01-01
    • 2011-03-29
    • 1970-01-01
    • 1970-01-01
    • 2016-10-06
    • 1970-01-01
    • 2011-10-27
    • 2014-05-31
    相关资源
    最近更新 更多