Rails 3 + Rspec 2:测试content_for

时间:2011-11-04 18:24:02

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

我正在运行Rails 3.1.1,RSpec 2.7.0和HAML 3.1.3。

说我有以下视图文件:

应用程序/视图/布局/ application.html.haml
!!!
%html
  %head
    %title Test
    = stylesheet_link_tag "application"
    = javascript_include_tag "application"
    = csrf_meta_tags

  %body
    = content_for?(:content) ? yield(:content) : yield
应用程序/视图/布局/ companies.html.haml
- content_for :content do
  #main
    = yield :main
  #sidebar
    = yield :sidebar

= render :template => 'layouts/application'
应用程序/视图/公司/ index.html.haml
- content_for :main do
  %h1 MainHeader
- content_for :sidebar do
  %h1 SidebarHeader

以下规范文件:

规格/视图/公司/ index_spec.rb
require 'spec_helper'

describe 'companies/index.html.haml' do

  it 'should show the headers' do
    render
    rendered.should contain('MainHeader')
    rendered.should contain('SidebarHeader')
  end

end

当我运行RSpec时,出现以下错误:

1) companies/index.html.haml should show the headers
   Failure/Error: rendered.should contain('MainHeader')
     expected the following element's content to include "MainHeader":
   # ./spec/views/companies/index_spec.rb:7:in `block (2 levels) in <top (required)>'

起初,我认为RSpec在渲染视图文件时会以某种方式遗漏content_for块。但是,我无法在RSpec的github存储库中找到任何与之相关的问题,所以我不确定在这里应该责怪谁。

我找到的一个(最近)解决方案是http://www.dixis.com/?p=571。但是,当我尝试建议的代码时

view.instance_variable_get(:@_content_for)

它返回nil。

  • 有没有办法在视图规范中测试content_for?
  • 有没有更好的方法来构建我的布局文件,这样我实际上能够测试它们并仍能达到相同的最终结果?

3 个答案:

答案 0 :(得分:27)

将Rspec 2与Rails 3一起使用,为了编写使用content_for的视图规范,请执行以下操作:

view.content_for(:main).should contain('MainHeader')
# instead of contain() I'd recommend using have_tag (webrat)
# or have_selector (capybara)

P.S。默认情况下,content_for(...)块的值为空字符串,因此如果您愿意 编写规范,显示没有调用content_for(:main)的情况,使用:

view.content_for(:main).should be_blank

您的规范可以写成:

it "should show the headers" do
  render
  view.content_for(:main).should contain('MainHeader')
  view.content_for(:side_header).should contain('SidebarHeader')
end

通过这种方式,您的规范可以准确显示视图的功能,而不受任何布局的影响。对于视图规范,我认为单独测试它是合适的。编写视图规范总是有用的吗?这是一个悬而未决的问题。

相反,如果您想编写显示标记为用户提供的内容的规格,那么您将需要请求规范或黄瓜功能。第三种选择是包含视图的控​​制器规范。

P.S。如果你需要指定一个直接输出一些标记并将其他标记委托给content_for()的视图,你可以这样做:

it "should output 'foo' directly, not as a content_for(:other) block" do
   render
   rendered.should contain('foo')
   view.content_for(:other).should_not contain('foo')
end
it "should pass 'bar' to content_for(:other), and not output 'bar' directly" do
   render
   rendered.should_not contain('bar')
   view.content_for(:other).should contain('bar')
end

这可能是多余的,但我只想展示render()如何填充渲染和view.content_for。 “rendered”包含视图直接生成的任何输出。 “view.content_for()”通过content_for()查找视图委托的任何内容。

答案 1 :(得分:1)

来自RSpec docs

  

要为渲染提供布局,您需要明确指定模板和布局。

我更新了规范并通过了:

require 'spec_helper'

describe 'companies/index.html.haml' do

  it 'should show the headers' do
    render :template => 'companies/index', :layout => 'layouts/companies'
    rendered.should contain('MainHeader')
    rendered.should contain('SidebarHeader')
  end

end

答案 2 :(得分:-7)

不要打扰视图规格。它们很难写得很好,而且它们没有足够的堆栈测试值得使用(特别是考虑到编写难度)。相反,使用Cucumber,并在此过程中测试您的观点。

您通常不希望特别测试content_for:那是实现,而您应该测试行为。所以,只需写下你的黄瓜故事,就可以测试所需的内容。

如果由于某些奇怪的原因你需要测试content_for,RSpec的语法类似于body[:content_name]body.capture :content_name,具体取决于版本(或类似的东西;暂时没有用过它。但要仔细考虑是否有更好的方法来测试你真正想要测试的内容。