Top Banner
With Ben Mabey Outside-In Development Saturday, March 14, 2009
137

Outside In Development With Cucumber

Dec 18, 2014

Download

Documents

LittleBIGRuby

 
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: Outside In Development With Cucumber

With

Ben Mabey

Outside-In Development

Saturday, March 14, 2009

Page 2: Outside In Development With Cucumber

Who’s myaudience?

Saturday, March 14, 2009

Page 3: Outside In Development With Cucumber

Saturday, March 14, 2009

Page 4: Outside In Development With Cucumber

Scenario: planning meetingGiven I am a Software DeveloperWhen I am given a feature requestThen I should...

Saturday, March 14, 2009

Page 5: Outside In Development With Cucumber

What is the mostCRITICAL

word to keep in mind?

Saturday, March 14, 2009

Page 6: Outside In Development With Cucumber

WSaturday, March 14, 2009

Page 7: Outside In Development With Cucumber

Scenario: planning meetingGiven I am a Software DeveloperWhen I am given a feature requestThen I should ask why.

Saturday, March 14, 2009

Page 8: Outside In Development With Cucumber

_why

Saturday, March 14, 2009

Page 9: Outside In Development With Cucumber

Why?Saturday, March 14, 2009

Page 11: Outside In Development With Cucumber

Saturday, March 14, 2009

Page 12: Outside In Development With Cucumber

Protect Revenue

Increase Revenue

Manage Cost

Saturday, March 14, 2009

Page 13: Outside In Development With Cucumber

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

Saturday, March 14, 2009

Page 14: Outside In Development With Cucumber

There is no template.What is important to have in narrative:

* business value * stakeholder role * user role * action to be taken by user

Saturday, March 14, 2009

Page 15: Outside In Development With Cucumber

Scenario: titleGiven [Context]When I do [Action]Then I should see [Outcome]

Saturday, March 14, 2009

Page 16: Outside In Development With Cucumber

Scenario: titleGiven [Context]And [More Context]When I do [Action]And [Other Action]Then I should see [Outcome]But I should not see [Outcome]

Saturday, March 14, 2009

Page 17: Outside In Development With Cucumber

project_root/| `-- features

Saturday, March 14, 2009

Page 18: Outside In Development With Cucumber

project_root/| `-- features |-- awesomeness.feature |-- greatest_ever.feature

Saturday, March 14, 2009

Page 19: Outside In Development With Cucumber

project_root/| `-- features |-- awesomeness.feature |-- greatest_ever.feature `-- support |-- env.rb `-- other_helpers.rb

Saturday, March 14, 2009

Page 20: Outside In Development With Cucumber

project_root/| `-- features |-- awesomeness.feature |-- greatest_ever.feature `-- support |-- env.rb `-- other_helpers.rb |-- step_definitions | |-- domain_concept_A.rb | `-- domain_concept_B.rb

Saturday, March 14, 2009

Page 21: Outside In Development With Cucumber

Step

Given a widget

Saturday, March 14, 2009

Page 22: Outside In Development With Cucumber

Step

Given a widgetGiven /^a widget$/ do #codes go hereend

Definition

Saturday, March 14, 2009

Page 23: Outside In Development With Cucumber

Step

Given a widgetGiven /^a widget$/ do #codes go hereend

Definition

Step Mother

Saturday, March 14, 2009

Page 24: Outside In Development With Cucumber

Step

Given a widgetGiven /^a widget$/ do #codes go hereend

Definition

Step Mother

Saturday, March 14, 2009

Page 25: Outside In Development With Cucumber

Outside-In

Saturday, March 14, 2009

Page 26: Outside In Development With Cucumber

Saturday, March 14, 2009

Page 27: Outside In Development With Cucumber

Saturday, March 14, 2009

Page 28: Outside In Development With Cucumber

Write Scenarios

Saturday, March 14, 2009

Page 29: Outside In Development With Cucumber

Steps are pending

Saturday, March 14, 2009

Page 30: Outside In Development With Cucumber

Write Step Definition

Saturday, March 14, 2009

Page 31: Outside In Development With Cucumber

Go Down A Gear

Saturday, March 14, 2009

Page 32: Outside In Development With Cucumber

RSpec

Saturday, March 14, 2009

Page 33: Outside In Development With Cucumber

RSpec

We ain’t gotno RSPEC!

Saturday, March 14, 2009

Page 34: Outside In Development With Cucumber

RSpec, TestUnit, etc

Saturday, March 14, 2009

Page 35: Outside In Development With Cucumber

Write Code Example(Unit Test)

Saturday, March 14, 2009

Page 36: Outside In Development With Cucumber

Make Example Pass

Saturday, March 14, 2009

Page 37: Outside In Development With Cucumber

REFACTOR!!

Saturday, March 14, 2009

Page 38: Outside In Development With Cucumber

Where Are we?

Saturday, March 14, 2009

Page 39: Outside In Development With Cucumber

Continue until...

Saturday, March 14, 2009

Page 40: Outside In Development With Cucumber

REFACTORand

REPEAT

Saturday, March 14, 2009

Page 41: Outside In Development With Cucumber

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

Scenario: add wish Given I am logged in When I make a "New car" wish Then "New car" should appear on my wish list

Saturday, March 14, 2009

Page 42: Outside In Development With Cucumber

Saturday, March 14, 2009

Page 43: Outside In Development With Cucumber

Line # of scenario

Saturday, March 14, 2009

Page 44: Outside In Development With Cucumber

Saturday, March 14, 2009

Page 45: Outside In Development With Cucumber

I can has backtraze?Given I am logged in #features/manage_my_wishes.feature:8

Saturday, March 14, 2009

Page 46: Outside In Development With Cucumber

Saturday, March 14, 2009

Page 47: Outside In Development With Cucumber

features/i_can_has_wishez_plz.feature

OH HAI: I CAN HAS WISHEZ PLZ

SO DAT I CAN HAS HUGS TIEM AN PLAY TIEM AN SLEEP TIEM AN NOM TIEM AS NICE GREEDEE KITTEH I CAN PLZ MANEGE TEH WISHEZ

MISHUN: MAK NEW WISH GIVN I AM LOGGD IN WEN I MAK "CHEEZBURGER" WISH DEN I C "CHEEZBURGER" ON ME WISHEZ LIT

Saturday, March 14, 2009

Page 48: Outside In Development With Cucumber

Saturday, March 14, 2009

Page 49: Outside In Development With Cucumber

Saturday, March 14, 2009

Page 50: Outside In Development With Cucumber

cucumber some.feature --language en-lol

Saturday, March 14, 2009

Page 51: Outside In Development With Cucumber

cucumber some.feature --language en-lol

Saturday, March 14, 2009

Page 52: Outside In Development With Cucumber

Saturday, March 14, 2009

Page 53: Outside In Development With Cucumber

Saturday, March 14, 2009

Page 54: Outside In Development With Cucumber

features/step_definitions/user_steps.rb

Given /^I am logged in$/ do @current_user = create_user(:email_confirmed => true)

end

Saturday, March 14, 2009

Page 55: Outside In Development With Cucumber

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

Saturday, March 14, 2009

Page 56: Outside In Development With Cucumber

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

Saturday, March 14, 2009

Page 57: Outside In Development With Cucumber

features/step_definitions/user_steps.rb

Given /^I am logged in$/ do @current_user = create_user(:email_confirmed => true)

end

Saturday, March 14, 2009

Page 58: Outside In Development With Cucumber

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

Saturday, March 14, 2009

Page 59: Outside In Development With Cucumber

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

Saturday, March 14, 2009

Page 60: Outside In Development With Cucumber

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

Saturday, March 14, 2009

Page 61: Outside In Development With Cucumber

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

Saturday, March 14, 2009

Page 62: Outside In Development With Cucumber

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

Saturday, March 14, 2009

Page 63: Outside In Development With Cucumber

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

19 Steps Out-of-box

Saturday, March 14, 2009

Page 64: Outside In Development With Cucumber

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

Saturday, March 14, 2009

Page 65: Outside In Development With Cucumber

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

Saturday, March 14, 2009

Page 66: Outside In Development With Cucumber

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

Saturday, March 14, 2009

Page 67: Outside In Development With Cucumber

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.

Saturday, March 14, 2009

Page 68: Outside In Development With Cucumber

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

Saturday, March 14, 2009

Page 69: Outside In Development With Cucumber

Saturday, March 14, 2009

Page 70: Outside In Development With Cucumber

No route matches “/sessions/create” with{:method=>:post} (ActionController::RoutingError)

Saturday, March 14, 2009

Page 71: Outside In Development With Cucumber

I’m going to cheat...

Saturday, March 14, 2009

Page 72: Outside In Development With Cucumber

I’m going to cheat...$ gem install thoughtbot-clearance$ ./script generate clearance$ ./script generate clearance_features

Saturday, March 14, 2009

Page 73: Outside In Development With Cucumber

Saturday, March 14, 2009

Page 74: Outside In Development With Cucumber

features/step_definitions/wish_steps.rb

When /^I make a "(.+)" wish$/ do |wish| end

Then /^(.+) should appear on my wish list$/ do |wish| end

Saturday, March 14, 2009

Page 75: Outside In Development With Cucumber

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

Saturday, March 14, 2009

Page 76: Outside In Development With Cucumber

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

Saturday, March 14, 2009

Page 77: Outside In Development With Cucumber

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

Saturday, March 14, 2009

Page 78: Outside In Development With Cucumber

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)

Saturday, March 14, 2009

Page 79: Outside In Development With Cucumber

config/routes.rb

ActionController::Routing::Routes.draw do |map| map.resources :wishes

Saturday, March 14, 2009

Page 80: Outside In Development With Cucumber

config/routes.rb

ActionController::Routing::Routes.draw do |map| map.resources :wishes

When I make a “New car” wishuninitialized constant WishesController (NameError)

Saturday, March 14, 2009

Page 81: Outside In Development With Cucumber

config/routes.rb

ActionController::Routing::Routes.draw do |map| map.resources :wishes

$./script generate rspec_controller new create

Saturday, March 14, 2009

Page 82: Outside In Development With Cucumber

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)

Saturday, March 14, 2009

Page 83: Outside In Development With Cucumber

app/views/wishes/index.html.erb

<%= link_to "Make a wish", new_wish_path %>

Saturday, March 14, 2009

Page 84: Outside In Development With Cucumber

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)

Saturday, March 14, 2009

Page 85: Outside In Development With Cucumber

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

Saturday, March 14, 2009

Page 86: Outside In Development With Cucumber

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 %>

Saturday, March 14, 2009

Page 87: Outside In Development With Cucumber

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!

Saturday, March 14, 2009

Page 88: Outside In Development With Cucumber

View

Controller

Saturday, March 14, 2009

Page 89: Outside In Development With Cucumber

spec/controllers/wishes_controller_spec.rb

describe WishesController do describe "POST / (#create)" do

endend

Saturday, March 14, 2009

Page 90: Outside In Development With Cucumber

spec/controllers/wishes_controller_spec.rb

describe WishesController do describe "POST / (#create)" do it "should create 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

Saturday, March 14, 2009

Page 91: Outside In Development With Cucumber

app/controllers/wishes_controller.rb

class WishesController < ApplicationController

def create current_user.wishes.create(params['wish']) end

end

Saturday, March 14, 2009

Page 92: Outside In Development With Cucumber

spec/controllers/wishes_controller_spec.rb

it "should redirect the user to their wish list" do do_post response.should redirect_to(wishes_path) end

spec/controllers/wishes_controller_spec.rb

describe WishesController do describe "POST / (#create)" do before(:each) do .....

endend

Saturday, March 14, 2009

Page 93: Outside In Development With Cucumber

app/controllers/wishes_controller.rb

def create current_user.wishes.create(params['wish']) redirect_to :action => :index end

Saturday, March 14, 2009

Page 94: Outside In Development With Cucumber

View

Controller

Model

Saturday, March 14, 2009

Page 95: Outside In Development With Cucumber

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)

Saturday, March 14, 2009

Page 96: Outside In Development With Cucumber

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

Saturday, March 14, 2009

Page 97: Outside In Development With Cucumber

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

Saturday, March 14, 2009

Page 98: Outside In Development With Cucumber

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!”

Saturday, March 14, 2009

Page 99: Outside In Development With Cucumber

spec/controllers/wishes_controller_spec.rb

it "should notify the user of creation via the flash" do do_post flash[:success].should == "Your wish has been added!"end

Saturday, March 14, 2009

Page 100: Outside In Development With Cucumber

app/controllers/wishes_controller.rb

def create flash[:success] = "Your wish has been added!" end

spec/controllers/wishes_controller_spec.rb

it "should notify the user of creation via the flash" do do_post flash[:success].should == "Your wish has been added!"end

current_user.wishes.create(params['wish']) redirect_to :action => :index

Saturday, March 14, 2009

Page 101: Outside In Development With Cucumber

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 notify 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”

Saturday, March 14, 2009

Page 102: Outside In Development With Cucumber

app/views/wishes/index.html.erb

<ul><% @wishes.each do |wish| %> <li><%= wish.name %></li><% end %></ul>

Saturday, March 14, 2009

Page 103: Outside In Development With Cucumber

spec/controllers/wishes_controller_spec.rb

describe "GET / (#index)" do def do_get get :index end

it "should assign the user's wishes to the view" do do_get assigns[:wishes].should == @current_user.wishes end

end

Saturday, March 14, 2009

Page 104: Outside In Development With Cucumber

app/controllers/wishes_controller.rb

def index @wishes = current_user.wishes end

Saturday, March 14, 2009

Page 105: Outside In Development With Cucumber

Saturday, March 14, 2009

Page 106: Outside In Development With Cucumber

Saturday, March 14, 2009

Page 107: Outside In Development With Cucumber

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 |

Saturday, March 14, 2009

Page 108: Outside In Development With Cucumber

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

Saturday, March 14, 2009

Page 109: Outside In Development With Cucumber

| 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 |

Saturday, March 14, 2009

Page 110: Outside In Development With Cucumber

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

Examples: | input_1 | input_2 | button | output | | 20 | 30 | add | 50 | | 2 | 5 | add | 7 | | 0 | 40 | add | 40 |

Saturday, March 14, 2009

Page 111: Outside In Development With Cucumber

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

Examples: | 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 |

Saturday, March 14, 2009

Page 112: Outside In Development With Cucumber

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

Examples: | 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 |

Saturday, March 14, 2009

Page 113: Outside In Development With Cucumber

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

Examples: | input_1 | input_2 | button | output | | 20 | 30 | add | 50 | | 2 | 5 | add | 7 | | 0 | 40 | add | 40 |

<input_1> <input_2> <button> <output>

| 2 | 5 | add | 7 |

Saturday, March 14, 2009

Page 114: Outside In Development With Cucumber

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

Examples: | input_1 | input_2 | button | output | | 20 | 30 | add | 50 | | 2 | 5 | add | 7 | | 0 | 40 | add | 40 |

<input_1> <input_2> <button> <output>

| 0 | 40 | add | 40 |

Saturday, March 14, 2009

Page 115: Outside In Development With Cucumber

When /^I view the wish list for "(.+)"$/ do |user_name| Given "I am logged in" visit "/wishes/#{user_name}"end

Steps Within Steps

Saturday, March 14, 2009

Page 116: Outside In Development With Cucumber

When /^I view the wish list for "(.+)"$/ do |user_name| visit "/wishes/#{user_name}"end

Steps Within Steps Given "I am logged in"

Saturday, March 14, 2009

Page 117: Outside In Development With Cucumber

When /^I view the wish list for "(.+)"$/ do |user_name| login_as(create_user) visit "/wishes/#{user_name}"end

Helpers - Ruby FTW

Saturday, March 14, 2009

Page 118: Outside In Development With Cucumber

When /^I view the wish list for "(.+)"$/ do |user_name| visit "/wishes/#{user_name}"end

Helpers - Ruby FTW login_as(create_user)

Saturday, March 14, 2009

Page 119: Outside In Development With Cucumber

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

Saturday, March 14, 2009

Page 120: Outside In Development With Cucumber

features/step_definitions/user_steps.rb

def login_as(user) visit new_session_path fill_in "Email", :with => 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 Given /^I am logged in$/ do @current_user = create_user(:email_confirmed => true) login_as(@current_user)end

Saturday, March 14, 2009

Page 121: Outside In Development With Cucumber

features/step_definitions/user_steps.rb

def login_as(user) visit new_session_path fill_in "Email", :with => 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 Given /^I am logged in$/ do @current_user = create_user(:email_confirmed => true) login_as(@current_user)end

Saturday, March 14, 2009

Page 122: Outside In Development With Cucumber

features/step_definitions/user_steps.rb

def login_as(user) visit new_session_path fill_in "Email", :with => 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 Given /^I am logged in$/ do @current_user = create_user(:email_confirmed => true) login_as(@current_user)end

“Every time you monkeypatch Object, a kitten dies.”

http://seanohalpin.github.com/unobtrusive-metaprogramming/unobtrusive-metaprogramming.html

Saturday, March 14, 2009

Page 123: Outside In Development With Cucumber

features/step_definitions/user_steps.rb

module UserHelpers def login_as(user) visit new_session_path fill_in "Email", :with => 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") endend

Saturday, March 14, 2009

Page 124: Outside In Development With Cucumber

features/step_definitions/user_steps.rb

module UserHelpers def login_as(user) visit new_session_path fill_in "Email", :with => 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") endend

Saturday, March 14, 2009

Page 125: Outside In Development With Cucumber

features/step_definitions/user_steps.rb

World { |world| world.extend UserHelpers }

module UserHelpers def login_as(user) visit new_session_path fill_in "Email", :with => 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") endend

World { |world| world.extend UserHelpers }

Saturday, March 14, 2009

Page 126: Outside In Development With Cucumber

I can skp teh unit testz?

Saturday, March 14, 2009

Page 127: Outside In Development With Cucumber

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.

Saturday, March 14, 2009

Page 128: Outside In Development With Cucumber

SRSLY?Model specs,Controller Specs,and view specs!?

Saturday, March 14, 2009

Page 129: Outside In Development With Cucumber

Saturday, March 14, 2009

Page 130: Outside In Development With Cucumber

Saturday, March 14, 2009

Page 131: Outside In Development With Cucumber

Saturday, March 14, 2009

Page 132: Outside In Development With Cucumber

WSaturday, March 14, 2009

Page 133: Outside In Development With Cucumber

MSaturday, March 14, 2009

Page 134: Outside In Development With Cucumber

More tests == More Maintenance

Saturday, March 14, 2009

Page 135: Outside In Development With Cucumber

Test Value =Design +

Documentation +Defence (regression)

Saturday, March 14, 2009

Page 136: Outside In Development With Cucumber

if test.value > test.cost Suite.add(test)end

Saturday, March 14, 2009

Page 137: Outside In Development With Cucumber

KTHXBYE!BenMabey.com

github.com/bmabey

Twitter: bmabeyIRC: mabes

Saturday, March 14, 2009