• Share
  • Email
  • Embed
  • Like
  • Save
  • Private Content
Cultivating Cucumber
 

Cultivating Cucumber

on

  • 2,408 views

Tips, Techniques, and Opinions on being more effective with Cucumber

Tips, Techniques, and Opinions on being more effective with Cucumber

Statistics

Views

Total Views
2,408
Views on SlideShare
2,397
Embed Views
11

Actions

Likes
4
Downloads
46
Comments
0

3 Embeds 11

http://lanyrd.com 9
http://twitter.com 1
https://lanyrd.com 1

Accessibility

Categories

Upload Details

Uploaded via as Adobe PDF

Usage Rights

CC Attribution License

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

    Cultivating Cucumber Cultivating Cucumber Document Transcript

    • Friday, February 4, 2011
    • @leshillFriday, February 4, 2011
    • Friday, February 4, 2011
    • Rocketeer #7Friday, February 4, 2011
    • Friday, February 4, 2011
    • We are hiring. http://pictureofhealth.comFriday, February 4, 2011
    • Cultivating Cucumber It is great food for thought!Friday, February 4, 2011
    • HappyFriday, February 4, 2011
    • Not so HappyFriday, February 4, 2011
    • Confident! And Happy!Friday, February 4, 2011
    • BackgroundFriday, February 4, 2011
    • Feature1 Feature: Design and Build an app using BDD2 In order to produce an app at low cost and high speed3 As a developer4 I should employ Rails with CucumberFriday, February 4, 2011
    • Scenario and Steps Scenario: Description of what to testFriday, February 4, 2011
    • Scenario and Steps Scenario: Description of what to test Given puts the system into a known stateFriday, 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 actionsFriday, 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 outcomeFriday, 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 outcomeFriday, 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 endFriday, 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 endFriday, 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 endFriday, 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 endFriday, 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 endFriday, 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 endFriday, 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 endFriday, February 4, 2011
    • HooksFriday, 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 endFriday, February 4, 2011
    • Around Hook Scenario: How are the around hooks sequenced When I runFriday, 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 didnt 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 didnt expect anything to pass. These scenarios passed:Friday, February 4, 2011
    • Around HookScenario: What happens when there is a failure When I failFriday, February 4, 2011
    • Around HookScenario: 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 HookScenario: 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
    • HappyFriday, February 4, 2011
    • AfterStep Hook 13 AfterStep do |scenario| 14 puts "after_step" 15 endFriday, 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 failFriday, February 4, 2011
    • Not so HappyFriday, February 4, 2011
    • Global Hooks # features/support/global.rb my_heavy_object = HeavyObject.new 18 my_heavy_object.do_it 19 20 at_exit do 21 my_heavy_object.undo_it 22 endFriday, February 4, 2011
    • AfterConfiguration Hook AfterConfiguration do |config|25 puts "Features in #{config.feature_dirs}"26 end Friday, February 4, 2011
    • TagsFriday, 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 scenarioFriday, February 4, 2011
    • Tags % cucumber --tags @likesFriday, February 4, 2011
    • Tags % cucumber --tags ~@likesFriday, February 4, 2011
    • Tags % cucumber --tags @likes,@ratingsFriday, February 4, 2011
    • Tags % cucumber --tags @likes --tags @ratingsFriday, February 4, 2011
    • Confident! And Happy!Friday, February 4, 2011
    • Tagged HooksFriday, February 4, 2011
    • Tagged Hooks 1 Before(@given_user) do 2 @user = "This is set" 3 endFriday, February 4, 2011
    • Tagged Hooks 1 Before(@given_user) do 2 @user = "This is set" 3 endFriday, 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 endFriday, 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 endFriday, 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 endFriday, February 4, 2011
    • Tagged Hooks1 Feature: Using Before and After with tags2 In order to be more effective with cucumber3 As a cucumberist4 You can use Before and After with tags!56 Scenario: Does not want the before step run7 Then the user is not set89 @given_user0 Scenario: Does want the before step run1 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 endFriday, 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.525sFriday, February 4, 2011
    • HappyFriday, February 4, 2011
    • Not so HappyFriday, 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 endFriday, February 4, 2011
    • Not so HappyFriday, February 4, 2011
    • Special TagsFriday, February 4, 2011
    • @wip 1 @wip 2 Feature: Resolving ambiguity with --guess 3 4 Scenario: Ambiguous step definitions 5 Given three blind miceFriday, 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(rerunrerun_opts = rerun.to_s.strip.empty? ? "--formatstd_opts = "--format #{ENV[CUCUMBER_FORMAT] ||%>default: <%= std_opts %> featureswip: --tags @wip:3 --wip featuresrerun: <%= rerun_opts %> --format rerun --out reFriday, February 4, 2011
    • @wip<%rerun = File.file?(rerun.txt) ? IO.read(rerunrerun_opts = rerun.to_s.strip.empty? ? "--formatstd_opts = "--format #{ENV[CUCUMBER_FORMAT] ||%>default: <%= std_opts %> featureswip: --tags @wip:3 --wip featuresrerun: <%= rerun_opts %> --format rerun --out reFriday, 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
    • Confident! And Happy!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 browserFriday, 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 browserFriday, February 4, 2011
    • HappyFriday, February 4, 2011
    • Using path_toFriday, 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) endFriday, 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) endFriday, 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) endFriday, 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) endFriday, 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) endFriday, February 4, 2011
    • path_tomodule 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 "Cant find mapping from "#{page_name}" to a path.n" + "Now, go and add a mapping in #{__FILE__}" end end endendWorld(NavigationHelpers)Friday, February 4, 2011
    • path_tomodule 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 "Cant find mapping from "#{page_name}" to a path.n" + "Now, go and add a mapping in #{__FILE__}" end end endendWorld(NavigationHelpers)Friday, February 4, 2011
    • path_tomodule 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 "Cant find mapping from "#{page_name}" to a path.n" + "Now, go and add a mapping in #{__FILE__}" end end endendWorld(NavigationHelpers)Friday, February 4, 2011
    • path_tomodule 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 "Cant find mapping from "#{page_name}" to a path.n" + "Now, go and add a mapping in #{__FILE__}" end end endendWorld(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
    • Confident! And Happy!Friday, February 4, 2011
    • Building A FactoryFriday, February 4, 2011
    • SpecificScenario: 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
    • SpecificScenario: 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) endFriday, February 4, 2011
    • SpecificScenario: 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) endFriday, February 4, 2011
    • SpecificScenario: 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) endFriday, February 4, 2011
    • Imperative Scenario: Way too granular Given a movie And I set the movies title to "Gone with the wind" And I set the movies 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 movies title to "Gone with the wind" And I set the movies 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 movies title to "Gone with the wind" And I set the movies 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)) endFriday, 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)) endFriday, February 4, 2011
    • Not so HappyFriday, February 4, 2011
    • Cleaned UpScenario: 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 UpScenario: 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 StepScenario: 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 StepScenario: 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) endFriday, 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) endFriday, 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) endFriday, 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) endFriday, 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) endFriday, 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 OHara | 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 OHara - 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 OHara | 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 OHara - 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 OHara | 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 OHara - 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 OHara | 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 OHara - Vivian Leigh" And I should see "Rhett Butler - Clark Gable"Friday, February 4, 2011
    • Confident! And Happy!Friday, February 4, 2011
    • TransformsFriday, 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 endFriday, 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 endFriday, 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 endFriday, 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 endFriday, 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 endFriday, 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 endFriday, February 4, 2011
    • Not so HappyFriday, 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 endFriday, 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 endFriday, 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 endFriday, 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 endFriday, February 4, 2011
    • Confident! And Happy!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 endFriday, 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 endFriday, 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 endFriday, 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 endFriday, 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 OHara | 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 OHara - 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 OHara | 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 OHara - 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 endFriday, February 4, 2011
    • HappyFriday, February 4, 2011
    • Not so HappyFriday, February 4, 2011
    • Better UI ScopesFriday, February 4, 2011
    • Shipped Web StepsScenario: 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_hjfarnsworFriday, February 4, 2011
    • Shipped Web StepsScenario: 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_hjfarnsworFriday, 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 44Friday, 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 44Friday, 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 44Friday, 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 44Friday, 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 44Friday, February 4, 2011
    • Not so HappyFriday, 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 listFriday, 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 listFriday, 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 endFriday, 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 endFriday, 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 endFriday, 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 endFriday, 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 endFriday, February 4, 2011
    • HappyFriday, 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 listFriday, 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 listFriday, 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 endFriday, 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 endFriday, 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 endFriday, 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 "Cant 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
    • HappyFriday, February 4, 2011
    • Persistent ScopesScenario: 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 ScopesScenario: 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 endFriday, 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 endFriday, 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 endFriday, 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 endFriday, 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 endFriday, February 4, 2011
    • Confident! And Happy!Friday, February 4, 2011
    • Write Better ScenariosFriday, February 4, 2011
    • ImperativeScenario: Successful animal creation Given Im 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 animals name, phylum, animal class,Friday, February 4, 2011
    • Declarative Scenario: Successful animal creation Given Im 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 | Lowes | 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 "Lowes 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 "Lowes coupons" within the advertiser carousel Then I should see "Coupons for Lowes" And I should see "Free free free" And I should not see "Buy three storage bins" And I should not see "View all Lowes coupons"Friday, February 4, 2011
    • Outside InFriday, February 4, 2011
    • Confident! And Happy!Friday, February 4, 2011
    • Cucumber: The Bad PartsFriday, February 4, 2011
    • Not so HappyFriday, February 4, 2011
    • Cucumber: The Good PartFriday, February 4, 2011
    • HappyFriday, February 4, 2011
    • Thank you!Friday, February 4, 2011