Feature
1 Feature: Design and Build an app using BDD
2 In order to produce an app at low cost
and high speed
3 As a developer
4 I should employ Rails with Cucumber
Friday, February 4, 2011
Scenario and Steps
Scenario: Description of what to test
Friday, February 4, 2011
Scenario and Steps
Scenario: Description of what to test
Given puts the system into a known state
Friday, February 4, 2011
Scenario and Steps
Scenario: Description of what to test
Given puts the system into a known state
When specifies the user’s actions
Friday, February 4, 2011
Scenario and Steps
Scenario: Description of what to test
Given puts the system into a known state
When specifies the user’s actions
Then we can observe the outcome
Friday, February 4, 2011
Scenario and Steps
Scenario: Description of what to test
Given puts the system into a known state
Given specifies the user’s actions
Given we can observe the outcome
Friday, February 4, 2011
Step Definitions
def log(*args)
puts args.join(',')
end
When /^three (.*) mice$/ do |disability|
log disability
end
When /^three blind (.*)$/ do |animal|
log animal
end
Friday, February 4, 2011
Step Definitions
def log(*args)
puts args.join(',')
end
When /^three (.*) mice$/ do |disability|
log disability
end
When /^three blind (.*)$/ do |animal|
log animal
end
Friday, February 4, 2011
Step Definitions
def log(*args)
puts args.join(',')
end
When /^three (.*) mice$/ do |disability|
log disability
end
When /^three blind (.*)$/ do |animal|
log animal
end
Friday, February 4, 2011
Step Definitions
def log(*args)
puts args.join(',')
end
When /^three (.*) mice$/ do |disability|
log disability
end
When /^three blind (.*)$/ do |animal|
log animal
end
Friday, February 4, 2011
Step Definitions
def log(*args)
puts args.join(',')
end
When /^three (.*) mice$/ do |disability|
log disability
end
When /^three blind (.*)$/ do |animal|
log animal
end
Friday, February 4, 2011
Step Definitions
def log(*args)
puts args.join(',')
end
When /^three (.*) mice$/ do |disability|
log disability
end
When /^three blind (.*)$/ do |animal|
log animal
end
Friday, February 4, 2011
Step Definitions
def log(*args)
puts args.join(',')
end
When /^three (.*) mice$/ do |disability|
log disability
end
When /^three blind (.*)$/ do |animal|
log animal
end
Friday, February 4, 2011
Around Hook
Around do |scenario, block|
2 puts "1st"
3 block.call
4 puts "1st"
5 end 6
7 Around do |scenario, block|
8 puts "2nd"
9 block.call
10 puts "2nd"
11 end
Friday, February 4, 2011
Around Hook
Scenario: How are the around hooks sequenced
When I run
Friday, February 4, 2011
Around Hook
Scenario: How are the around hooks sequenced
When I run
%wip
Using the wip profile...
Feature: Around hook sequencing
@wip
Scenario: How are the around hooks sequenced # features/around_hook.feature:7
1st
2nd
When I run # features/step_definitions/run_steps.rb:5
2nd
1st
1 scenario (1 passed)
1 step (1 passed)
0m1.569s
The --wip switch was used, so I didn't expect anything to pass. These scenarios passed:
Friday, February 4, 2011
Around Hook
Scenario: How are the around hooks sequenced
When I run
%wip
Using the wip profile...
Feature: Around hook sequencing
@wip
Scenario: How are the around hooks sequenced # features/around_hook.feature:7
1st
2nd
When I run # features/step_definitions/run_steps.rb:5
2nd
1st
1 scenario (1 passed)
1 step (1 passed)
0m1.569s
The --wip switch was used, so I didn't expect anything to pass. These scenarios passed:
Friday, February 4, 2011
Around Hook
Scenario: What happens when there is a failure
When I fail
% wip
Feature: Around hook sequencing
@wip
Scenario: What happens when there is a failure # features/around_hook.feature:10
1st
2nd
When I fail # features/step_definitions/run_steps.rb:9
(RuntimeError)
./features/step_definitions/run_steps.rb:10:in `/^I fail$/'
features/around_hook.feature:11:in `When I fail'
2nd
1st
Failing Scenarios:
cucumber -p wip features/around_hook.feature:10 # Scenario: What happens when there is a failure
1 scenario (1 failed)
1 step (1 failed)
0m1.522s
The --wip switch was used, so the failures were expected. All is good.
Friday, February 4, 2011
Around Hook
Scenario: What happens when there is a failure
When I fail
% wip
Feature: Around hook sequencing
@wip
Scenario: What happens when there is a failure # features/around_hook.feature:10
1st
2nd
When I fail # features/step_definitions/run_steps.rb:9
(RuntimeError)
./features/step_definitions/run_steps.rb:10:in `/^I fail$/'
features/around_hook.feature:11:in `When I fail'
2nd
1st
Failing Scenarios:
cucumber -p wip features/around_hook.feature:10 # Scenario: What happens when there is a failure
1 scenario (1 failed)
1 step (1 failed)
0m1.522s
The --wip switch was used, so the failures were expected. All is good.
Friday, February 4, 2011
AfterStep Hook
13 AfterStep do |scenario|
14 puts "after_step"
15 end
Friday, February 4, 2011
AfterStep Hook
Scenario: What happens when there is a failure
When I run
And I fail
Scenario: What happens when there is a failure # features/after_step_hook.feature:13
after_step
When I run # features/step_definitions/run_steps.rb:5
And I fail # features/step_definitions/run_steps.rb:9
(RuntimeError)
./features/step_definitions/run_steps.rb:10:in `/^I fail$/'
features/after_step_hook.feature:15:in `And I fail'
Friday, February 4, 2011
Tags
@likes
Scenario: This scenario is tagged by likes
Given this scenario is tagged "@likes"
Then the "likes" tag is on the scenario
Friday, February 4, 2011
Tags
% cucumber --tags @likes
Friday, February 4, 2011
Tags
% cucumber --tags ~@likes
Friday, February 4, 2011
Tags
% cucumber --tags @likes,@ratings
Friday, February 4, 2011
Tagged Hooks
1 Before('@given_user') do
2 @user = "This is set"
3 end
Friday, February 4, 2011
Tagged Hooks
1 Before('@given_user') do
2 @user = "This is set"
3 end
Friday, February 4, 2011
World Object
def log(*args)
puts args.join(',')
end
When /^three (.*) mice$/ do |disability|
log disability
end
When /^three blind (.*)$/ do |animal|
log animal
end
Friday, February 4, 2011
World Object
def log(*args)
puts args.join(',')
end
When /^three (.*) mice$/ do |disability|
log disability
end
When /^three blind (.*)$/ do |animal|
log animal
end
Friday, February 4, 2011
World Object
module Log
def log(*args)
puts args.join(',')
end
end
World(Log)
When /^three (.*) mice$/ do |disability|
log disability
end
When /^three blind (.*)$/ do |animal|
log animal
end
Friday, February 4, 2011
Tagged Hooks
1 Feature: Using Before and After with tags
2 In order to be more effective with cucumber
3 As a cucumberist
4 You can use Before and After with tags!
5
6 Scenario: Does not want the before step run
7 Then the user is not set
8
9 @given_user
0 Scenario: Does want the before step run
1 Then the user is set
Friday, February 4, 2011
Tagged Hooks
Then /^the user is( not)? set$/ do |negated|
if negated
@user.should_not be
else
@user.should be
end
end
Friday, February 4, 2011
Tagged Hooks
$ cucumber features/before_and_after_profile.feature
Using the default profile...
Feature: Using Before and After with tags
In order to be more effective with cucumber
As a cucumberist
You can use Before and After with tags!
Scenario: This scenario does not want the before step run # features/before_and_after_profile.featur
Then the user is not set # features/step_definitions/user_steps.rb:1
@given_user
Scenario: This scenario wants something set before it runs # features/before_and_after_profile.featur
Then the user is set # features/step_definitions/user_steps.rb:1
2 scenarios (2 passed)
2 steps (2 passed)
0m1.525s
Friday, February 4, 2011
Tagged Hooks
5 Before('@reviews,@likes') do
6 puts "This is an OR"
7 end
8
9 Before ('@reviews', '@likes') do
10 puts "This is an AND"
11 end
12
13 Before ('~@reviews') do
14 puts "This is NOT"
15 end
Friday, February 4, 2011
@wip
1 @wip
2 Feature: Resolving ambiguity with --guess
3
4 Scenario: Ambiguous step definitions
5 Given three blind mice
Friday, February 4, 2011
@wip
% cucumber -p wip
% rake cucumber:wip
% alias wip=‘cucumber -p wip’
Friday, February 4, 2011
@wip
<%
rerun = File.file?('rerun.txt') ? IO.read('rerun
rerun_opts = rerun.to_s.strip.empty? ? "--format
std_opts = "--format #{ENV['CUCUMBER_FORMAT'] ||
%>
default: <%= std_opts %> features
wip: --tags @wip:3 --wip features
rerun: <%= rerun_opts %> --format rerun --out re
Friday, February 4, 2011
@wip
<%
rerun = File.file?('rerun.txt') ? IO.read('rerun
rerun_opts = rerun.to_s.strip.empty? ? "--format
std_opts = "--format #{ENV['CUCUMBER_FORMAT'] ||
%>
default: <%= std_opts %> features
wip: --tags @wip:3 --wip features
rerun: <%= rerun_opts %> --format rerun --out re
Friday, February 4, 2011
@wip
% wip
Using the wip profile...
Feature: Using the path helper
@wip
Scenario: Using a regex with the path helper # features/paths.feature:7
Given the following movie: # features/step_definitions/fabrication_steps.rb:37
| title | Gone with the wind |
| year | 1939 |
When I go to the "Gone with the wind" movie page # features/step_definitions/web_steps.rb:30
Then I should see "Gone with the wind (1939)" # features/step_definitions/web_steps.rb:114
expected #has_content?("Gone with the wind (1939)") to return true, got false
(RSpec::Expectations::ExpectationNotMetError)
features/paths.feature:12:in `Then I should see "Gone with the wind (1939)"'
Failing Scenarios:
cucumber -p wip features/paths.feature:7 # Scenario: Using a regex with the path helper
1 scenario (1 failed)
3 steps (1 failed, 2 passed)
0m2.245s
The --wip switch was used, so the failures were expected. All is good.
Friday, February 4, 2011
@no-txn
@no-txn
Scenario: Sending a message without pusher
Given @philip_jay_fry signs in with Twitter
And I start a conversation with @t_leela
When I reply with "Hi Leela"
Then the source is the browser
Friday, February 4, 2011
@javascript
@javascript @pusher
Scenario: Starting a conversation with Pusher
Given @philip_jay_fry signs in with Twitter
When the browser has subscribed to Pusher
And I start a conversation with"@t_leela"
Then the source is pusher in the browser
Friday, February 4, 2011
path_to
Scenario: Context is king
Given the following movie:
| title | Gone with the wind |
| year | 1939 |
When the movie "Gone with the wind" has been liked 5 times
And I go to ‘/’
Then I should see "5 likes"
Friday, February 4, 2011
path_to
Scenario: Context is king
Given the following movie:
| title | Gone with the wind |
| year | 1939 |
When the movie "Gone with the wind" has been liked 5 times
And I go to ‘/’
Then I should see "5 likes"
Scenario: Context is king
Given the following movie:
| title | Gone with the wind |
| year | 1939 |
When the movie "Gone with the wind" has been liked 5 times
And I go to the home page
Then I should see "5 likes"
Friday, February 4, 2011
path_to
When /^(?:|I )am on (.+)$/ do |page_name|
visit path_to(page_name)
end
When /^(?:|I )go to (.+)$/ do |page_name|
visit path_to(page_name)
end
Friday, February 4, 2011
path_to
When /^(?:|I )am on (.+)$/ do |page_name|
visit path_to(page_name)
end
When /^(?:|I )go to (.+)$/ do |page_name|
visit path_to(page_name)
end
Friday, February 4, 2011
path_to
When /^(?:|I )am on (.+)$/ do |page_name|
visit path_to(page_name)
end
When /^(?:|I )go to (.+)$/ do |page_name|
visit path_to(page_name)
end
Friday, February 4, 2011
path_to
When /^(?:|I )am on (.+)$/ do |page_name|
visit path_to(page_name)
end
When /^(?:|I )go to (.+)$/ do |page_name|
visit path_to(page_name)
end
Friday, February 4, 2011
path_to
When /^(?:|I )am on (.+)$/ do |page_name|
visit path_to(page_name)
end
When /^(?:|I )go to (.+)$/ do |page_name|
visit path_to(page_name)
end
Friday, February 4, 2011
path_to
module NavigationHelpers
def path_to(page_name)
case page_name
when /the homes?page/
'/'
else
begin
page_name =~ /the (.*) page/
path_components = $1.split(/s+/)
self.send(path_components.push('path').join('_').to_sym)
rescue Object => e
raise "Can't find mapping from "#{page_name}" to a path.n" +
"Now, go and add a mapping in #{__FILE__}"
end
end
end
end
World(NavigationHelpers)
Friday, February 4, 2011
path_to
module NavigationHelpers
def path_to(page_name)
case page_name
when /the homes?page/
'/'
else
begin
page_name =~ /the (.*) page/
path_components = $1.split(/s+/)
self.send(path_components.push('path').join('_').to_sym)
rescue Object => e
raise "Can't find mapping from "#{page_name}" to a path.n" +
"Now, go and add a mapping in #{__FILE__}"
end
end
end
end
World(NavigationHelpers)
Friday, February 4, 2011
path_to
module NavigationHelpers
def path_to(page_name)
case page_name
when /the homes?page/
'/'
else
begin
page_name =~ /the (.*) page/
path_components = $1.split(/s+/)
self.send(path_components.push('path').join('_').to_sym)
rescue Object => e
raise "Can't find mapping from "#{page_name}" to a path.n" +
"Now, go and add a mapping in #{__FILE__}"
end
end
end
end
World(NavigationHelpers)
Friday, February 4, 2011
path_to
module NavigationHelpers
def path_to(page_name)
case page_name
when /the homes?page/
'/'
else
begin
page_name =~ /the (.*) page/
path_components = $1.split(/s+/)
self.send(path_components.push('path').join('_').to_sym)
rescue Object => e
raise "Can't find mapping from "#{page_name}" to a path.n" +
"Now, go and add a mapping in #{__FILE__}"
end
end
end
end
World(NavigationHelpers)
Friday, February 4, 2011
path_to
Scenario: Using a regex with the path helper
Given the following movie:
| title | Gone with the wind |
| year | 1939 |
When I go to the "Gone with the wind" movie page
Then I should see "Gone with the wind (1939)"
Friday, February 4, 2011
path_to
Scenario: Using a regex with the path helper
Given the following movie:
| title | Gone with the wind |
| year | 1939 |
When I go to the "Gone with the wind" movie page
Then I should see "Gone with the wind (1939)"
Friday, February 4, 2011
path_to
Scenario: Using a regex with the path helper
Given the following movie:
| title | Gone with the wind |
| year | 1939 |
When I go to the "Gone with the wind" movie page
Then I should see "Gone with the wind (1939)"
when /the "([^"]+)" movie page/
movie_path(Movie.find_by_title($1))
Friday, February 4, 2011
path_to
Scenario: Using a regex with the path helper
Given the following movie:
| title | Gone with the wind |
| year | 1939 |
When I go to the "Gone with the wind" movie page
Then I should see "Gone with the wind (1939)"
when /the "([^"]+)" movie page/
movie_path(Movie.find_by_title($1))
Friday, February 4, 2011
Specific
Scenario: Domain specific, totally opaque
Given a movie
When I go to the home page
Then I should see "Gone with the wind (1939)"
Friday, February 4, 2011
Specific
Scenario: Domain specific, totally opaque
Given a movie
When I go to the home page
Then I should see "Gone with the wind (1939)"
When /^a movie$/ do
Movie.create(title: 'Gone with the wind', year: 1939)
end
Friday, February 4, 2011
Specific
Scenario: Domain specific, totally opaque
Given a movie
When I go to the home page
Then I should see "Gone with the wind (1939)"
When /^a movie$/ do
Movie.create(title: 'Gone with the wind', year: 1939)
end
Friday, February 4, 2011
Specific
Scenario: Domain specific, totally opaque
Given a movie
When I go to the home page
Then I should see "Gone with the wind (1939)"
When /^a movie$/ do
Movie.create(title: 'Gone with the wind', year: 1939)
end
Friday, February 4, 2011
Imperative
Scenario: Way too granular
Given a movie
And I set the movie's title to "Gone with the wind"
And I set the movie's year to "1939"
And I save the movie
When I go to the home page
Then I should see "Gone with the wind (1939)"
Friday, February 4, 2011
Imperative
Scenario: Way too granular
Given a movie
And I set the movie's title to "Gone with the wind"
And I set the movie's year to "1939"
And I save the movie
When I go to the home page
Then I should see "Gone with the wind (1939)"
Friday, February 4, 2011
Imperative
Scenario: Way too granular
Given a movie
And I set the movie's title to "Gone with the wind"
And I set the movie's year to "1939"
And I save the movie
When I go to the home page
Then I should see "Gone with the wind (1939)"
Friday, February 4, 2011
Too much like Code
Scenario: Too much like code
Given a movie exists with { "title" => "Gone with the wind", "year" => "1939" }
When I go to the home page
Then I should see "Gone with the wind (1939)"
Friday, February 4, 2011
Too much like Code
Scenario: Too much like code
Given a movie exists with { "title" => "Gone with the wind", "year" => "1939" }
When I go to the home page
Then I should see "Gone with the wind (1939)"
When /^a (.+) exists with ({.+})$/ do |model_name, attributes|
model = dehumanize(model_name)
model.create(eval(attributes))
end
Friday, February 4, 2011
Too much like Code
Scenario: Too much like code
Given a movie exists with { "title" => "Gone with the wind", "year" => "1939" }
When I go to the home page
Then I should see "Gone with the wind (1939)"
When /^a (.+) exists with ({.+})$/ do |model_name, attributes|
model = dehumanize(model_name)
model.create(eval(attributes))
end
Yikes!
Friday, February 4, 2011
Too much like Code
Scenario: Too much like code
Given a movie exists with { "title" => "Gone with the wind", "year" => "1939" }
When I go to the home page
Then I should see "Gone with the wind (1939)"
`
When /^a (.+) exists with ({.+})$/ do |model_name, attributes|
model = dehumanize(model_name)
model.create(eval(attributes))
end
Friday, February 4, 2011
Cleaned Up
Scenario: Pickle
Given a movie exists with title: "Gone with the wind", year: "1939"
When I go to the home page
Then I should see "Gone with the wind (1939)"
Friday, February 4, 2011
Cleaned Up
Scenario: Pickle
Given a movie exists with title: "Gone with the wind", year: "1939"
When I go to the home page
Then I should see "Gone with the wind (1939)"
Friday, February 4, 2011
Generic Factory Step
Scenario: Generic factory step
Given the following movie:
| title | Gone with the wind |
| year | 1939 |
When I go to the home page
Then I should see "Gone with the wind (1939)"
Friday, February 4, 2011
Generic Factory Step
Scenario: Generic factory step
Given the following movie:
| title | Gone with the wind |
| year | 1939 |
When I go to the home page
Then I should see "Gone with the wind (1939)"
Friday, February 4, 2011
Using Tables
ruby-1.9.2-p0 :001 > table
=>
| title | year |
| Gone with the wind | 1939 |
ruby-1.9.2-p0 :002 > table.headers
=> ["title", "year"]
ruby-1.9.2-p0 :003 > table.rows
=> [["Gone with the wind", "1939"]]
ruby-1.9.2-p0 :004 > table.hashes
=> [{"title"=>"Gone with the wind", "year"=>"1939"}]
ruby-1.9.2-p0 :005 > table.rows_hash
=> {"title"=>"year", "Gone with the wind"=>"1939"}
Friday, February 4, 2011
Using Tables
ruby-1.9.2-p0 :001 > table
=>
| title | year |
| Gone with the wind | 1939 |
ruby-1.9.2-p0 :002 > table.headers
=> ["title", "year"]
ruby-1.9.2-p0 :003 > table.rows
=> [["Gone with the wind", "1939"]]
ruby-1.9.2-p0 :004 > table.hashes
=> [{"title"=>"Gone with the wind", "year"=>"1939"}]
ruby-1.9.2-p0 :005 > table.rows_hash
=> {"title"=>"year", "Gone with the wind"=>"1939"}
Friday, February 4, 2011
Using Tables
ruby-1.9.2-p0 :001 > table
=>
| title | year |
| Gone with the wind | 1939 |
ruby-1.9.2-p0 :002 > table.headers
=> ["title", "year"]
ruby-1.9.2-p0 :003 > table.rows
=> [["Gone with the wind", "1939"]]
ruby-1.9.2-p0 :004 > table.hashes
=> [{"title"=>"Gone with the wind", "year"=>"1939"}]
ruby-1.9.2-p0 :005 > table.rows_hash
=> {"title"=>"year", "Gone with the wind"=>"1939"}
Friday, February 4, 2011
Using Tables
ruby-1.9.2-p0 :001 > table
=>
| title | year |
| Gone with the wind | 1939 |
ruby-1.9.2-p0 :002 > table.headers
=> ["title", "year"]
ruby-1.9.2-p0 :003 > table.rows
=> [["Gone with the wind", "1939"]]
ruby-1.9.2-p0 :004 > table.hashes
=> [{"title"=>"Gone with the wind", "year"=>"1939"}]
ruby-1.9.2-p0 :005 > table.rows_hash
=> {"title"=>"year", "Gone with the wind"=>"1939"}
Friday, February 4, 2011
Using Tables
ruby-1.9.2-p0 :001 > table
=>
| title | year |
| Gone with the wind | 1939 |
ruby-1.9.2-p0 :002 > table.headers
=> ["title", "year"]
ruby-1.9.2-p0 :003 > table.rows
=> [["Gone with the wind", "1939"]]
ruby-1.9.2-p0 :004 > table.hashes
=> [{"title"=>"Gone with the wind", "year"=>"1939"}]
ruby-1.9.2-p0 :005 > table.rows_hash
=> {"title"=>"year", "Gone with the wind"=>"1939"}
Friday, February 4, 2011
Generic Factory Step
module FabricationMethods
def create_from_table(model_name, table, extra = {})
fabricator_name = generate_fabricator_name(model_name)
is_singular = model_name.to_s.singularize == model_name.to_s
hashes = is_singular ? [table.rows_hash] : table.hashes
@they = hashes.map do |hash|
hash = hash.merge(extra).inject({}) {|h,(k,v)| h.update(k.gsub(/W+/,'_').to_sym => v)
Fabricate(fabricator_name, hash)
end
if is_singular
@it = @they.last
instance_variable_set("@#{fabricator_name}", @it)
end
end
def generate_fabricator_name(model_name)
model_name.gsub(/W+/, '_').downcase.singularize.to_sym
end
end
World(FabricationMethods)
When /^the following ([^"]*):$/ do |model_name, table|
create_from_table(model_name, table)
end
Friday, February 4, 2011
Generic Factory Step
module FabricationMethods
def create_from_table(model_name, table, extra = {})
fabricator_name = generate_fabricator_name(model_name)
is_singular = model_name.to_s.singularize == model_name.to_s
hashes = is_singular ? [table.rows_hash] : table.hashes
@they = hashes.map do |hash|
hash = hash.merge(extra).inject({}) {|h,(k,v)| h.update(k.gsub(/W+/,'_').to_sym => v)
Fabricate(fabricator_name, hash)
end
if is_singular
@it = @they.last
instance_variable_set("@#{fabricator_name}", @it)
end
end
def generate_fabricator_name(model_name)
model_name.gsub(/W+/, '_').downcase.singularize.to_sym
end
end
World(FabricationMethods)
When /^the following ([^"]*):$/ do |model_name, table|
create_from_table(model_name, table)
end
Friday, February 4, 2011
Generic Factory Step
module FabricationMethods
def create_from_table(model_name, table, extra = {})
fabricator_name = generate_fabricator_name(model_name)
is_singular = model_name.to_s.singularize == model_name.to_s
hashes = is_singular ? [table.rows_hash] : table.hashes
@they = hashes.map do |hash|
hash = hash.merge(extra).inject({}) {|h,(k,v)| h.update(k.gsub(/W+/,'_').to_sym => v)
Fabricate(fabricator_name, hash)
end
if is_singular
@it = @they.last
instance_variable_set("@#{fabricator_name}", @it)
end
end
def generate_fabricator_name(model_name)
model_name.gsub(/W+/, '_').downcase.singularize.to_sym
end
end
World(FabricationMethods)
When /^the following ([^"]*):$/ do |model_name, table|
create_from_table(model_name, table)
end
Friday, February 4, 2011
Generic Factory Step
module FabricationMethods
def create_from_table(model_name, table, extra = {})
fabricator_name = generate_fabricator_name(model_name)
is_singular = model_name.to_s.singularize == model_name.to_s
hashes = is_singular ? [table.rows_hash] : table.hashes
@they = hashes.map do |hash|
hash = hash.merge(extra).inject({}) {|h,(k,v)| h.update(k.gsub(/W+/,'_').to_sym => v)
Fabricate(fabricator_name, hash)
end
if is_singular
@it = @they.last
instance_variable_set("@#{fabricator_name}", @it)
end
end
def generate_fabricator_name(model_name)
model_name.gsub(/W+/, '_').downcase.singularize.to_sym
end
end
World(FabricationMethods)
When /^the following ([^"]*):$/ do |model_name, table|
create_from_table(model_name, table)
end
Friday, February 4, 2011
Generic Factory Step
module FabricationMethods
def create_from_table(model_name, table, extra = {})
fabricator_name = generate_fabricator_name(model_name)
is_singular = model_name.to_s.singularize == model_name.to_s
hashes = is_singular ? [table.rows_hash] : table.hashes
@they = hashes.map do |hash|
hash = hash.merge(extra).inject({}) {|h,(k,v)| h.update(k.gsub(/W+/,'_').to_sym => v)
Fabricate(fabricator_name, hash)
end
if is_singular
@it = @they.last
instance_variable_set("@#{fabricator_name}", @it)
end
end
def generate_fabricator_name(model_name)
model_name.gsub(/W+/, '_').downcase.singularize.to_sym
end
end
World(FabricationMethods)
When /^the following ([^"]*):$/ do |model_name, table|
create_from_table(model_name, table)
end
Friday, February 4, 2011
Easy Relationships
Scenario: Has/Belongs to Relationships
Given the following movie:
| title | Gone with the wind |
| year | 1939 |
And that movie has the following role:
| name | Scarlett O'Hara |
And that role has the following actor:
| name | Vivian Leigh |
And that movie has the following role:
| name | Rhett Butler |
And that role has the following actor:
| name | Clark Gable |
When I go to the home page
And I follow "Gone with the wind (1939)"
Then I should see "Scarlett O'Hara - Vivian Leigh"
And I should see "Rhett Butler - Clark Gable"
Friday, February 4, 2011
Easy Relationships
Scenario: Has/Belongs to Relationships
Given the following movie:
| title | Gone with the wind |
| year | 1939 |
And that movie has the following role:
| name | Scarlett O'Hara |
And that role has the following actor:
| name | Vivian Leigh |
And that movie has the following role:
| name | Rhett Butler |
And that role has the following actor:
| name | Clark Gable |
When I go to the home page
And I follow "Gone with the wind (1939)"
Then I should see "Scarlett O'Hara - Vivian Leigh"
And I should see "Rhett Butler - Clark Gable"
Friday, February 4, 2011
Easy Relationships
Scenario: Has/Belongs to Relationships
Given the following movie:
| title | Gone with the wind |
| year | 1939 |
And that movie has the following role:
| name | Scarlett O'Hara |
And that role has the following actor:
| name | Vivian Leigh |
And that movie has the following role:
| name | Rhett Butler |
And that role has the following actor:
| name | Clark Gable |
When I go to the home page
And I follow "Gone with the wind (1939)"
Then I should see "Scarlett O'Hara - Vivian Leigh"
And I should see "Rhett Butler - Clark Gable"
Friday, February 4, 2011
Easy Relationships
Scenario: Has/Belongs to Relationships
Given the following movie:
| title | Gone with the wind |
| year | 1939 |
And that movie has the following role:
| name | Scarlett O'Hara |
And that role has the following actor:
| name | Vivian Leigh |
And that movie has the following role:
| name | Rhett Butler |
And that role has the following actor:
| name | Clark Gable |
When I go to the home page
And I follow "Gone with the wind (1939)"
Then I should see "Scarlett O'Hara - Vivian Leigh"
And I should see "Rhett Butler - Clark Gable"
Friday, February 4, 2011
Step Argument Transform
Scenario: Step argument transforms
Given the following movie:
| title | Gone with the wind |
| year | 1939 |
When that movie has been liked 5 times
And I go to the home page
Then I should see "5 likes"
Friday, February 4, 2011
Step Argument Transform
Scenario: Step argument transforms
Given the following movie:
| title | Gone with the wind |
| year | 1939 |
When that movie has been liked 5 times
And I go to the home page
Then I should see "5 likes"
Friday, February 4, 2011
Step Argument Transform
When /^that movie has been liked (d+) times$/ do |count|
count.to_i.times do |i|
@movie.like!
end
end
Friday, February 4, 2011
Step Argument Transform
When /^that movie has been liked (d+) times$/ do |count|
count.to_i.times do |i|
@movie.like!
end
end
Friday, February 4, 2011
Step Argument Transform
# Convert 'a' or 'an' to the integer value 1
Transform /^(an?|-?d+)$/ do |amount|
amount =~ /an?/ ? 1 : amount.to_i
end
When /^that movie has been liked (an?|-?d+) times$/ do |count|
count.times do |i|
@movie.like!
end
end
Friday, February 4, 2011
Step Argument Transform
# Convert 'a' or 'an' to the integer value 1
Transform /^(an?|-?d+)$/ do |amount|
amount =~ /an?/ ? 1 : amount.to_i
end
When /^that movie has been liked (an?|-?d+) times$/ do |count|
count.times do |i|
@movie.like!
end
end
Friday, February 4, 2011
Step Argument Transform
# Convert 'a' or 'an' to the integer value 1
Transform /^(an?|-?d+)$/ do |amount|
amount =~ /an?/ ? 1 : amount.to_i
end
When /^that movie has been liked (an?|-?d+) times$/ do |count|
count.times do |i|
@movie.like!
end
end
Friday, February 4, 2011
Step Argument Transform
# Convert 'a' or 'an' to the integer value 1
Transform /^(an?|-?d+)$/ do |amount|
amount =~ /an?/ ? 1 : amount.to_i
end
When /^that movie has been liked (an?|-?d+) times$/ do |count|
count.times do |i|
@movie.like!
end
end
Friday, February 4, 2011
Step Argument Transforms
Scenario: Context is king
Given the following movie:
| title | Gone with the wind |
| year | 1939 |
When the movie "Gone with the wind" has been liked 5 times
And I go to the home page
Then I should see "5 likes"
Friday, February 4, 2011
Step Argument Transforms
Scenario: Context is king
Given the following movie:
| title | Gone with the wind |
| year | 1939 |
When the movie "Gone with the wind" has been liked 5 times
And I go to the home page
Then I should see "5 likes"
Friday, February 4, 2011
Step Argument Transforms
Transform /^movie "([^"]+)"$/ do |title|
Movie.find_by_title(title)
end
When /^the (movie "(?:[^"]+)") has been liked (an?|-?d+) times$/ do |movie, count|
count.times do |i|
movie.like!
end
end
Friday, February 4, 2011
Step Argument Transforms
Transform /^movie "([^"]+)"$/ do |title|
Movie.find_by_title(title)
end
When /^the (movie "(?:[^"]+)") has been liked (an?|-?d+) times$/ do |movie, count|
count.times do |i|
movie.like!
end
end
Friday, February 4, 2011
Step Argument Transforms
Transform /^movie "([^"]+)"$/ do |title|
Movie.find_by_title(title)
end
When /^the (movie "(?:[^"]+)") has been liked (an?|-?d+) times$/ do |movie, count|
count.times do |i|
movie.like!
end
end
Friday, February 4, 2011
Step Argument Transforms
Transform /^movie "([^"]+)"$/ do |title|
Movie.find_by_title(title)
end
When /^the (movie "(?:[^"]+)") has been liked (an?|-?d+) times$/ do |movie, count|
count.times do |i|
movie.like!
end
end
Friday, February 4, 2011
Table Transforms
Transform /^table:name,actor$/ do |table|
table.map_column!(:actor) do |actor_name|
Actor.find_by_name(actor_name)
end
table
end
Friday, February 4, 2011
Table Transforms
Transform /^table:name,actor$/ do |table|
table.map_column!(:actor) do |actor_name|
Actor.find_by_name(actor_name)
end
table
end
Friday, February 4, 2011
Table Transforms
Transform /^table:name,actor$/ do |table|
table.map_column!(:actor) do |actor_name|
Actor.find_by_name(actor_name)
end
table
end
Friday, February 4, 2011
Table Transforms
Transform /^table:name,actor$/ do |table|
table.map_column!(:actor) do |actor_name|
Actor.find_by_name(actor_name)
end
table
end
Friday, February 4, 2011
Table Transforms
Scenario: Relationships using step transforms to transform the table
Given the following movie:
| title | Gone with the wind |
| year | 1939 |
And that movie has the following roles:
| name | actor |
| Scarlett O'Hara | Vivian Leigh |
| Rhett Butler | Clark Gable |
When I go to the home page
And I follow "Gone with the wind (1939)"
Then I should see "Scarlett O'Hara - Vivian Leigh"
And I should see "Rhett Butler - Clark Gable"
Friday, February 4, 2011
Table Transforms
Scenario: Relationships using step transforms to transform the table
Given the following movie:
| title | Gone with the wind |
| year | 1939 |
And that movie has the following roles:
| name | actor |
| Scarlett O'Hara | Vivian Leigh |
| Rhett Butler | Clark Gable |
When I go to the home page
And I follow "Gone with the wind (1939)"
Then I should see "Scarlett O'Hara - Vivian Leigh"
And I should see "Rhett Butler - Clark Gable"
Friday, February 4, 2011
Table Transforms
Transform /^table:name,actor$/ do |table|
table.map_column!(:actor) do |actor_name|
Fabricate(:actor, :name => actor_name)
end
table
end
Friday, February 4, 2011
Shipped Web Steps
Scenario: Viewing a group
When @philip_jay_fry signs in
And I go to the “Planet Express” group
Then I should see "Planet_Express" within "//h2"
And I should see "t_leela" within "//ul/li[@id='t_leela']"
And I should see "dr_hjfarnsworth" within "//ul/li[@id='dr_hjfarnswor
Friday, February 4, 2011
Shipped Web Steps
Scenario: Viewing a group
When @philip_jay_fry signs in
And I go to the “Planet Express” group
Then I should see "Planet_Express" within "//h2"
And I should see "t_leela" within "//ul/li[@id='t_leela']"
And I should see "dr_hjfarnsworth" within "//ul/li[@id='dr_hjfarnswor
Friday, February 4, 2011
Shipped Web Steps
module WithinHelpers
13def with_scope(locator)
14 locator ? within(locator) { yield } : yield
15end
16
end
17
World(WithinHelpers)
18
27 When /^(?:|I )press "([^"]*)"(?: within "([^"]*)")?$/ do |button, selector|
28 with_scope(selector) do
29 click_button(button)
30 end
31 end
32
33 When /^(?:|I )follow "([^"]*)"(?: within "([^"]*)")?$/ do |link, selector|
34 with_scope(selector) do
35 click_link(link)
36 end
37 end
38
39 When /^(?:|I )fill in "([^"]*)" with "([^"]*)"(?: within "([^"]*)")?$/ do |field
40 with_scope(selector) do
41 fill_in(field, :with => value)
42 end
43 end
44
Friday, February 4, 2011
Shipped Web Steps
module WithinHelpers
13def with_scope(locator)
14 locator ? within(locator) { yield } : yield
15end
16
end
17
World(WithinHelpers)
18
27 When /^(?:|I )press "([^"]*)"(?: within "([^"]*)")?$/ do |button, selector|
28 with_scope(selector) do
29 click_button(button)
30 end
31 end
32
33 When /^(?:|I )follow "([^"]*)"(?: within "([^"]*)")?$/ do |link, selector|
34 with_scope(selector) do
35 click_link(link)
36 end
37 end
38
39 When /^(?:|I )fill in "([^"]*)" with "([^"]*)"(?: within "([^"]*)")?$/ do |field
40 with_scope(selector) do
41 fill_in(field, :with => value)
42 end
43 end
44
Friday, February 4, 2011
Shipped Web Steps
module WithinHelpers
13def with_scope(locator)
14 locator ? within(locator) { yield } : yield
15end
16
end
17
World(WithinHelpers)
18
27 When /^(?:|I )press "([^"]*)"(?: within "([^"]*)")?$/ do |button, selector|
28 with_scope(selector) do
29 click_button(button)
30 end
31 end
32
33 When /^(?:|I )follow "([^"]*)"(?: within "([^"]*)")?$/ do |link, selector|
34 with_scope(selector) do
35 click_link(link)
36 end
37 end
38
39 When /^(?:|I )fill in "([^"]*)" with "([^"]*)"(?: within "([^"]*)")?$/ do |field
40 with_scope(selector) do
41 fill_in(field, :with => value)
42 end
43 end
44
Friday, February 4, 2011
Shipped Web Steps
module WithinHelpers
13def with_scope(locator)
14 locator ? within(locator) { yield } : yield
15end
16
end
17
World(WithinHelpers)
18
27 When /^(?:|I )press "([^"]*)"(?: within "([^"]*)")?$/ do |button, selector|
28 with_scope(selector) do
29 click_button(button)
30 end
31 end
32
33 When /^(?:|I )follow "([^"]*)"(?: within "([^"]*)")?$/ do |link, selector|
34 with_scope(selector) do
35 click_link(link)
36 end
37 end
38
39 When /^(?:|I )fill in "([^"]*)" with "([^"]*)"(?: within "([^"]*)")?$/ do |field
40 with_scope(selector) do
41 fill_in(field, :with => value)
42 end
43 end
44
Friday, February 4, 2011
Shipped Web Steps
module WithinHelpers
13def with_scope(locator)
14 locator ? within(locator) { yield } : yield
15end
16
end
17
World(WithinHelpers)
18
27 When /^(?:|I )press "([^"]*)"(?: within "([^"]*)")?$/ do |button, selector|
28 with_scope(selector) do
29 click_button(button)
30 end
31 end
32
33 When /^(?:|I )follow "([^"]*)"(?: within "([^"]*)")?$/ do |link, selector|
34 with_scope(selector) do
35 click_link(link)
36 end
37 end
38
39 When /^(?:|I )fill in "([^"]*)" with "([^"]*)"(?: within "([^"]*)")?$/ do |field
40 with_scope(selector) do
41 fill_in(field, :with => value)
42 end
43 end
44
Friday, February 4, 2011
Removing CSS/XPath
Scenario: Simple and Direct
Given the following movie:
| title | Gone with the wind |
| year | 1939 |
When I go to the home page
Then I should see "Gone with the wind (1939)" in the movie list
Friday, February 4, 2011
Removing CSS/XPath
Scenario: Simple and Direct
Given the following movie:
| title | Gone with the wind |
| year | 1939 |
When I go to the home page
Then I should see "Gone with the wind (1939)" in the movie list
Friday, February 4, 2011
Removing CSS/XPath
Scenario: Simple and Direct
Given the following movie:
| title | Gone with the wind |
| year | 1939 |
When I go to the home page
Then I should see "Gone with the wind (1939)" in the movie list
{
"in the movie list" => '.movies'
}.each do |within, selector|
When /^(.+) #{within}$/ do |step|
with_scope(selector) do
When step
end
end
end
Friday, February 4, 2011
Removing CSS/XPath
Scenario: Simple and Direct
Given the following movie:
| title | Gone with the wind |
| year | 1939 |
When I go to the home page
Then I should see "Gone with the wind (1939)" in the movie list
{
"in the movie list" => '.movies'
}.each do |within, selector|
When /^(.+) #{within}$/ do |step|
with_scope(selector) do
When step
end
end
end
Friday, February 4, 2011
Removing CSS/XPath
Scenario: Simple and Direct
Given the following movie:
| title | Gone with the wind |
| year | 1939 |
When I go to the home page
Then I should see "Gone with the wind (1939)" in the movie list
{
"in the movie list" => '.movies'
}.each do |within, selector|
When /^(.+) #{within}$/ do |step|
with_scope(selector) do
When step
end
end
end
Friday, February 4, 2011
Removing CSS/XPath
Scenario: Simple and Direct
Given the following movie:
| title | Gone with the wind |
| year | 1939 |
When I go to the home page
Then I should see "Gone with the wind (1939)" in the movie list
{
"in the movie list" => '.movies'
}.each do |within, selector|
When /^(.+) #{within}$/ do |step|
with_scope(selector) do
When step
end
end
end
Friday, February 4, 2011
Removing CSS/XPath
Scenario: Simple and Direct
Given the following movie:
| title | Gone with the wind |
| year | 1939 |
When I go to the home page
Then I should see "Gone with the wind (1939)" in the movie list
{
"in the movie list" => '.movies'
}.each do |within, selector|
When /^(.+) #{within}$/ do |step|
with_scope(selector) do
When step
end
end
end
Friday, February 4, 2011
Removing CSS/XPath
Scenario: Using selector_for
Given the following movie:
| title | Gone with the wind |
| year | 1939 |
When I go to the home page
Then I should see "Gone with the wind (1939)" within the movie list
Friday, February 4, 2011
Removing CSS/XPath
Scenario: Using selector_for
Given the following movie:
| title | Gone with the wind |
| year | 1939 |
When I go to the home page
Then I should see "Gone with the wind (1939)" within the movie list
Friday, February 4, 2011
Removing CSS/XPath
Scenario: Using selector_for
Given the following movie:
| title | Gone with the wind |
| year | 1939 |
When I go to the home page
Then I should see "Gone with the wind (1939)" within the movie list
When /^(.*) within ([^:"]+)$/ do |step, scope|
with_scope(selector_for(scope)) do
When step
end
end
Friday, February 4, 2011
Removing CSS/XPath
Scenario: Using selector_for
Given the following movie:
| title | Gone with the wind |
| year | 1939 |
When I go to the home page
Then I should see "Gone with the wind (1939)" within the movie list
When /^(.*) within ([^:"]+)$/ do |step, scope|
with_scope(selector_for(scope)) do
When step
end
end
Friday, February 4, 2011
Removing CSS/XPath
Scenario: Using selector_for
Given the following movie:
| title | Gone with the wind |
| year | 1939 |
When I go to the home page
Then I should see "Gone with the wind (1939)" within the movie list
When /^(.*) within ([^:"]+)$/ do |step, scope|
with_scope(selector_for(scope)) do
When step
end
end
Friday, February 4, 2011
selector_for
module HtmlSelectorsHelper
def selector_for(scope)
case scope
when /the body/
"html > body"
when /the movie list/
".movies"
else
raise "Can't find mapping from "#{scope}" to a selector.n" +
"Now, go and add a mapping in #{__FILE__}"
end
end
end
World(HtmlSelectorsHelper)
Friday, February 4, 2011
Persistent Scopes
Scenario: Persistent scoping
Given the following movies:
| title | year |
| Gone with the wind | 1939 |
| The Wizard of Oz | 1939 |
When I go to the home page
Then I should see "Gone with the wind (1939)" within the movie list
And also I should see "The Wizard of Oz (1939)"
Friday, February 4, 2011
Persistent Scopes
Scenario: Persistent scoping
Given the following movies:
| title | year |
| Gone with the wind | 1939 |
| The Wizard of Oz | 1939 |
When I go to the home page
Then I should see "Gone with the wind (1939)" within the movie list
And also I should see "The Wizard of Oz (1939)"
Friday, February 4, 2011
Persistent Scopes
module PersistentScope
def persistent_scope(scope = nil)
if scope
page.find(scope)
@persistent_scope = scope
end
@persistent_scope
end
end
World(PersistentScope)
When /^(.*) within ([^:"]+)$/ do |step, scope|
with_scope(persistent_scope(selector_for(scope))) do
When step
end
end
When /^also (.*)$/ do |step|
fail unless persistent_scope
with_scope(persistent_scope) do
When step
end
end
Friday, February 4, 2011
Persistent Scopes
module PersistentScope
def persistent_scope(scope = nil)
if scope
page.find(scope)
@persistent_scope = scope
end
@persistent_scope
end
end
World(PersistentScope)
When /^(.*) within ([^:"]+)$/ do |step, scope|
with_scope(persistent_scope(selector_for(scope))) do
When step
end
end
When /^also (.*)$/ do |step|
fail unless persistent_scope
with_scope(persistent_scope) do
When step
end
end
Friday, February 4, 2011
Persistent Scopes
module PersistentScope
def persistent_scope(scope = nil)
if scope
page.find(scope)
@persistent_scope = scope
end
@persistent_scope
end
end
World(PersistentScope)
When /^(.*) within ([^:"]+)$/ do |step, scope|
with_scope(persistent_scope(selector_for(scope))) do
When step
end
end
When /^also (.*)$/ do |step|
fail unless persistent_scope
with_scope(persistent_scope) do
When step
end
end
Friday, February 4, 2011
Persistent Scopes
module PersistentScope
def persistent_scope(scope = nil)
if scope
page.find(scope)
@persistent_scope = scope
end
@persistent_scope
end
end
World(PersistentScope)
When /^(.*) within ([^:"]+)$/ do |step, scope|
with_scope(persistent_scope(selector_for(scope))) do
When step
end
end
When /^also (.*)$/ do |step|
fail unless persistent_scope
with_scope(persistent_scope) do
When step
end
end
Friday, February 4, 2011
Persistent Scopes
module PersistentScope
def persistent_scope(scope = nil)
if scope
page.find(scope)
@persistent_scope = scope
end
@persistent_scope
end
end
World(PersistentScope)
When /^(.*) within ([^:"]+)$/ do |step, scope|
with_scope(persistent_scope(selector_for(scope))) do
When step
end
end
When /^also (.*)$/ do |step|
fail unless persistent_scope
with_scope(persistent_scope) do
When step
end
end
Friday, February 4, 2011
Imperative
Scenario: Successful animal creation
Given I'm on the animal creation page
When I fill in Name with 'Alligator'
And select Phylum as 'Chordata'
And fill in Animal Class with 'Sauropsida'
And fill in Order with 'Crocodilia'
And fill in Family with 'Alligatoridae'
And fill in Genus with 'Alligator'
And check Lay Eggs
And click the Create button
Then I should see the notice 'Thank you for your animal submission!'
And the page should include the animal's name, phylum, animal class,
Friday, February 4, 2011
Declarative
Scenario: Successful animal creation
Given I'm on the animal creation page
When I add a new animal
Then I should see the page for my newly created animal
And the notice 'Thank you for your animal submission!'
Friday, February 4, 2011
UX
Feature: Visitor uses advertiser carousel
Background:
Given the following advertiser:
| name | Lowe's |
And that advertiser has the following coupons:
| description |
| Free free free |
And the following advertiser:
| name | Home Depot |
And that advertiser has the following coupons:
| description |
| Buy three storage bins and get the next 20 absolutely free for a limited time! |
When I go to the homepage
Scenario: populating the carousel
Then I should see "Lowe's coupons" within the advertiser carousel
And I should see "Free free free" within the advertiser carousel
And I should see "Home Depot coupons" within the advertiser carousel
And I should see "Buy three storage" within the advertiser carousel
Scenario: truncating the coupon copy
Then I should see "Buy three storage bins and get the next 20 absolute..." within the advertiser carousel
Scenario: viewing all coupons for an advertiser
When I follow "Lowe's coupons" within the advertiser carousel
Then I should see "Coupons for Lowe's"
And I should see "Free free free"
And I should not see "Buy three storage bins"
And I should not see "View all Lowe's coupons"
Friday, February 4, 2011