Acceptance testing with Cucumber and Capybara
One of my first tasks as a developer was to migrate endless tests from Twist to Cucumber. Since then, I have written and refactored countless more, but I never had to set up Cucumber testing from zero. Until now. It was really not complicated, but it took me a while to get everything going. This is what I’ve come up with.
Prerequisites •
Bundler — the Ruby equivalent of npm. Just gem install bundler
.
phantomjs — get it from homebrew: brew install phantomjs
What to test? •
I’m prioritising main user stories — Can they log in and out? Can they navigate the page? Do they see the right content? Are more items loaded after they scroll a table? Can they submit forms and create items (e.g. messages, events)? Do the actions they perform have the right effect? Can they view and download invoices? …and so forth. I have an excel sheet for them — this way, even non-coders can add (request) test cases; and it’s a good way to track progress. One thing is for sure though: whenever something breaks, if it wasn’t tested before, I write a test for it.
Setup •
I will demo what I did for testing a simple sign in on our client-facing dashboard. I chose Selenium webdriver, because that’s what I’m used to, but Poltergeist looks very promising as well. I might try it out and compare experiences.
Our directory structure will look something like this:
.gitignore
.secrets
Gemfile
Rakefile
features/
|-- sign.feature
|-- step_definitions/
|-- sign.rb
|-- support/
|-- env.rb
First of all, let’s be secure and not push secrets to GitHub, even if it’s a private repo. Let’s keep them local or on the CI. For this, we have a .secrets
file that will hold our secrets. (Replace with your own – btw these creds are fake.)
export TEST_USER=kitten@cats-net.com
export TEST_PW=CorrectHorseBatteryStaple
Let’s put this file in our .gitignore
, to avoid pushing it accidentally.
# .gitignore
.secrets
For JS developers, our Gemfile
is basically what package.json
’s dependencies
or requirements.txt
does. Once we have it, we can run bundle install
and it installs all dependencies.
# Gemfile
source "https://rubygems.org"
gem 'rake'
group(:test) do
gem 'cucumber'
gem 'capybara'
gem 'rspec'
gem 'poltergeist'
gem 'selenium-webdriver'
gem 'chromedriver-helper'
end
I think about the Rakefile
as the scripts
part of a package.json
.
It enables us to call rake features
from the command line, which in turn will run all our tests.
# Rakefile
require 'cucumber'
require 'cucumber/rake/task'
task default: :features
Cucumber::Rake::Task.new(:features) do |t|
t.cucumber_opts = "--format pretty"
end
Some more configuration in env.rb
, and we are good to go. Here, we register a webdriver for the tests to run against, and configure an app_host
, which will be our base url.
# features/support/env.rb
require 'capybara'
require 'capybara/cucumber'
Capybara.register_driver :selenium do |app|
Capybara::Selenium::Driver.new(app, :browser => :chrome)
end
Capybara.configure do |config|
config.default_driver = :selenium
config.app_host = 'https://my-awesome-pets.com'
end
World(Capybara)
Ready for our first feature test? •
Features are written in Gherkin, an easy-to-read templating language that goes well with Cucumber.
# features/sign.feature
Feature: Sign in
Scenario: Sign in and see cats
Given I am on the Sign in page
When I sign in
Then I should see cats
These Given
, When
and Then
steps are regular expressions, and they can be matched to step definitions like this:
# features/step_definitions/sign.rb
Given /^I am on the Sign in page$/ do
visit('/sign-in') # we already have the base_url from env.rb
expect(page).to have_content('Sign in') # let's check if this really works
end
And /^I sign in$/ do
fill_in 'email', :with => $test_user
fill_in 'password', :with => $test_pw
find('button[type="submit"]').click
end
Then /^I should see (cats|dogs)$/ do |things|
expect(page).to have_content(things) # in our case, it will look for 'cats'.
end
Read more about expects and other matchers here.
That’s it, running rake features
should fire up a Chrome browser, visit my-awesome-pets.com
, sign in successfully, and report the results in the command line.