Talk given by Joseph Wilk at Scotland on Rails 2009. Examines how Cucumber and Rspec fit together in the testing workflow, how and why Cucumber is useful and how it works. Walks through a simple example based on renting DVDs showing how to use Cucumber and some of the best practices. Looks at how Webrat can drive Selenium to in-turn drive Cucumber features through the browser.
7. Scenario: Happy SoR attendees
Given people turned up
When Joseph talks
Then everyone should acquire some new knowledge
And no-one should fall asleep
And no rotten food should be thrown
24. Cucumber Feature
Not
executed
Feature: Be awesome
Narrative
Scenario: title Example of
Given <some context> behaviour
And <yet more context>
When <some action>
And <more actions>
Then <some outcome>
And <more outcomes>
25. regexp match
Step
definition
Given /^we like (.*)$/i do |fruit|
fruit.should == 'cukes'
Ruby tests #assert_equal(fruit, 'cukes')
end
Plaintext Given we like cukes
Feature
Cucumber
28. огурец Russian Chinese
concombre French Korean
gurka Swedish
Japanese
German castravete Romanian
Gurke
ogórek
Cucumber English Polish
pepino Spanish
Italian
cetriolo
Danish
agurk
ﺍﳋﻴﺎﺭ Arabic
Indonisean
ketimun
29. огурец Russian Chinese
concombre French Korean
gurka Swedish
Japanese
German castravete Romanian
Gurke
ogórek
Cucumber English Polish
pepino Spanish
Treetop Rocks
Italian
cetriolo
ANTLR
Danish
agurk
could rock
ﺍﳋﻴﺎﺭ Arabic
Indonisean
harder
ketimun
49. Feature (terrible)
Value
Feature: select a movie to rent with priority
In order to maximise allocation of films
The website user
Needs to be able to add movies to their rental list with a priority
Role Feature
50. Feature (terrible)
Value
Feature: select a movie to rent with priority
In order to maximise allocation of films
Narrative
The website user
Needs to be able to add movies to their rental list with a priority
Role Feature
51. Feature (terrible)
Value
Feature: select a movie to rent with priority
In order to maximise allocation of films
The website user
Needs to be able to add movies to their rental list with a priority
Role Feature
52. Feature (terrible)
Feature: select a movie to rent with priority
In order to maximise allocation of films
The website user
Needs to be able to add movies to their rental list with a priority
53. Feature (terrible)
Feature: select a movie to rent with priority
In order to maximise allocation of films
The website user
Needs to be able to add movies to their rental list with a priority
Noise
54. Feature (terrible)
Feature: select a movie to rent with priority
In order to maximise allocation of films
The website user
Needs to be able to add movies to their rental list with a priority
Too generic
role
55. Feature (terrible)
Feature: select a movie to rent with priority
In order to maximise allocation of films
The website user Film member
Needs to be able to add movies to their rental list with a priority
Too generic
role
56. Feature (terrible)
Role can change
feature
Feature: select a movie to rent with priority
In order to maximise allocation of films
The website user Film member
Needs to be able to add movies to their rental list with a priority
57. Feature (terrible)
Role can change
feature
Film Member selects a movie to rent with priority
Feature: select a movie to rent with priority
In order to maximise allocation of films
The website user Film member
Needs to be able to add movies to their rental list with a priority
58. Nice
Feature (terrible)
Film Member selects a movie to rent with priority
Feature: select a movie to rent with priority
In order to maximise allocation of films
The website user Film member
Needs to be able to add movies to their rental list with a priority
60. Scenarios
Feature: Film Member selects a movie to rent with priority
In order to maximise allocation of films
The Film member
Needs to add movies to their rental list with a priority
Scenario: High priority
61. Scenarios
Feature: Film Member selects a movie to rent with priority
In order to maximise allocation of films
The Film member
Needs to add movies to their rental list with a priority
Scenario: High priority
Then I should see quot;My rental listquot;
And I should see quot;Casshernquot; in my rental list
And quot;Casshernquot; should be marked as quot;High priorityquot;
62. Scenarios
Feature: Film Member selects a movie to rent with priority
In order to maximise allocation of films
The Film member
Needs to add movies to their rental list with a priority
Scenario: High priority
When I choose quot;High priorityquot;
And I press quot;Rentquot;
Then I should see quot;My rental listquot;
And I should see quot;Casshernquot; in my rental list
And quot;Casshernquot; should be marked as quot;High priorityquot;
63. Scenarios
Feature: Film Member selects a movie to rent with priority
In order to maximise allocation of films
The Film member
Needs to add movies to their rental list with a priority
Scenario: High priority
Given I'm logged in
And I am viewing the movie quot;Casshernquot;
When I choose quot;High priorityquot;
And I press quot;Rentquot;
Then I should see quot;My rental listquot;
And I should see quot;Casshernquot; in my rental list
And quot;Casshernquot; should be marked as quot;High priorityquot;
70. Fixtures
Scenario: search results found Given /^the Movies$/i do |movie_hash|
Given the Movies #{:title => quot;The colour whitequot;},
| title | #{:title => quot;The colour redquot;},
| The colour white | #{:title => quot;Casshernquot;}
| The colour red | movies.hashes.each do |values|
| Casshern | Movie.create!(values)
When I search for quot;colourquot; end
Then I will see 2 results end
Scenario: search results found
Given 2 films with quot;colourquot; in the title
When I search for quot;colourquot;
Then I will see 2 results
71. Stick it to the World
module NavigationHelpers
def path_to(page_name)
case page_name
when /the homepage/
root_path
else
raise quot;Can't find mapping from quot;#{page_name}quot; to a path.quot;
end
end
end
World do |world|
world.extend NavigationHelpers
world
end
72. Hooks
Hooks are GLOBAL!
Before do
# do something before each scenario.
end
After do
#do something after each scenario
end
73. How many scenarios is
enough?
• Given/When/Then
“Finite state machine” Uncle Bob
• What’s the Return on Investment?
75. Cowcumbers
Given /^dirty state$/ do
@movie = Movie.create!
Relying on state (too much) end
Given /^coupled by state$/ do
@movie.title = quot;yuckyquot;
end
Given /^does a user care$/ do
response.current_url == ‘silly’
end
Tests without user value Given /^checking the db$/ do
Movie.find(1).should_not == nil
end
77. Concrete vs Abstract
Scenarios
Given I'm logged in
Given I go to the login page
And I fill in quot;usernamequot; with quot;josephquot;
And I fill in quot;passwordquot; with quot;cukerquot;
And I click quot;loginquot;
Domain understanding
Concrete Abstract
78. Calling steps from steps
Given /I’m logged in/ do
User.create!(:user => 'josephwilk', :password => quot;passquot;)
Given 'I fill in quot;passwordquot; with quot;josephwilkquot;'
Given 'I fill in quot;passwordquot; with quot;passquot;'
Given 'I click quot;loginquot;'
end
82. Webrat / Selenium
# Sets up the Rails environment for Cucumber
ENV[quot;RAILS_ENVquot;] ||= quot;seleniumquot;
require File.expand_path(File.dirname(__FILE__) + '/../../config/environment')
require 'cucumber/rails/world'
require 'cucumber/formatters/unicode'
Turn off
#Cucumber::Rails.use_transactional_fixtures
require 'webrat'
Webrat.configure do |config|
Switch to Selenium
config.mode = :selenium
end
require 'cucumber/rails/rspec'
require 'webrat/core/matchers'
Before do
Movie.delete_all
Manually cleanup
RentalRequest.delete_all
end