If you are using RSpec and RSpec Rails to test your Rails application, I strongly encourage you to keep reading this post because there’s a gotcha in the default configuration you might not expect, especially if you ever used the default Rails test framework before.
A couple of days ago I was notified about a but in a Rails application. The application crashed when trying to create a new record.
I changed the
new action the day before, but I was sure all the tests passed and the action was covered with a pretty reasonable RSpec test suite. Moreover, the action method was one of the most simplest methods I have ever written.
def new @record = Model.new end
I run the test suite, all green. I executed the page in the browser, it crashed.
After several minutes of debugging I discovered the culprit: RSpec (actually the RSpec Rails gem) doesn’t render the content of the action by default, like the common Rails functional tests do. In fact,
@response.body always resulted in an empty string.
The view contained a statement like the following
<%= f.collection_select Model.all, :id, :name %>
that was misspelled and crashed when the template was rendered. But because RSpec doesn’t render the Rails views, the view was not covered by the tests at all.
The solution is simple and is called render_views.
To tell a controller to render the content of the view, simply call
require "spec_helper" describe RecordsController do render_views describe "GET index" do # ... end end
You can also enable
render_views globally, in your
RSpec.configure do |config| config.render_views end
The reason behind this choice is because RSpec Rails actually provides a special RSpec group called “view specs”.
describe "events/index.html.erb" do it "renders _event partial for each event" do assign(:events, [stub_model(Event), stub_model(Event)]) render view.should render_template(:partial => "_event", :count => 2) end end
According to the documentation, this is the right way to test Rails templates in RSpec. Honestly, I never really liked this feature and I tend to keep using controller specs — the RSpec equivalent of functional tests — (or alternative test tools) to test the views.