outside in development with cucumber

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

Upload: littlebigruby

Post on 18-Dec-2014

1.634 views

Category:

Documents


1 download

DESCRIPTION

 

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