writing software not code with cucumber
DESCRIPTION
Describes Outside-In development and Behvaiour Driven Development. Illustrates basic Cucumber usage within a Rails app and then goes over more advanced topics such as JS as web services.TRANSCRIPT
![Page 1: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/1.jpg)
With
Ben Mabey
Writing Software not code
![Page 2: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/2.jpg)
With
Ben Mabey
Writing Software not code
![Page 3: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/3.jpg)
With
Ben Mabey
Writing Software not code
Behaviour Driven Development
![Page 4: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/4.jpg)
?
![Page 5: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/5.jpg)
![Page 6: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/6.jpg)
Tweet in the blanks...
"most software projects are like _ _ _ _ _ _ _ _"
#rubyhoedown #cucumber
![Page 7: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/7.jpg)
"most software projects are like _ _ _ _ _ _ _ _"
#rubyhoedown #cucumber
![Page 8: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/8.jpg)
![Page 9: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/9.jpg)
![Page 10: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/10.jpg)
So... why are software projects like “The Homer”?
![Page 11: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/11.jpg)
![Page 12: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/12.jpg)
![Page 13: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/13.jpg)
![Page 14: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/14.jpg)
Feature Devotion
TextPlacing emphasis on features instead of
overall outcome
![Page 15: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/15.jpg)
![Page 16: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/16.jpg)
Shingeo Shingo of Toyota says...
![Page 17: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/17.jpg)
"Inspection to find defects is waste."
![Page 18: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/18.jpg)
"Inspection to prevent defects is
essential."
"Inspection to find defects is waste."
![Page 19: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/19.jpg)
56% of all bugs are introduced in requirements. (CHAOS Report)
![Page 20: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/20.jpg)
Root Cause Analysis
![Page 21: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/21.jpg)
Popping the Why Stack...
![Page 22: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/22.jpg)
![Page 23: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/23.jpg)
Protect Revenue
Increase Revenue
Manage Cost
![Page 24: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/24.jpg)
![Page 25: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/25.jpg)
Feature: title
In order to [Business Value]As a [Role]I want to [Some Action] (feature)
* not executed* documentation value* variant of contextra* business value up front
![Page 26: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/26.jpg)
There is no template.What is important to have in narrative:
* business value * stakeholder role * user role * action to be taken by user
![Page 27: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/27.jpg)
<rant>
![Page 28: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/28.jpg)
With
Ben Mabey
Writing Software not code
Behaviour Driven Development
![Page 29: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/29.jpg)
!= BDD
![Page 30: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/30.jpg)
!= BDD
![Page 31: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/31.jpg)
RSpec != BDD
![Page 32: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/32.jpg)
RSpec != BDD
![Page 33: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/33.jpg)
“All of these tools are great... but, in the end, tools are tools. While RSpec and Cucumber are optimized for BDD, using them
doesn’t automatically mean you’re doing BDD"
The RSpec Book
![Page 34: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/34.jpg)
BDD is a mindset
not a tool set
![Page 35: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/35.jpg)
</rant>
![Page 36: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/36.jpg)
Feature: title
In order to [Business Value]As a [Role]I want to [Some Action] (feature)
* not executed* documentation value* variant of contextra* business value up front
![Page 37: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/37.jpg)
Scenario: titleGiven [Context]When I do [Action]Then I should see [Outcome]
![Page 38: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/38.jpg)
Scenario: titleGiven [Context]And [More Context]When I do [Action]And [Other Action]Then I should see [Outcome]But I should not see [Outcome]
![Page 39: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/39.jpg)
project_root/| `-- features
![Page 40: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/40.jpg)
project_root/| `-- features |-- awesomeness.feature |-- greatest_ever.feature
![Page 41: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/41.jpg)
project_root/| `-- features |-- awesomeness.feature |-- greatest_ever.feature `-- support |-- env.rb `-- other_helpers.rb
![Page 42: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/42.jpg)
project_root/| `-- features |-- awesomeness.feature |-- greatest_ever.feature `-- support |-- env.rb `-- other_helpers.rb |-- step_definitions | |-- domain_concept_A.rb | `-- domain_concept_B.rb
![Page 43: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/43.jpg)
Step
Given a widget
![Page 44: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/44.jpg)
Step
Given a widgetGiven /^a widget$/ do #codes go hereend
Definition
![Page 45: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/45.jpg)
Step
Given a widgetGiven /^a widget$/ do #codes go hereend
Definition
Step Mother
![Page 46: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/46.jpg)
Step
Given a widgetGiven /^a widget$/ do #codes go hereend
Definition
Step Mother
![Page 47: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/47.jpg)
a.featureb.feature
![Page 48: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/48.jpg)
a.featureb.feature
![Page 49: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/49.jpg)
a.featureb.feature
![Page 50: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/50.jpg)
a.featureb.feature 28+
Languages
![Page 51: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/51.jpg)
a.featureb.feature
x_steps.rby_steps.rb
28+ Languages
![Page 52: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/52.jpg)
a.featureb.feature
x_steps.rby_steps.rb
RSpec, Test::Unit, etc
28+ Languages
![Page 53: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/53.jpg)
a.featureb.feature
x_steps.rby_steps.rb
Your Code
RSpec, Test::Unit, etc
28+ Languages
![Page 54: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/54.jpg)
Not Just for Rails
![Page 55: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/55.jpg)
Outside-In
![Page 56: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/56.jpg)
![Page 57: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/57.jpg)
![Page 58: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/58.jpg)
Write Scenarios
![Page 59: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/59.jpg)
Steps are pending
![Page 60: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/60.jpg)
Write Step Definition
![Page 61: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/61.jpg)
Go Down A Gear
![Page 62: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/62.jpg)
RSpec, TestUnit, etc
![Page 63: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/63.jpg)
Write Code Example(Unit Test)
![Page 64: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/64.jpg)
Make Example Pass
![Page 65: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/65.jpg)
REFACTOR!!
![Page 66: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/66.jpg)
Where Are we?
![Page 67: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/67.jpg)
Continue until...
![Page 68: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/68.jpg)
REFACTORand
REPEAT
![Page 69: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/69.jpg)
features/manage_my_wishes.feature
Feature: manage my wishes
In order to get more stuff As a greedy person I want to manage my wish list for my family members to view @proposed Scenario: add wish
@proposed Scenario: remove wish
@proposed Scenario: tweet wish
![Page 70: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/70.jpg)
features/manage_my_wishes.feature
Feature: manage my wishes
In order to get more stuff As a greedy person I want to manage my wish list for my family members to view
@wip Scenario: add wish Given I am logged in When I make a "New car" wish Then "New car" should appear on my wish list
@proposedScenario: remove wish
@proposedScenario: tweet wish
Work In Progress
![Page 71: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/71.jpg)
Workflow
![Page 72: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/72.jpg)
Workflow
git branch -b add_wish_tracker#
![Page 73: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/73.jpg)
Workflow
git branch -b add_wish_tracker#Tag Scenario or Feature with @wip
![Page 74: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/74.jpg)
Workflow
git branch -b add_wish_tracker#Tag Scenario or Feature with @wip
cucumber --wip --tags @wip
![Page 75: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/75.jpg)
Workflow
git branch -b add_wish_tracker#Tag Scenario or Feature with @wip
cucumber --wip --tags @wipDevelop it Outside-In
![Page 76: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/76.jpg)
Workflow
git branch -b add_wish_tracker#Tag Scenario or Feature with @wip
cucumber --wip --tags @wipDevelop it Outside-In
git rebase ---interactive; git merge
![Page 77: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/77.jpg)
Workflow
git branch -b add_wish_tracker#Tag Scenario or Feature with @wip
cucumber --wip --tags @wipDevelop it Outside-In
git rebase ---interactive; git mergeRepeat!
![Page 78: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/78.jpg)
@wip on master?
![Page 79: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/79.jpg)
$ rake -T cucumber
@wip on master?
![Page 80: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/80.jpg)
$ rake -T cucumberrake cucumber:ok OR rake cucumber
@wip on master?
![Page 81: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/81.jpg)
$ rake -T cucumberrake cucumber:ok OR rake cucumber
cucumber --tags ~@wip --strict
@wip on master?
![Page 82: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/82.jpg)
$ rake -T cucumberrake cucumber:ok OR rake cucumber
cucumber --tags ~@wip --strict
@wip on master?Tag Exclusion
![Page 83: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/83.jpg)
@wip on master?$ rake -T cucumber
![Page 84: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/84.jpg)
@wip on master?$ rake -T cucumberrake cucumber:wip
![Page 85: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/85.jpg)
cucumber --tags @wip:2 --wip
@wip on master?$ rake -T cucumberrake cucumber:wip
![Page 86: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/86.jpg)
cucumber --tags @wip:2 --wip
@wip on master?$ rake -T cucumberrake cucumber:wip
Limit tags in flow
![Page 87: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/87.jpg)
cucumber --tags @wip:2 --wip
@wip on master?$ rake -T cucumberrake cucumber:wip
Limit tags in flow
Expect failure - Success == Failure
![Page 88: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/88.jpg)
@wip on master?$ rake -T cucumberrake cucumber:all
Runs both ok and wip -- great for CI
![Page 89: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/89.jpg)
features/manage_my_wishes.feature
Feature: manage my wishes
In order to get more stuff As a greedy person I want to manage my wish list for my family members to view
@wip Scenario: add wish Given I am logged in When I make a "New car" wish Then "New car" should appear on my wish list
@proposedScenario: remove wish
@proposedScenario: tweet wish
![Page 90: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/90.jpg)
![Page 91: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/91.jpg)
Line # of scenario
![Page 92: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/92.jpg)
![Page 93: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/93.jpg)
Look Ma! backtraces!Given I am logged in #features/manage_my_wishes.feature:8
![Page 94: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/94.jpg)
![Page 95: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/95.jpg)
![Page 96: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/96.jpg)
features/step_definitions/user_steps.rb
Given /^I am logged in$/ do @current_user = create_user(:email_confirmed => true)
end
![Page 97: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/97.jpg)
features/step_definitions/user_steps.rb
Given /^I am logged in$/ do @current_user = create_user(:email_confirmed => true)
end
Test Data Builder / Object Mother
![Page 98: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/98.jpg)
features/step_definitions/user_steps.rb
Given /^I am logged in$/ do @current_user = create_user(:email_confirmed => true)
end
spec/fixjour_builders.rb
Fixjour do define_builder(User) do |klass, overrides| klass.new( :email => "user#{counter(:user)}@email.com", :password => 'password', :password_confirmation => 'password' ) endend
Fixture Replacement, Fixjour, Factory Girl, etc
![Page 99: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/99.jpg)
features/step_definitions/user_steps.rb
Given /^I am logged in$/ do @current_user = create_user(:email_confirmed => true)
end
![Page 100: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/100.jpg)
features/step_definitions/user_steps.rb
Given /^I am logged in$/ do @current_user = create_user(:email_confirmed => true)
visit new_session_path fill_in "Email", :with => @current_user.email fill_in "Password", :with => valid_user_attributes["password"] click_buttonend
![Page 101: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/101.jpg)
features/step_definitions/user_steps.rb
Given /^I am logged in$/ do @current_user = create_user(:email_confirmed => true)
visit new_session_path fill_in "Email", :with => @current_user.email fill_in "Password", :with => valid_user_attributes["password"] click_buttonend
Webrat / Awesomeness
![Page 102: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/102.jpg)
features/step_definitions/user_steps.rb
Given /^I am logged in$/ do @current_user = create_user(:email_confirmed => true)
visit new_session_path fill_in "Email", :with => @current_user.email fill_in "Password", :with => valid_user_attributes["password"] click_buttonend
Webrat / Awesomeness
![Page 103: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/103.jpg)
features/step_definitions/user_steps.rb
Given /^I am logged in$/ do @current_user = create_user(:email_confirmed => true)
visit new_session_path fill_in "Email", :with => @current_user.email fill_in "Password", :with => valid_user_attributes["password"] click_buttonend
features/support/env.rb
require 'webrat'
Webrat.configure do |config| config.mode = :railsend
Webrat / Awesomeness
![Page 104: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/104.jpg)
features/step_definitions/user_steps.rb
Given /^I am logged in$/ do @current_user = create_user(:email_confirmed => true)
visit new_session_path fill_in "Email", :with => @current_user.email fill_in "Password", :with => valid_user_attributes["password"] click_buttonend
features/support/env.rb
require 'webrat'
Webrat.configure do |config| config.mode = :railsend
Adapter
Webrat / Awesomeness
![Page 105: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/105.jpg)
features/step_definitions/user_steps.rb
Given /^I am logged in$/ do @current_user = create_user(:email_confirmed => true)
visit new_session_path fill_in "Email", :with => @current_user.email fill_in "Password", :with => valid_user_attributes["password"] click_buttonend
features/step_definitions/webrat_steps.rb
When /^I press "(.*)"$/ do |button| click_button(button)end
When /^I follow "(.*)"$/ do |link| click_link(link)end
When /^I fill in "(.*)" with "(.*)"$/ do |field, value| fill_in(field, :with => value) end
When /^I select "(.*)" from "(.*)"$/ do |value, field| select(value, :from => field) end
# Use this step in conjunction with Rail's datetime_select helper. For example:# When I select "December 25, 2008 10:00" as the date and time When /^I select "(.*)" as the date and time$/ do |time| select_datetime(time)end
# Use this step when using multiple datetime_select helpers on a page or # you want to specify which datetime to select. Given the following view:# <%= f.label :preferred %><br /># <%= f.datetime_select :preferred %># <%= f.label :alternative %><br /># <%= f.datetime_select :alternative %># The following steps would fill out the form:# When I select "November 23, 2004 11:20" as the "Preferred" data and time# And I select "November 25, 2004 10:30" as the "Alternative" data and timeWhen /^I select "(.*)" as the "(.*)" date and time$/ do |datetime, datetime_label| select_datetime(datetime, :from => datetime_label)end
# Use this step in conjunction with Rail's time_select helper. For example:# When I select "2:20PM" as the time# Note: Rail's default time helper provides 24-hour time-- not 12 hour time. Webrat# will convert the 2:20PM to 14:20 and then select it. When /^I select "(.*)" as the time$/ do |time| select_time(time)end
# Use this step when using multiple time_select helpers on a page or you want to# specify the name of the time on the form. For example:# When I select "7:30AM" as the "Gym" timeWhen /^I select "(.*)" as the "(.*)" time$/ do |time, time_label| select_time(time, :from => time_label)end
# Use this step in conjunction with Rail's date_select helper. For example:# When I select "February 20, 1981" as the dateWhen /^I select "(.*)" as the date$/ do |date| select_date(date)end
# Use this step when using multiple date_select helpers on one page or# you want to specify the name of the date on the form. For example:# When I select "April 26, 1982" as the "Date of Birth" dateWhen /^I select "(.*)" as the "(.*)" date$/ do |date, date_label| select_date(date, :from => date_label)end
When /^I check "(.*)"$/ do |field| check(field) end
When /^I uncheck "(.*)"$/ do |field| uncheck(field) end
When /^I choose "(.*)"$/ do |field| choose(field)end
When /^I attach the file at "(.*)" to "(.*)" $/ do |path, field| attach_file(field, path)end
Then /^I should see "(.*)"$/ do |text| response.should contain(text)end
Then /^I should not see "(.*)"$/ do |text| response.should_not contain(text)end
Then /^the "(.*)" checkbox should be checked$/ do |label| field_labeled(label).should be_checkedend
Webrat / Awesomeness
20+ Steps Out-of-box
![Page 106: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/106.jpg)
features/step_definitions/user_steps.rb
Given /^I am logged in$/ do @current_user = create_user(:email_confirmed => true)
visit new_session_path fill_in "Email", :with => @current_user.email fill_in "Password", :with => valid_user_attributes["password"] click_buttonend
![Page 107: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/107.jpg)
Given /^I am logged in$/ do @current_user = create_user(:email_confirmed => true)
visit new_session_path fill_in "Email", :with => @current_user.email fill_in "Password", :with => valid_user_attributes["password"] click_button
end
features/step_definitions/user_steps.rb
Given /^I am logged in$/ do
# make sure we have actually logged in- so we fail fast if not session[:user_id].should == @current_user.idend
![Page 108: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/108.jpg)
features/step_definitions/user_steps.rb
Given /^I am logged in$/ do
# make sure we have actually logged in- so we fail fast if not controller.current_user.should == @current_userend
Given /^I am logged in$/ do @current_user = create_user(:email_confirmed => true)
visit new_session_path fill_in "Email", :with => @current_user.email fill_in "Password", :with => valid_user_attributes["password"] click_button session[:user_id].should == @current_user.id
![Page 109: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/109.jpg)
Given /^I am logged in$/ do @current_user = create_user(:email_confirmed => true)
visit new_session_path fill_in "Email", :with => @current_user.email fill_in "Password", :with => valid_user_attributes["password"] click_button
features/step_definitions/user_steps.rb
Given /^I am logged in$/ do
# make sure we have actually logged in- so we fail fast if not session[:user_id].should == @current_user.id controller.current_user.should == @current_user response.should contain("Signed in successfully")end
Specify outcome, not implementation.
![Page 110: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/110.jpg)
features/step_definitions/user_steps.rb
Given /^I am logged in$/ do @current_user = create_user(:email_confirmed => true)
visit new_session_path fill_in "Email", :with => @current_user.email fill_in "Password", :with => valid_user_attributes["password"] click_button # make sure we have actually logged in- so we fail fast if not response.should contain("Signed in successfully")end
![Page 111: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/111.jpg)
![Page 112: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/112.jpg)
No route matches “/sessions/create” with{:method=>:post} (ActionController::RoutingError)
![Page 113: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/113.jpg)
I’m going to cheat...
![Page 114: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/114.jpg)
I’m going to cheat...$ gem install thoughtbot-clearance$ ./script generate clearance$ ./script generate clearance_features
![Page 115: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/115.jpg)
Authlogic?
http://github.com/hectoregm/groundwork
![Page 116: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/116.jpg)
![Page 117: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/117.jpg)
features/step_definitions/wish_steps.rb
When /^I make a "(.+)" wish$/ do |wish| end
Then /^(.+) should appear on my wish list$/ do |wish| end
![Page 118: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/118.jpg)
features/step_definitions/wish_steps.rb
When /^I make a "(.+)" wish$/ do |wish| end
Then /^(.+) should appear on my wish list$/ do |wish| end
Regexp Capture -> Yielded Variable
![Page 119: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/119.jpg)
features/step_definitions/wish_steps.rb
When /^I make a "(.+)" wish$/ do |wish| visit "/wishes" click_link "Make a wish" fill_in "Wish", :with => wish click_buttonend
Then /^(.+) should appear on my wish list$/ do |wish| end
![Page 120: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/120.jpg)
features/step_definitions/wish_steps.rb
Then /^(.+) should appear on my wish list$/ do |wish| response.should contain("Your wish has been added!") response.should contain(wish)end
When /^I make a "(.+)" wish$/ do |wish| visit "/wishes" click_link "Make a wish" fill_in "Wish", :with => wish click_buttonend
![Page 121: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/121.jpg)
features/step_definitions/wish_steps.rb
When /^I make a "(.+)" wish$/ do |wish| visit "/wishes" click_link "Make a wish" fill_in "Wish", :with => wish click_buttonend
Then /^(.+) should appear on my wish list$/ do |wish| response.should contain("Your wish has been added!") response.should contain(wish)end
No route matches “/wishes” with{:method=>:get} (ActionController::RoutingError)
![Page 122: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/122.jpg)
config/routes.rb
ActionController::Routing::Routes.draw do |map| map.resources :wishes
![Page 123: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/123.jpg)
config/routes.rb
ActionController::Routing::Routes.draw do |map| map.resources :wishes
When I make a “New car” wishuninitialized constant WishesController (NameError)
![Page 124: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/124.jpg)
config/routes.rb
ActionController::Routing::Routes.draw do |map| map.resources :wishes
$./script generate rspec_controller new create
![Page 125: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/125.jpg)
config/routes.rb
ActionController::Routing::Routes.draw do |map| map.resources :wishes
When I make a “New car” wishCould not find link with text or title orid “Make a wish” (Webrat::NotFoundError)
![Page 126: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/126.jpg)
app/views/wishes/index.html.erb
<%= link_to "Make a wish", new_wish_path %>
![Page 127: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/127.jpg)
app/views/wishes/index.html.erb
<%= link_to "Make a wish", new_wish_path %>
When I make a “New car” wish Could not find field: “Wish” (Webrat::NotFoundError)
![Page 128: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/128.jpg)
features/step_definitions/wish_steps.rb
When /^I make a "(.+)" wish$/ do |wish| visit "/wishes" click_link "Make a wish" fill_in "Wish", :with => wish click_buttonend
![Page 129: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/129.jpg)
features/step_definitions/wish_steps.rb
When /^I make a "(.+)" wish$/ do |wish| visit "/wishes" click_link "Make a wish" fill_in "Wish", :with => wish click_buttonend
app/views/wishes/new.html.erb
<% form_for :wish do |f| %> <%= f.label :name, "Wish" %> <%= f.text_field :name %> <%= submit_tag "Make the wish!" %><% end %>
![Page 130: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/130.jpg)
fill_in "Wish", :with => wish
<%= f.label :name, "Wish" %> <%= f.text_field :name %>
features/step_definitions/wish_steps.rb
When /^I make a "(.+)" wish$/ do |wish| visit "/wishes" click_link "Make a wish" fill_in "Wish", :with => wish click_buttonend
app/views/wishes/new.html.erb
<% form_for :wish do |f| %> <%= submit_tag "Make the wish!" %><% end %>
Location Strategy FTW!
![Page 131: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/131.jpg)
View
Controller
![Page 132: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/132.jpg)
spec/controllers/wishes_controller_spec.rb
describe WishesController do describe "POST / (#create)" do
endend
![Page 133: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/133.jpg)
spec/controllers/wishes_controller_spec.rb
describe WishesController do describe "POST / (#create)" do it "creates a new wish for the user with the params" do user = mock_model(User, :wishes => mock("wishes association")) controller.stub!(:current_user).and_return(user) user.wishes.should_receive(:create).with(wish_params)
post :create, 'wish' => {'name' => 'Dog'} end endend
![Page 134: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/134.jpg)
app/controllers/wishes_controller.rb
class WishesController < ApplicationController
def create current_user.wishes.create(params['wish']) end
end
![Page 135: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/135.jpg)
spec/controllers/wishes_controller_spec.rb
describe WishesController do describe "POST / (#create)" do before(:each) do .....
endend
spec/controllers/wishes_controller_spec.rb
it "redirects the user to their wish list" do do_post response.should redirect_to(wishes_path) end
![Page 136: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/136.jpg)
app/controllers/wishes_controller.rb
def create current_user.wishes.create(params['wish']) redirect_to :action => :index end
![Page 137: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/137.jpg)
View
Controller
Model
![Page 138: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/138.jpg)
app/controllers/wishes_controller.rb
def create current_user.wishes.create(params['wish']) redirect_to :action => :index end
When I make a “New car” wishundefined method `wishes` for #<User:0x268e898> (NoMethodError)
![Page 139: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/139.jpg)
app/controllers/wishes_controller.rb
def create current_user.wishes.create(params['wish']) redirect_to :action => :index end
$./script generate rspec_model wish name:string user_id:integer
![Page 140: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/140.jpg)
app/models/wish.rb
class Wish < ActiveRecord::Base belongs_to :userend
app/models/user.rb
class User < ActiveRecord::Base include Clearance::App::Models::User has_many :wishesend
![Page 141: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/141.jpg)
app/models/wish.rb
class Wish < ActiveRecord::Base belongs_to :userend
app/models/user.rb
class User < ActiveRecord::Base include Clearance::App::Models::User has_many :wishesend
When I make a “New car” wishThen “New car” should appear on my wishexpected the following element’s content to include “Your wish has been added!”
![Page 142: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/142.jpg)
spec/controllers/wishes_controller_spec.rb
it "notifies the user of creation via the flash" do do_post flash[:success].should == "Your wish has been added!"end
![Page 143: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/143.jpg)
current_user.wishes.create(params['wish']) redirect_to :action => :index
app/controllers/wishes_controller.rb
def create flash[:success] = "Your wish has been added!" end
spec/controllers/wishes_controller_spec.rb
it "notifies the user of creation via the flash" do do_post flash[:success].should == "Your wish has been added!"end
![Page 144: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/144.jpg)
current_user.wishes.create(params['wish']) redirect_to :action => :index
app/controllers/wishes_controller.rb
def create flash[:success] = "Your wish has been added!" end
spec/controllers/wishes_controller_spec.rb
it "should notifies the user of creation via the flash" do do_post flash[:success].should == "Your wish has been added!"end
Then “New car” should appear on my wishexpected the following element’s content to include “New car”
![Page 145: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/145.jpg)
app/views/wishes/index.html.erb
<ul><% @wishes.each do |wish| %> <li><%= wish.name %></li><% end %></ul>
![Page 146: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/146.jpg)
spec/controllers/wishes_controller_spec.rb
describe "GET / (#index)" do def do_get get :index end
it "assigns the user's wishes to the view" do do_get assigns[:wishes].should == @current_user.wishes end
end
![Page 147: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/147.jpg)
app/controllers/wishes_controller.rb
def index @wishes = current_user.wishes end
![Page 148: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/148.jpg)
![Page 149: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/149.jpg)
FAQ
How do I test JS and
AJAX?
![Page 150: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/150.jpg)
![Page 151: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/151.jpg)
Slow
Fast
![Page 152: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/152.jpg)
Slow
Fast
Integrated
Isolated
![Page 153: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/153.jpg)
Slow
Fast
Integrated
Isolated
![Page 154: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/154.jpg)
Slow
Fast
Integrated
Isolated
![Page 155: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/155.jpg)
Slow
Fast
Integrated
Isolated
![Page 156: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/156.jpg)
Slow
Fast
Integrated
Isolated
![Page 157: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/157.jpg)
Slow
Fast
![Page 158: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/158.jpg)
Slow
Fast Joyful
![Page 159: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/159.jpg)
Slow
Fast
Painful
Joyful
![Page 160: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/160.jpg)
Slow
Fast
Painful
Joyful
Celerity
![Page 161: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/161.jpg)
Celerity
![Page 162: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/162.jpg)
CelerityHtmlUnit
![Page 163: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/163.jpg)
CelerityHtmlUnit
![Page 164: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/164.jpg)
CelerityHtmlUnit
![Page 165: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/165.jpg)
CelerityHtmlUnit
![Page 166: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/166.jpg)
require "rubygems"require "celerity"
browser = Celerity::Browser.new
browser.goto('http://www.google.com')browser.text_field(:name, 'q').value = 'Celerity'browser.button(:name, 'btnG').click
puts "yay" if browser.text.include? 'celerity.rubyforge.org'
![Page 167: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/167.jpg)
What if I use MRI?
![Page 168: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/168.jpg)
Culerity
http://github.com/langalex/culerity
![Page 169: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/169.jpg)
require "rubygems"require "culerity"
culerity_server = Culerity::run_server
browser = Culerity::RemoteBrowserProxy.new(culerity_server)browser.goto('http://www.google.com')browser.text_field(:name, 'q').value = 'Celerity'browser.button(:name, 'btnG').click
puts "yay" if browser.text.include? 'celerity.rubyforge.org'
![Page 170: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/170.jpg)
Celerity +http://github.com/dstrelau/webrat
![Page 171: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/171.jpg)
+HtmlUnit
http://github.com/johnnyt/webrat
![Page 172: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/172.jpg)
CodeNote
http://github.com/bmabey/codenote
![Page 173: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/173.jpg)
Feature: CLI Server In order to save me time and headaches As a presenter of code I create a presentation in plaintext a'la Slidedown (from Pat Nakajima) and have CodeNote serve it up for me
Scenario: basic presentation loading and viewing Given that the codenote server is not running And a file named "presentation.md" with: """ !TITLE My Presentation !PRESENTER Ben Mabey # This is the title slide !SLIDE # This is second slide... """ When I run "codenote_load presentation.md" And I run "codenote" And I visit the servers address
For example of how to test CLI tools take a look at CodeNote on github.
RSpec and Cucumber also have good examples of how to do this.
![Page 174: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/174.jpg)
Feature: Twitter Quiz In order to encourage audience participation where 90% of the audience is hacking on laptops As a presenter I want audience members To answer certain questions via twitter
![Page 175: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/175.jpg)
Feature: Twitter Quiz In order to encourage audience participation where 90% of the audience is hacking on laptops As a presenter I want audience members To answer certain questions via twitter
@proposed Scenario: waiting for an answer
@proposed Scenario: winner is displayed
@proposed Scenario: fail whale
@proposed Scenario: network timeout
![Page 176: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/176.jpg)
Feature: Twitter Quiz In order to encourage audience participation where 90% of the audience is hacking on laptops As a presenter I want audience members To answer certain questions via twitter
@wip Scenario: waiting for an answer
![Page 177: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/177.jpg)
@wipScenario: waiting for an answer Given the following presentation """ !TITLE American History !PRESENTER David McCullough # Wanna win a prize? ### You'll have to answer a question... ### in a tweet! First correct tweet wins! !SLIDE # Who shot Alexander Hamilton? ## You must use #free_stuff in your tweet. !DYNAMIC-SLIDE TwitterQuiz '#free_stuff "aaron burr"' !SLIDE Okay, that was fun. Lets actually start now. """
![Page 178: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/178.jpg)
!DYNAMIC-SLIDE TwitterQuiz '#free_stuff "aaron burr"'
@wipScenario: waiting for an answer Given the following presentation """ !TITLE American History !PRESENTER David McCullough # Wanna win a prize? ### You'll have to answer a question... ### in a tweet! First correct tweet wins! !SLIDE # Who shot Alexander Hamilton? ## You must use #free_stuff in your tweet. !SLIDE Okay, that was fun. Lets actually start now. """
![Page 179: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/179.jpg)
@wipScenario: waiting for an answer Given the following presentation ... And no tweets have been tweeted that match the '#free_stuff "aaron burr"' search When the presenter goes to the 3rd slide And I go to the 3rd slide Then I should see "And the winner is..." And I should see an ajax spinner
![Page 180: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/180.jpg)
Given /the following presentation$/ do |presentation| end
Given the following presentation """ blah, blah """
![Page 181: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/181.jpg)
Given /the following presentation$/ do |presentation| end
Given the following presentation """ blah, blah """
Yields the multi-line string
![Page 182: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/182.jpg)
CodeNote::PresentationLoader.setup(presentation)
Given /the following presentation$/ do |presentation| end
Given the following presentation """ blah, blah """
![Page 183: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/183.jpg)
RSpec Cycle
![Page 184: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/184.jpg)
And no tweets have been tweeted that match the '#free_stuff "aaron burr"' search
![Page 185: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/185.jpg)
FAQ
How do I test webservices?
![Page 186: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/186.jpg)
http://github.com/chrisk/fakeweb
![Page 187: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/187.jpg)
http://github.com/chrisk/fakeweb
page = `curl -is http://www.google.com/`FakeWeb.register_uri(:get, "http://www.google.com/",
:response => page)
Net::HTTP.get(URI.parse("http://www.google.com/")) # => Full response, including headers
![Page 188: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/188.jpg)
Given %r{no tweets have been tweeted that match the '([']*)' search$} do |query| end
And no tweets have been tweeted that match the '#free_stuff "aaron burr"' search
![Page 189: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/189.jpg)
Given %r{no tweets have been tweeted that match the '([']*)' search$} do |query| FakeWeb.register_uri(:get, search_url_for(query), :body => canned_response_for(query))end
And no tweets have been tweeted that match the '#free_stuff "aaron burr"' search
![Page 190: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/190.jpg)
Given %r{no tweets have been tweeted that match the '([']*)' search$} do |query| FakeWeb.register_uri(:get, search_url_for(query), :body => canned_response_for(query))end
![Page 191: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/191.jpg)
Given %r{no tweets have been tweeted that match the '([']*)' search$} do |query| FakeWeb.register_uri(:get, search_url_for(query), :body => canned_response_for(query))end
Helpers
![Page 192: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/192.jpg)
Given %r{no tweets have been tweeted that match the '([']*)' search$} do |query| FakeWeb.register_uri(:get, search_url_for(query), :body => canned_response_for(query))end
def search_url_for(query) "http://search.twitter.com/search.json?q=#{CGI.escape(query)}" end
def canned_response_for(query) .... return file_path end
Helpers
![Page 193: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/193.jpg)
Given %r{no tweets have been tweeted that match the '([']*)' search$} do |query| FakeWeb.register_uri(:get, search_url_for(query), :body => canned_response_for(query))end
def search_url_for(query) "http://search.twitter.com/search.json?q=#{CGI.escape(query)}" end
def canned_response_for(query) .... return file_path end
![Page 194: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/194.jpg)
Given %r{no tweets have been tweeted that match the '([']*)' search$} do |query| FakeWeb.register_uri(:get, search_url_for(query), :body => canned_response_for(query))end
def search_url_for(query) "http://search.twitter.com/search.json?q=#{CGI.escape(query)}" end
def canned_response_for(query) .... return file_path end
![Page 195: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/195.jpg)
Given %r{no tweets have been tweeted that match the '([']*)' search$} do |query| FakeWeb.register_uri(:get, search_url_for(query), :body => canned_response_for(query))end
def search_url_for(query) "http://search.twitter.com/search.json?q=#{CGI.escape(query)}" end
def canned_response_for(query) .... return file_path end
“Every time you monkeypatch Object, a kitten dies.”
![Page 196: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/196.jpg)
Given %r{no tweets have been tweeted that match the '([']*)' search$} do |query| FakeWeb.register_uri(:get, search_url_for(query), :body => canned_response_for(query))end
module TwitterHelpers def search_url_for(query) "http://search.twitter.com/search.json?q=#{CGI.escape(query)}" end
def canned_response_for(query) .... return file_path end
end
![Page 197: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/197.jpg)
Given %r{no tweets have been tweeted that match the '([']*)' search$} do |query| FakeWeb.register_uri(:get, search_url_for(query), :body => canned_response_for(query))end
module TwitterHelpers def search_url_for(query) "http://search.twitter.com/search.json?q=#{CGI.escape(query)}" end
def canned_response_for(query) .... return file_path end
end
World(TwitterHelpers)
![Page 198: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/198.jpg)
Given %r{no tweets have been tweeted that match the '([']*)' search$} do |query| FakeWeb.register_uri(:get, search_url_for(query), :body => canned_response_for(query))end
module TwitterHelpers def search_url_for(query) "http://search.twitter.com/search.json?q=#{CGI.escape(query)}" end
def canned_response_for(query) .... return file_path end
end
World(TwitterHelpers)
![Page 199: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/199.jpg)
When the presenter goes to the 3rd slide
![Page 200: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/200.jpg)
When the presenter goes to the 3rd slide
When /the presenter goes to the (\d+)(?:st|nd|rd|th) slide$/ do |slide_number|
presenter_browser.goto path('/') (slide_number.to_i - 1).times do presenter_browser.link(:text, "Next").click endend
![Page 201: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/201.jpg)
When the presenter goes to the 3rd slide
When /the presenter goes to the (\d+)(?:st|nd|rd|th) slide$/ do |slide_number|
presenter_browser.goto path('/') (slide_number.to_i - 1).times do presenter_browser.link(:text, "Next").click endend
Presenter has own browser,multiple sessions!
![Page 202: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/202.jpg)
And I go to the 3rd slide Then I should see "And the winner is..."
![Page 203: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/203.jpg)
And I go to the 3rd slide Then I should see "And the winner is..."
When /I go to the (\d+)(?:st|nd|rd|th) slide$/ do |slide_number| browser.goto path("/slides/#{slide_number}")end
![Page 204: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/204.jpg)
And I go to the 3rd slide Then I should see "And the winner is..."
When /I go to the (\d+)(?:st|nd|rd|th) slide$/ do |slide_number| browser.goto path("/slides/#{slide_number}")end
Then /I should see "(["]*)"$/ do |text| browser.should contain(text)end
![Page 205: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/205.jpg)
And I should see an ajax spinner
![Page 206: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/206.jpg)
And I should see an ajax spinner
Then /I should see an ajax spinner$/ do browser.image(:id, 'spinner').exists?.should be_trueend
![Page 207: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/207.jpg)
Brief RSpec cycle?
![Page 208: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/208.jpg)
Scenario: waiting for an answer Given the following presentation ... And no tweets have been tweeted that match the '#free_stuff "aaron burr"' search When the presenter goes to the 3rd slide And I go to the 3rd slide Then I should see "And the winner is..." And I should see an ajax spinner
![Page 209: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/209.jpg)
Feature: Twitter Quiz In order to encourage audience participation where 90% of the audience is hacking on laptops As a presenter I want audience members To answer certain questions via twitter
Scenario: waiting for an answer ..... @wip Scenario: winner is displayed
![Page 210: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/210.jpg)
@wipScenario: winner is displayed Given the following presentation ... And no tweets have been tweeted that match the '#free_stuff "aaron burr"' search
![Page 211: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/211.jpg)
@wipScenario: winner is displayed Given the following presentation ... And no tweets have been tweeted that match the '#free_stuff "aaron burr"' search
Duplication of context!
![Page 212: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/212.jpg)
Feature: Twitter Quiz ... Background: A presentation with a Twitter Quiz
Given the following presentation """ blah, blah """ And no tweets have been tweeted that match the '#free_stuff "aaron burr"' search
Scenario: waiting for an answer When the presenter goes to the 3rd slide And I go to the 3rd slide Then I should see "And the winner is..." And I should see an ajax spinner
@wip Scenario: winner is displayed
Extract to ‘Background’
![Page 213: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/213.jpg)
@wipScenario: winner is displayed When the following tweets are tweeted that match the '#free_stuff "aaron burr"' search | From User | Text | Created At | | @adams | Aaron Burr shot Alexander Hamilton #free_stuff | 1 minute ago | | @jefferson | Aaron Burr shot Alexander Hamilton #free_stuff | 2 minutes ago | And the presenter goes to the 3rd slide And I go to the 3rd slide
Then I should see @jefferson's tweet along with his avatar
![Page 214: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/214.jpg)
When the following tweets are tweeted that match the '#free_stuff "aaron burr"' search
| From User | Text | Created At | | @adams | Aaron Burr shot Alexander Hamilton #free_stuff | 1 minute ago | | @jefferson | Aaron Burr shot Alexander Hamilton #free_stuff | 2 minutes ago |
![Page 215: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/215.jpg)
When %r{the following tweets are tweeted that match the '([']*)' search$} do |query, tweet_table|
end
When the following tweets are tweeted that match the '#free_stuff "aaron burr"' search
| From User | Text | Created At | | @adams | Aaron Burr shot Alexander Hamilton #free_stuff | 1 minute ago | | @jefferson | Aaron Burr shot Alexander Hamilton #free_stuff | 2 minutes ago |
![Page 216: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/216.jpg)
When %r{the following tweets are tweeted that match the '([']*)' search$} do |query, tweet_table|
end
When the following tweets are tweeted that match the '#free_stuff "aaron burr"' search
Cucumber::AST::Table
| From User | Text | Created At | | @adams | Aaron Burr shot Alexander Hamilton #free_stuff | 1 minute ago | | @jefferson | Aaron Burr shot Alexander Hamilton #free_stuff | 2 minutes ago |
![Page 217: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/217.jpg)
When %r{the following tweets are tweeted that match the '([']*)' search$} do |query, tweet_table| FakeWeb.register_uri(:get, search_url_for(query), :body => canned_response_for(query))
end
When the following tweets are tweeted that match the '#free_stuff "aaron burr"' search
| From User | Text | Created At | | @adams | Aaron Burr shot Alexander Hamilton #free_stuff | 1 minute ago | | @jefferson | Aaron Burr shot Alexander Hamilton #free_stuff | 2 minutes ago |
![Page 218: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/218.jpg)
When %r{the following tweets are tweeted that match the '([']*)' search$} do |query, tweet_table| FakeWeb.register_uri(:get, search_url_for(query), :body => canned_response_for(query))
end
Umm... that won’t work.
When the following tweets are tweeted that match the '#free_stuff "aaron burr"' search
| From User | Text | Created At | | @adams | Aaron Burr shot Alexander Hamilton #free_stuff | 1 minute ago | | @jefferson | Aaron Burr shot Alexander Hamilton #free_stuff | 2 minutes ago |
![Page 219: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/219.jpg)
When %r{the following tweets are tweeted that match the '([']*)' search$} do |query, tweet_table| FakeWeb.register_uri(:get, search_url_for(query), :body => canned_response_for(query))
end
What I would really like is atest data builder/factory for
twitter searches...
When the following tweets are tweeted that match the '#free_stuff "aaron burr"' search
| From User | Text | Created At | | @adams | Aaron Burr shot Alexander Hamilton #free_stuff | 1 minute ago | | @jefferson | Aaron Burr shot Alexander Hamilton #free_stuff | 2 minutes ago |
![Page 220: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/220.jpg)
http://github.com/bmabey/faketwitterrequire 'faketwitter'
FakeTwitter.register_search("#cheese", {:results => [{:text => "#cheese is good"}]})
require 'twitter_search'TwitterSearch::Client.new('').query('#cheese')=> [#<TwitterSearch::Tweet:0x196cef8 @id=1, @text="#cheese is good", @created_at="Fri, 21 Aug 2009 09:31:27 +0000", @to_user_id=nil, @from_user_id=1, @to_user=nil, @source="<a href="http://twitter.com/">web</a>", @iso_language_code="en", @from_user="jojo", @language="en", @profile_image_url="http://s3.amazonaws.com/twitter_production/profile_images/1/photo.jpg">]
![Page 221: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/221.jpg)
When %r{the following tweets are tweeted that match the '([']*)' search$} do |query, tweet_table| FakeTwitter.register_search(query, { :results => tweet_table.hashes})
end
When the following tweets are tweeted that match the '#free_stuff "aaron burr"' search
| From User | Text | Created At | | @adams | Aaron Burr shot Alexander Hamilton #free_stuff | 1 minute ago | | @jefferson | Aaron Burr shot Alexander Hamilton #free_stuff | 2 minutes ago |
![Page 222: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/222.jpg)
When %r{the following tweets are tweeted that match the '([']*)' search$} do |query, tweet_table| FakeTwitter.register_search(query, { :results => tweet_table.hashes})
end
When the following tweets are tweeted that match the '#free_stuff "aaron burr"' search
| From User | Text | Created At | | @adams | Aaron Burr shot Alexander Hamilton #free_stuff | 1 minute ago | | @jefferson | Aaron Burr shot Alexander Hamilton #free_stuff | 2 minutes ago |
Our headers and columnsaren’t compatible with API.
![Page 223: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/223.jpg)
When %r{the following tweets are tweeted that match the '([']*)' search$} do |query, tweet_table| tweet_table.map_headers! do |header| header.downcase.gsub(' ','_') end
FakeTwitter.register_search(query, {:results => tweet_table.hashes})
end
When the following tweets are tweeted that match the '#free_stuff "aaron burr"' search
| From User | Text | Created At | | @adams | Aaron Burr shot Alexander Hamilton #free_stuff | 1 minute ago | | @jefferson | Aaron Burr shot Alexander Hamilton #free_stuff | 2 minutes ago |
![Page 224: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/224.jpg)
When %r{the following tweets are tweeted that match the '([']*)' search$} do |query, tweet_table| tweet_table.map_headers! do |header| header.downcase.gsub(' ','_') end
tweet_table.map_column!('created_at') do |relative_time| interpret_time(relative_time) end
FakeTwitter.register_search(query, {:results => tweet_table.hashes})
end
When the following tweets are tweeted that match the '#free_stuff "aaron burr"' search
| From User | Text | Created At | | @adams | Aaron Burr shot Alexander Hamilton #free_stuff | 1 minute ago | | @jefferson | Aaron Burr shot Alexander Hamilton #free_stuff | 2 minutes ago |
![Page 225: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/225.jpg)
@wipScenario: winner is displayed When the following tweets are tweeted that match the '#free_stuff "aaron burr"' search | From User | Text | Created At | | @adams | Aaron Burr shot Alexander Hamilton #free_stuff | 1 minute ago | | @jefferson | Aaron Burr shot Alexander Hamilton #free_stuff | 2 minutes ago | And the presenter goes to the 3rd slide And I go to the 3rd slide Then I should see @jefferson's tweet along with his avatar
![Page 226: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/226.jpg)
Then %r{I should see @([']+)'s tweet along with (?:his|her) avatar$} do |user|
tweet = FakeTwitter.tweets_from(user).first browser.should contain(tweet['text'], :wait => 10) browser.should have_image(:src, tweet['profile_image_url'])end
Timeout
![Page 227: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/227.jpg)
Then %r{I should see @([']+)'s tweet along with (?:his|her) avatar$} do |user|
tweet = FakeTwitter.tweets_from(user).first browser.should contain(tweet['text'], :wait => 10) browser.should have_image(:src, tweet['profile_image_url'])end
Spec::Matchers.define :contain do |text, options| match do |browser| options[:wait] ||= 0 browser.wait_until(options[:wait]) do browser.text.include?(text) end endend
![Page 228: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/228.jpg)
Then %r{I should see @([']+)'s tweet along with (?:his|her) avatar$} do |user|
tweet = FakeTwitter.tweets_from(user).first browser.should contain(tweet['text'], :wait => 10) browser.should have_image(:src, tweet['profile_image_url'])end
Spec::Matchers.define :contain do |text, options| match do |browser| options[:wait] ||= 0 browser.wait_until(options[:wait]) do browser.text.include?(text) end endend
Keep trying after sleepinguntil it times out
![Page 229: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/229.jpg)
RSpec Cycle
![Page 230: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/230.jpg)
Scenario: winner is displayed When the following tweets are tweeted that match the '#free_stuff "aaron burr"' search | From User | Text | Created At | | @adams | Aaron Burr shot Alexander Hamilton #free_stuff | 1 minute ago | | @jefferson | Aaron Burr shot Alexander Hamilton #free_stuff | 2 minutes ago | And the presenter goes to the 3rd slide And I go to the 3rd slide
Then I should see @jefferson's tweet along with his avatar
![Page 231: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/231.jpg)
Demo!
![Page 232: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/232.jpg)
More tricks...
![Page 233: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/233.jpg)
![Page 234: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/234.jpg)
Scenario: view members list Given the following wishes exist | Wish | Family Member | | Laptop | Thomas | | Nintendo Wii | Candace | | CHEEZBURGER | FuzzBuzz | When I view the wish list for "Candace"
Then I should see the following wishes | Wish | | Nintendo Wii |
![Page 235: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/235.jpg)
Given the following wishes exist | Wish | Family Member | | Laptop | Thomas | | Nintendo Wii | Candace | | CHEEZBURGER | FuzzBuzz |
features/step_definitions/wish_steps.rb
Given /^the following wishes exist$/ do |table|
endend
![Page 236: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/236.jpg)
| Wish | Family Member | features/step_definitions/wish_steps.rb
Given /^the following wishes exist$/ do |table| table.hashes.each do |row| member = User.find_by_name(row["Family Member"]) || create_user(:name => row["Family Member"])
member.wishes.create!(:name => row["Wish"]) endend
Given the following wishes exist | Wish | Family Member | | Laptop | Thomas | | Nintendo Wii | Candace | | CHEEZBURGER | FuzzBuzz |
![Page 237: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/237.jpg)
Table Diffinghttp://wiki.github.com/aslakhellesoy/cucumber/multiline-step-arguments
![Page 238: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/238.jpg)
Feature: Addition In order to avoid silly mistakes As a math idiot I want to be told the sum of two numbers
Scenario Outline: Add two numbers Given I have entered <input_1> into the calculator And I have entered <input_2> into the calculator When I press <button> Then the result should be <output> on the screen
Scenarios: | input_1 | input_2 | button | output | | 20 | 30 | add | 50 | | 2 | 5 | add | 7 | | 0 | 40 | add | 40 |
<input_1> <input_2> <button> <output>
| input_1 | input_2 | button | output |
![Page 239: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/239.jpg)
Feature: Addition In order to avoid silly mistakes As a math idiot I want to be told the sum of two numbers
Scenario Outline: Add two numbers Given I have entered <input_1> into the calculator And I have entered <input_2> into the calculator When I press <button> Then the result should be <output> on the screen
Scenarios: addition | input_1 | input_2 | button | output | | 20 | 30 | add | 50 | | 2 | 5 | add | 7 | Scenarios: subtraction | 0 | 40 | minus | -40 |
![Page 240: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/240.jpg)
Feature: Addition In order to avoid silly mistakes As a math idiot I want to be told the sum of two numbers
Scenario Outline: Add two numbers Given I have entered <input_1> into the calculator And I have entered <input_2> into the calculator When I press <button> Then the result should be <output> on the screen
Scenarios: | input_1 | input_2 | button | output | | 20 | 30 | add | 50 | | 2 | 5 | add | 7 | | 0 | 40 | add | 40 |
<input_1> <input_2> <button> <output>
| 20 | 30 | add | 50 |
![Page 241: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/241.jpg)
<input_1> <input_2> <button> <output>
| 2 | 5 | add | 7 |
Feature: Addition In order to avoid silly mistakes As a math idiot I want to be told the sum of two numbers
Scenario Outline: Add two numbers Given I have entered <input_1> into the calculator And I have entered <input_2> into the calculator When I press <button> Then the result should be <output> on the screen
Scenarios: | input_1 | input_2 | button | output | | 20 | 30 | add | 50 | | 2 | 5 | add | 7 | | 0 | 40 | add | 40 |
![Page 242: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/242.jpg)
<input_1> <input_2> <button> <output>
| 0 | 40 | add | 40 |
Feature: Addition In order to avoid silly mistakes As a math idiot I want to be told the sum of two numbers
Scenario Outline: Add two numbers Given I have entered <input_1> into the calculator And I have entered <input_2> into the calculator When I press <button> Then the result should be <output> on the screen
Scenarios: | input_1 | input_2 | button | output | | 20 | 30 | add | 50 | | 2 | 5 | add | 7 | | 0 | 40 | add | 40 |
![Page 243: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/243.jpg)
When /^I view the wish list for "(.+)"$/ do |user_name| Given "I am logged in" visit "/wishes/#{user_name}"end
Steps Within Steps
![Page 244: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/244.jpg)
When /^I view the wish list for "(.+)"$/ do |user_name| visit "/wishes/#{user_name}"end
Steps Within Steps Given "I am logged in"
![Page 245: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/245.jpg)
HooksBefore doend
After do |scenario|end
World doend
World(MyModule)World(HerModule)
![Page 246: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/246.jpg)
Tagged HooksBefore('@im_special', '@me_too') do @icecream = trueend
@me_tooFeature: Lorem Scenario: Ipsum Scenario: Dolor
Feature: Sit @im_special Scenario: Amet Scenario: Consec
![Page 247: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/247.jpg)
Spork
http://github.com/timcharper/spork
Sick of slow loading times? Spork will load your main environment once. It then runs a DRB server so cucumber (or RSpec) can run against it with the --drb flag. For each test run Spork forks a child process to run them in a clean memory state. So.. it is a DRb server that forks.. hence Spork. :)
![Page 248: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/248.jpg)
Drinking the Cucumber Kool-Aid?
![Page 249: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/249.jpg)
Integration tests are a scam
http://www.jbrains.ca/permalink/239
J. B. Rainsberger
Obviously, I don’t agree with this 100%. But he has some valid points. Integrations tests are not a replacement for good unit tests. Use cucumber for happy paths. Use lower level tests for design and to isolate object behavior.
![Page 250: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/250.jpg)
Cucumber is a good hammer
![Page 251: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/251.jpg)
Cucumber is a good hammer
Not everything is a nail
![Page 252: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/252.jpg)
I can skp teh unit testz?
![Page 253: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/253.jpg)
Acceptance Tests
Application LevelFor CustomersSlowGood confidencePrevent against regression
Unit Tests
Object Level- Isolated!For developersFAST! (should be at least)- Tighter Feedback LoopMore about design!!!!!!!!!!!!
Will need both gears! Some things are easier to test at the application level and vice-versa.
![Page 254: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/254.jpg)
SRSLY?Model specs,Controller Specs,and view specs!?
![Page 255: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/255.jpg)
![Page 256: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/256.jpg)
![Page 257: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/257.jpg)
![Page 258: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/258.jpg)
W
![Page 259: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/259.jpg)
M
![Page 260: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/260.jpg)
More tests == More Maintenance
![Page 261: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/261.jpg)
Test Value =Design +
Documentation +Defence (regression)
![Page 262: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/262.jpg)
if test.value > test.cost Suite.add(test)end
![Page 263: Writing Software not Code with Cucumber](https://reader035.vdocuments.net/reader035/viewer/2022081400/54bd180c4a7959766e8b457b/html5/thumbnails/263.jpg)
KTHXBYE!BenMabey.com
github.com/bmabey
Twitter: bmabeyIRC: mabes