This is a guest blog post by Chris Johnson, a web developer, author and technology consultant. Cucumber and Selenium are a great way to bring browser testing to your Rails application. Selenium gives you the ability to automate tests that actually use the browser the way a human user might, giving you confidence that your application actually works. But one problem you may run in to is testing multiple browsers. Sauce Labs comes to the rescue with the ability to let you easily run your tests in the cloud on multiple browsers.
Let's hook up our rails application, Twitflickup, to work with Sauce Labs. To start, we'll grab the application's source code from github.
$ git clone git://github.com/johnsonch/twitflickup.git
With the repository cloned, we'll want to run $ bundle install to get our basic dependencies installed. This application requires a Flickr API key, which can be obtained from http://www.flickr.com/services/apps/create/. After getting an API key, we'll want to copy env.yml.example and rename it env.yml, then replace the API key and secret from Flickr in this file.
Writing a Cucumber Test
Let's start by adding a Cucumber test around the homepage of Twitflickup by creating the homepage.feature file inside of the features directory. By opening up the app/models/mashup.rb file, we see that when a new mashup is created, the application searches Twitter for the word "fish," then searches Flickr for the third word of the tweet. For our homepage to look correct, we'll want to make sure there is an image on it and a tweet with the word "fish" in it.
@selenium Feature: Twitflickup searches twitter and flicker Scenario: Search twitter for fish and display tweet Given I am on the twitflickup homepage Then I should see a tweet with the word "fish" in it Scenario: Search flickr for an image Given I am on the twitflickup homepage Then I should seen an image from Flickr
With our feature file in place, let's build out the step definition in features/step_definitions/homepage_steps.rb
Given /^I am on the twitflickup homepage$/ do page.visit("/") end Then /^I should see a tweet with the word "([^"]*)" in it$/ do |search| page.should have_content(search) end Then /^I should seen an image from Flickr$/ do page.has_selector?('#flickr-image img') end
We now have our tests in place and can run them with the following command.
After running the feature, we'll get an output like the following:
Feature: Twitflickup searches twitter and flicker Scenario: Search twitter for fish and display tweet # features/homepage.feature:3 Given I am on the twitflickup homepage # features/step_definitions/homepage_steps.rb:1 Then I should see a tweet with the word "fish" in it # features/step_definitions/homepage_steps.rb:5 expected there to be content "fish" in "Twitflickup\n\nTwitflickup\n\n\n\n\nwho told you to come outside smelling like FISH and eggs ?\n\n@\nbaby_itsREALxX\n\n\n\n\n" (RSpec::Expectations::ExpectationNotMetError) ./features/step_definitions/homepage_steps.rb:6:in `/^I should see a tweet with the word "([^"]*)" in it$/' features/homepage.feature:5:in `Then I should see a tweet with the word "fish" in it' Scenario: Search flickr for an image # features/homepage.feature:7 Given I am on the twitflickup homepage # features/step_definitions/homepage_steps.rb:1 Then I should seen an image from Flickr # features/step_definitions/homepage_steps.rb:9 Failing Scenarios: cucumber features/homepage.feature:3 # Scenario: Search twitter for fish and display tweet 2 scenarios (1 failed, 1 passed) 4 steps (1 failed, 3 passed) 0m10.009s
We are left with a failing test, but there is no way to see what's going on. Sure, in this case, we can determine relatively easily that the failure is caused by us looking for the word "fish" and the tweet returning "FISH." But wouldn't it be nice to see a screen shot of what's going on too? Luckily for us, we can easily set up our application to use Sauce Labs and take advantage of the ability to playback a test that's been recorded to visually pinpoint what went wrong. To run our Cucumber tests with Sauce Labs, we'll need a Sauce Labs account and Sauce Labs API key. To get an account, sign up at https://saucelabs.com/signup and then grab the API key from the "My Account" page. For the purpose of this project, let's copy the ondemand.yml.example file, rename it to ondemand.yml, and then replace the API and Username values with those we got from our own account. The ondemand.yml file will let Sauce Labs know who we are, which let's us view our test runs from their web interface. With our ondemand.yml file set up, we'll need to include the Sauce gem in our gemfile. Inside of Gemfile, let's add the following to the test group:
The Sauce gem is the Ruby client adapter that allows users to make Selenium tests run in Sauce OnDemand without any test changes. This gem can also be used with RSpec and Test::Unit, but here we'll stick with Cucumber. The source for the Sauce gem is available at https://github.com/saucelabs/sauce_ruby. Next we need to tell Cucumber about Sauce Labs, which will be set up in features/support/env.rb. We'll need to require sauce, sauce/capybara, set up Sauce.config and change Capybara's default driver to be sauce.
require 'sauce' require 'sauce/capybara' Sauce.config do |config| config.browser = "iexplore"
config.os = "Windows 2008"
config.browser_version = "9" end Capybara.default_driver = :sauce
The Sauce.config section is where we can change what browser we want to test against. In this example, let's stick with Internet Explorer on Windows 2008. Now that we have everything in place, we can run our Cucumber tests again. This time we'll see our output letting us know we are connecting to Sauce OnDemand. By logging into Sauce Labs, we can see the job is executing and we can even click on the job name and watch the test execute in realtime.
Now that we have our tests executing on Sauce Labs, we can login to our account, see our test runs, and take advantage of Sauce's great playback and screen shot features. To find out more about using Cucumber and Selenium to test any website along with many other great web development tips, tricks and techniques, be sure to checkout Web Development Recipes from the Pragmatic Programmers.
Chris Johnson is a web developer, author and technology consultant living outside of Madison, Wisconsin. He has been developing websites professionally since 2003 when he got his first paycheck as a freelancer. When he's not developing or writing, he enjoys tinkering with technology and mechanical things, photography, video games, playing hockey and spending time with his wife and their two dogs. Twitter: @johnsonch Website: http://www.johnsonch.com Blog: http://blog.johnsonch.com