This article will get you setup with the bare-minimum environment to run Selenium tests with RSpec, for automated, full-stack testing of Rails apps. Once that’s done, we’ll work on polishing it for a nicer experience. In this post you find amalgamations of mostly outdated articles from around the internet updated to work with a modern rails system.
It’s written on a clean environment courtesy of rvm, so you may have some of the gems already setup.
A new Rails app, RSpec, and rspec-rails
First off, we’ll start with a new rails project:
gem install rails --no-ri --no-rdoc rails rspec_saucerc gem install rspec gem install rspec-rails
Edit config/environment.rb and add:
config.gem "rspec", :lib => false, :version => ">= 1.2.9" config.gem "rspec-rails", :lib => false, :version => ">= 1.2.9"
This sets up all the required files for RSpec to get off the ground, but we need to integrate it into Rails:
script/generate rspec
That will add the rake tasks, create the appropriate directories, and basic files. Now let’s get Selenium up and running!
Selenium
We’ll need to create a separate selenium database. in config/database.yml, let’s add:
selenium: adapter: sqlite3 database: db/selenium.sqlite3 encoding: utf8 timeout: 5000
To get Selenium running under our RSpec stories, we’ll need the Selenium gem (note the capital “S” — it’s case-sensitive). Let’s also make sure we have the sqlite3 gem installed, and then prepare an appropriate environment for our selenium tests:
gem install Selenium gem install sqlite3-ruby cp config/environments/test.rb config/environments/selenium.rb
Open config/environments/selenium.rb and remove the last line that reads:
config.gem 'rspec-rails', :version => '>= 1.3.2', :lib => false unless File.directory?(File.join(Rails.root, 'vendor/plugins/rspec-rails'))
Sauce RC and Selenium RC
Sauce RC will broker all communication between rails and any browsers you might be driving. Get it from our downloads page for Windows or Mac, or use Selenium RC for Linux, and start it up so we can run our tests.
Testables
We’ll need some fodder to test. Use the RSpec generator, then create and migrate the database:
script/generate rspec_scaffold person name:string age:string language:string rake RAILS_ENV=selenium db:create rake RAILS_ENV=selenium db:migrate
Startup our test server
Rails tests do not normally bind to a webserver, so there is no way for Selenium to access the frontend. As a temporary workaround, we’ll manually invoke a Rails server using the selenium environment:
script/server -e selenium
Our spec helper
We will be using the Selenium gem, so let’s add it to the spec helper:
gem "selenium-client" require "selenium/client" require "selenium/rspec/spec_helper"
Example story
We’ll gloss over which types of tests should include selenium front-end testing for now, and just say it belongs in integration tests. Let’s run an example story that will fail the first time through, and we’ll then fix it.
Put the following in spec/integration/people_spec.rb:
require 'spec_helper'
describe "People" do
before(:all) do
@verification_errors = []
@browser = Selenium::Client::Driver.new(
:host => "localhost",
:port => 4444,
:browser => "*firefox"
:url => "http://localhost:3000",
:timeout_in_second => 90)
@browser.start
end
before(:each) do
@browser.start_new_browser_session
end
append_after(:each) do
@browser.close_current_browser_session
@verification_errors.should == []
end
it "should create a new Person with valid input" do
@browser.open "/people"
@browser.click "link=New person"
@browser.wait_for_page_to_load "2000"
@browser.type "person_name", "Jason Huggins"
@browser.type "person_age", "26"
@browser.type "person_language", "Albanian"
@browser.click "person_submit"
@browser.wait_for_page_to_load "30000"
@browser.is_alert_present.should be_true
end
end
Let’s try it out:
rake spec:integration F 1) 'People should create a new Person with valid input' FAILED expected false to be true ./spec/integration/people_spec.rb:22: Finished in 7.443904 seconds 1 example, 1 failure
It’s failing as we expected it to (there shouldn’t be a javascript alert on submit). Let’s change the last line:
@browser.is_alert_present.should be_false
… and try our test again:
rake spec:integration . Finished in 7.079062 seconds 1 example, 0 failures
Looks good! We finally have a working rails project with rspec runners and Selenium.
Weaknesses
Although we’ve got Rails, RSpec, and Selenium all working together, the relationship is not harmonious.
Automated tests in rails are not meant to serve the outside world, and as such they don’t bind to a webserver/port. Tests are run within the same process, which makes them quite fast, but prevents us from using browser-based frontend tools such as Selenium. To get around that, we manually fired up a rails server instance with the selenium environment, but this is messy for a number of reasons:
- We have to manually start/stop the test server that selenium wants to access
- We have to manually create the selenium environment’s database
- We have to manually migrate the selenium environment each time there’s a schema change
- Worse, we have to manually reset the database after each run
- Running Selenium tests in serial is slow
We‘ve developed a plugin to automate some of these issues, called SpecStorm. We’ll go over installing it to get the most out of your tests (including running them in parallel) in the next post.
Notes:
Selenium matchers are case-sensitive: @browser.click “link=New Person” won’t match a link with “New person”

Hi,
Thanks for this tutorial. I’m almost there, but I’m getting this error when I try to run ‘rake spec:integration’
1)
NoMethodError in ‘People before(:all)’
undefined method `start’ for nil:NilClass
/home/matt/Projects/rspec_saucerc/spec/integration/people_spec.rb:13:in `block (2 levels) in ‘
Finished in 0.005840741 seconds
0 examples, 1 failure
I didn’t do the generate/plugin step. Instead I just did ‘gem install selenium-rails’. Here is my list of installed gems:
actionmailer (2.3.5)
actionpack (2.3.5)
activerecord (2.3.5)
activeresource (2.3.5)
activesupport (2.3.5)
gemcutter (0.5.0)
hoe (2.5.0)
json_pure (1.2.2)
mocha (0.9.8)
mysql (2.8.1)
rack (1.1.0, 1.0.1)
rails (2.3.5)
rake (0.8.7)
RedCloth (4.2.3)
rspec (1.3.0)
rspec-rails (1.3.2)
rubyforge (2.0.4)
rubygems-update (1.3.6)
Selenium (1.1.14)
selenium-client (1.2.18)
selenium-rails (0.0.3)
sqlite3-ruby (1.2.5)
test-unit (1.2.3)
Sorry if I’m missing something obvious. I’m still getting started with all this. Also, if I already have several models, controllers, views, etc. created using the normal rails scaffold, what is the best approach to go back and add rspec tests?
Hello Matt – there was an error on line 06 of of people_spec.rb. Check the updated source above. Instead of @selenium_driver, it should be @browser.
Thanks for catching that! Please let me know if that works for you, and if there’s any other issue that comes up.
And good question about grafting tests onto pre-existing rails models. For RSpec unit tests where you’re familiar with the inner-workings of the code, you’ll want to add in tests for each of the methods of your models, and then move onto functional/integration tests. If you’re new to the code, it often works better the other way around. Get a bird’s-eye view of the code by looking at its function and verifying the application as a whole, and work your way into the nitty-gritty with unit tests.
It’s an interesting question, I think I’ll have to follow up with a few posts on that.
Very nice Tutorial.
Its working fine. Now i gonna try specstorm.
Regards
Alok S
Consultant, Spritle Software.
I’m glad you like it Alok! If you have any questions on running SpecStorm, please feel free to post them on our forums at http://www.saucelabs.com/forums. I’m more than happy to help others using it!