tutorial - driving view behaviour with 'spec/rails'
November 6th, 2006
[Updated for 0.9 on 2007/04/12]
rspec-0.9’s ‘spec/rails’ (RSpec on Rails) plugin lets you spec your views in complete isolation of any controllers. This means that you can spec your views even before there are any models or controllers! Once models and controllers do exist, changes to them will not cause your view specs to fail.
Here’s a brief tutorial to get you started.
Create a new rails app.
rails oldnews
Now install rspec and rspec_on_rails plugins.
cd oldnews
ruby script/plugin install svn://rubyforge.org/var/svn/rspec/tags/REL_0_9_0_BETA_2/rspec
ruby script/plugin install svn://rubyforge.org/var/svn/rspec/tags/REL_0_9_0_BETA_2/rspec_on_rails
ruby script/generate rspec
Next, using the rspec controller generator, create a controller for articles:
$ script/generate rspec_controller articles list show
exists app/controllers/
exists app/helpers/
create app/views/articles
create spec/controllers/
create spec/helpers/
create spec/views/articles
create spec/controllers/articles_controller_spec.rb
create spec/helpers/articles_helper_spec.rb
create app/controllers/articles_controller.rb
create app/helpers/articles_helper.rb
create spec/views/articles/list_view_spec.rb
create app/views/articles/list.rhtml
create spec/views/articles/show_view_spec.rb
create app/views/articles/show.rhtml
Open up spec/views/articles/list_view_spec.rb and update it as follows:
require File.dirname(__FILE__) + '/../../spec_helper'
describe "articles/list with just one article" do
it "should display the title" do
render 'articles/list'
response.should have_tag('div', "example title")
end
end
Now run the specs – stand in the project root and …
ruby spec/views/articles/list_view_spec.rb -fs
... and you should get output like this (plus some backtrace info) ...
articles/list with just one article
- should display the title (FAILED - 1)
1)
'articles/list with just one article should display the title' FAILED
Expected at least 1 elements, found 0.
<false> is not true.
Open up app/views/articles/list.rhtml and edit as follows…
<div>example title</div>
Run the spec again and you’ll see that it passes. We have duplication between the spec and the subject code. To get rid of it, we’ll have to feed the view some data that it can display. Add a setup to the spec:
require File.dirname(__FILE__) + '/../../spec_helper'
describe "articles/list with just one article" do
before do
@article = mock("article")
@article.should_receive(:title).and_return("example title")
assigns[:articles] = [@article]
end
it "should display the title" do
render 'articles/list'
response.should have_tag('div', "example title")
end
end
... and run the specs …
articles/list with just one article
- should display the title (ERROR - 1)
1)
Spec::Mocks::MockExpectationError in 'articles/list with just one article should display the title'
Mock 'article' expected :title with (any args) once, but received it 0 times
This fails because the mock article never receives the :title message. You can get this to pass like so …
# in app/views/articles/list.rhtml
<div><%= @articles[0].title %></div>
So we’re part of the way there, but what we want is for the view to iterate through the list. So add another spec …
describe "articles/list with three articles" do
before do
articles = (1..3).inject([]) do |list, index|
article = mock("article #{index}")
article.should_receive(:title).and_return("example title #{index}")
list << article
end
assigns[:articles] = articles
end
it "should display the title" do
render 'articles/list'
response.should have_tag("div", "example title 1")
response.should have_tag("div", "example title 2")
response.should have_tag("div", "example title 3")
end
end
... which produces …
$ ruby spec/views/articles/list_view_spec.rb -fs
articles/list with just one article
- should display the title
articles/list with three articles
- should display the title (FAILED - 1)
1)
'articles/list with three articles should display the title' FAILED
<"example title 2"> expected but was
<"example title 1">.
It is failing on the second title because we’re not yet iterating through the articles. So…
<% for article in @articles %>
<div><%= article.title %></div>
<% end %>
... and viola!
$ ruby spec/views/articles/list_view_spec.rb -fs
articles/list with just one article
- should display the title
articles/list with three articles
- should display the title
As you can see, we are able to do this without any models or actions yet developed. As those get added, this spec will continue to pass because there is no dependency between it and the real models and controllers.
Now the risk here is that you could build a model that doesn’t have a title field in it and your app will blow up! Admittedly, if you only write isolated, granular specs like this that risk is real. So you should be doing this in conjunction with integration testing. Unfortunately, RSpec 0.9 does not yet support any integration testing directly, but there are plenty of great tools that will handle that for you. If you want to keep it on the command line, use something like rails integration testing. If you like in-browser testing you can use watir or selenium.

July 13th, 2008 at 06:06 AM
Hey,
I really enjoy your blog. I’m trying to do this who RSpec thing, but I’m running into issues, and you’re the only one who seems to be running 0.7.5. RSpec installs fine, but then when I try it install the rails plugin, weird stuff happens. Any ideas?
July 13th, 2008 at 06:06 AM
Heh, I’m sorry. I figured out my problem. My apparent dyslexia got me, and i completely messed up the subversion path. Thanks again.
July 13th, 2008 at 06:06 AM
hmz I am getting the same problem as Jordan, except I’ve checked and doubble checked the svn path and it seems I am doing everything alright.
RSPEC_0_7_5 on rails 1.1.6
any thoughts?
July 13th, 2008 at 06:06 AM
Danny – the path should be this:
svn://rubyforge.org/var/svn/rspec/tags/REL_0_7_5/rspec_on_rails/vendor/plugins/rspec_on_rails
Is that what you’re using?
July 13th, 2008 at 06:06 AM
Yes that is what I’m using, I checked… very strange, I’m trying to find on the net what I am doing wrong…
July 13th, 2008 at 06:06 AM
apparently I’m suffering from dyslexia too? it works now I’ve copy paste your svn path
svn://rubyforge.org/var/svn/rspec/tags/REL_0_7_5/vendor /rspec_on_rails/vendor/plugins/rspec_on_rails
svn://rubyforge.org/var/svn/rspec/tags/REL_0_7_5 /rspec_on_rails/vendor/plugins/rspec_on_rails
the top one is the one from the tutorials on the net (i copy paste it just now from up at this page) The lower one is the one you just gave me, maybe update? :p
thanks a lot though!!
July 13th, 2008 at 06:06 AM
Yeah, they’ve definitely got the wrong svn repo on the rspec site… or at least they changed the location.. welcome to rails
July 13th, 2008 at 06:06 AM
Yeah, they’ve definitely got the wrong svn repo on the rspec site… or at least they changed the location.. welcome to rails
July 13th, 2008 at 06:06 AM
I am trying to learn rails.
I’ve installed rspec fine (rspec 0.7.5.1). I’ve then insalled the rspec plugin. But, when I run “ruby script/generate rspec, I get the “Couldn’t find ‘rspec’ generator” message. I have rails 1.2.1 installed.
Is rspec 0.7.5.1 compatible with rails 1.2.1?
Thanks.
July 13th, 2008 at 06:06 AM
It is and I’ve not heard that problem reported yet. If it persists, please report a bug to the tracker:
http://rubyforge.org/tracker/?group_id=797
Thanks for checking out rspec!
July 13th, 2008 at 06:06 AM
for rspec 0.7.5.1 used: svn://rubyforge.org/var/svn/rspec/tags/REL_0_7_5_1/rspec_on_rails/vendor/plugins/rspec_on_rails on edge rails and Rails 1.1.6 installed as gem
July 13th, 2008 at 06:06 AM
i have installed gem for rspec. but when i go for installing rspec plugin then its not found and name occur. and after that if i try ruby script/generate rspec then i says that it couldn’t find rspec generator.
i am using ruby185-22_rc2.exe and rails gem 0.7.5.1. so reply me if anyone know solution for this.