You are on page 1of 137

Outside-In

Development
With

Ben Mabey
Saturday, March 14, 2009
Who’s my
audience?

Saturday, March 14, 2009


Saturday, March 14, 2009
Scenario: planning meeting
Given I am a Software Developer
When I am given a feature request
Then I should...

Saturday, March 14, 2009


What is the most
CRITICAL
word to keep in mind?

Saturday, March 14, 2009


Saturday, March 14, 2009
W
Scenario: planning meeting
Given I am a Software Developer
When I am given a feature request
Then I should ask why.

Saturday, March 14, 2009


_why

Saturday, March 14, 2009


Why?
Saturday, March 14, 2009
Feature Request:
Print Reports
Story from
Thought works:

http://
www.theregister.co.uk/
2007/06/25/

Saturday, March 14, 2009


Saturday, March 14, 2009
Protect Revenue

Increase Revenue

Manage Cost

Saturday, March 14, 2009


* not executed
* documentation value

Feature: title * variant of contextra


* business value up front

In order to [Business Value]


As a [Role]
I want to [Some Action] (feature)

Saturday, March 14, 2009


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


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

Saturday, March 14, 2009


Scenario: title
Given [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


project_root/
|
`-- features

Saturday, March 14, 2009


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

Saturday, March 14, 2009


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

Saturday, March 14, 2009


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


Step

Given a widget

Saturday, March 14, 2009


Step Definition

Given /^a widget$/ do


Given a widget #codes go here
end

Saturday, March 14, 2009


Step Definition
Step Mother

Given /^a widget$/ do


Given a widget #codes go here
end

Saturday, March 14, 2009


Step Definition
Step Mother

Given /^a widget$/ do


Given a widget #codes go here
end

Saturday, March 14, 2009


Outside-In

Saturday, March 14, 2009


Saturday, March 14, 2009
Saturday, March 14, 2009
Write Scenarios

Saturday, March 14, 2009


Steps are pending

Saturday, March 14, 2009


Write Step Definition

Saturday, March 14, 2009


Go Down A Gear

Saturday, March 14, 2009


RSpec

Saturday, March 14, 2009


RSpec

We ain’t got
no RSPEC!

Saturday, March 14, 2009


RSpec, TestUnit, etc

Saturday, March 14, 2009


Write Code Example
(Unit Test)

Saturday, March 14, 2009


Make Example Pass

Saturday, March 14, 2009


REFACTOR!!

Saturday, March 14, 2009


Where Are we?

Saturday, March 14, 2009


Continue until...

Saturday, March 14, 2009


REFACTOR
and
REPEAT
Saturday, March 14, 2009
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


Saturday, March 14, 2009
Line # of scenario

Saturday, March 14, 2009


Saturday, March 14, 2009
I can has backtraze?
Given I am logged in #features/manage_my_wishes.feature:8

Saturday, March 14, 2009


Saturday, March 14, 2009
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


Saturday, March 14, 2009
Saturday, March 14, 2009
cucumber some.feature --language en-lol

Saturday, March 14, 2009


cucumber some.feature --language en-lol

Saturday, March 14, 2009


Saturday, March 14, 2009
Saturday, March 14, 2009
features/step_definitions/user_steps.rb
Given /^I am logged in$/ do
@current_user = create_user(:email_confirmed => true)

end

Saturday, March 14, 2009


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


features/step_definitions/user_steps.rb
Given /^I am logged in$/ do
@current_user = create_user(:email_confirmed => true)

end

Fixture Replacement, Fixjour, Factory Girl, etc


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'
)
end
end

Saturday, March 14, 2009


features/step_definitions/user_steps.rb
Given /^I am logged in$/ do
@current_user = create_user(:email_confirmed => true)

end

Saturday, March 14, 2009


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
end

Saturday, March 14, 2009


features/step_definitions/user_steps.rb
Webrat / Awesomeness
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

Saturday, March 14, 2009


features/step_definitions/user_steps.rb
Webrat / Awesomeness
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

Saturday, March 14, 2009


features/step_definitions/user_steps.rb
Webrat / Awesomeness
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/support/env.rb
require 'webrat'

Webrat.configure do |config|
config.mode = :rails
end

Saturday, March 14, 2009


features/step_definitions/user_steps.rb
Webrat / Awesomeness
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/support/env.rb
require 'webrat'

Webrat.configure do |config|
config.mode = :rails
end
Adapter

Saturday, March 14, 2009


features/step_definitions/user_steps.rb
Webrat / Awesomeness
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/webrat_steps.rb
When /^I press "(.*)"$/ do |button|
click_button(button)
end
19 Steps Out-of-box
When /^I follow "(.*)"$/ do |link|
click_link(link)
end

When /^I fill in "(.*)" with "(.*)"$/ do |field, value|


fill_in(field, :with => value)
end
Saturday, March 14, 2009
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
end

Saturday, March 14, 2009


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
session[:user_id].should == @current_user.id
end

Saturday, March 14, 2009


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
session[:user_id].should == @current_user.id
controller.current_user.should == @current_user
end

Saturday, March 14, 2009


features/step_definitions/user_steps.rb
Given /^I am logged in$/ do
@current_user = create_user(:email_confirmed => true)

visit new_session_path
Specify outcome, not implementation.
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
session[:user_id].should == @current_user.id
controller.current_user.should == @current_user
response.should contain("Signed in successfully")
end

Saturday, March 14, 2009


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


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

Saturday, March 14, 2009


I’m going to cheat...

Saturday, March 14, 2009


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

Saturday, March 14, 2009


Saturday, March 14, 2009
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


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


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

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

end

Saturday, March 14, 2009


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

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


response.should contain("Your wish has been added!")
response.should contain(wish)
end

Saturday, March 14, 2009


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_button
end
No route matches “/wishes” with
Then /^(.+) should appear
{:method=>:get} on my wish list$/ do |wish|
(ActionController::RoutingError)
response.should contain("Your wish has been added!")
response.should contain(wish)
end

Saturday, March 14, 2009


config/routes.rb
ActionController::Routing::Routes.draw do |map|

map.resources :wishes

Saturday, March 14, 2009


config/routes.rb
ActionController::Routing::Routes.draw do |map|

map.resources :wishes

When I make a “New car” wish


uninitialized constant WishesController (NameError)

Saturday, March 14, 2009


config/routes.rb
ActionController::Routing::Routes.draw do |map|

map.resources :wishes

$./script generate rspec_controller new create

Saturday, March 14, 2009


config/routes.rb
ActionController::Routing::Routes.draw do |map|

map.resources :wishes

When I make a “New car” wish


Could not find link with text or title or
id “Make a wish” (Webrat::NotFoundError)

Saturday, March 14, 2009


app/views/wishes/index.html.erb
<%= link_to "Make a wish", new_wish_path %>

Saturday, March 14, 2009


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


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

Saturday, March 14, 2009


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

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


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

Location Strategy FTW!


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


View

Controller

Saturday, March 14, 2009


spec/controllers/wishes_controller_spec.rb
describe WishesController do
describe "POST / (#create)" do

end
end

Saturday, March 14, 2009


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

Saturday, March 14, 2009


app/controllers/wishes_controller.rb
class WishesController < ApplicationController

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

end

Saturday, March 14, 2009


spec/controllers/wishes_controller_spec.rb
describe WishesController do
describe "POST / (#create)" do
before(:each) do
.....

it "should redirect the user to their wish list" do


do_post
response.should redirect_to(wishes_path)
end

end
end

Saturday, March 14, 2009


app/controllers/wishes_controller.rb
def create
current_user.wishes.create(params['wish'])
redirect_to :action => :index
end

Saturday, March 14, 2009


View

Controller

Model

Saturday, March 14, 2009


app/controllers/wishes_controller.rb
def create
current_user.wishes.create(params['wish'])
redirect_to :action => :index
end

When I make a “New car” wish


undefined method `wishes` for #<User:0x268e898>
(NoMethodError)

Saturday, March 14, 2009


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


app/models/wish.rb
class Wish < ActiveRecord::Base
belongs_to :user
end

app/models/user.rb
class User < ActiveRecord::Base
include Clearance::App::Models::User
has_many :wishes
end

Saturday, March 14, 2009


app/models/wish.rb
class Wish < ActiveRecord::Base
belongs_to :user
end

app/models/user.rb
When I make a “New car” wish
class User < ActiveRecord::Base
Then “New car” should appear on my wish
include Clearance::App::Models::User
expected the following element’s content to include
has_many :wishes
“Your wish has been added!”
end

Saturday, March 14, 2009


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


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

app/controllers/wishes_controller.rb
def create
current_user.wishes.create(params['wish'])
flash[:success] = "Your wish has been added!"
redirect_to :action => :index
end

Saturday, March 14, 2009


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

app/controllers/wishes_controller.rb
Then “New car” should appear on my wish
expected the following element’s content to include
def create
“New car”
current_user.wishes.create(params['wish'])
flash[:success] = "Your wish has been added!"
redirect_to :action => :index
end

Saturday, March 14, 2009


app/views/wishes/index.html.erb
<ul>
<% @wishes.each do |wish| %>
<li><%= wish.name %></li>
<% end %>
</ul>

Saturday, March 14, 2009


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


app/controllers/wishes_controller.rb
def index
@wishes = current_user.wishes
end

Saturday, March 14, 2009


Saturday, March 14, 2009
Saturday, March 14, 2009
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


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|

end
end

Saturday, March 14, 2009


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|
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"])


end
end

Saturday, March 14, 2009


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


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


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


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


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


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

Saturday, March 14, 2009


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

Saturday, March 14, 2009


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

Saturday, March 14, 2009


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

Saturday, March 14, 2009


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
end

Saturday, March 14, 2009


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


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


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 “Every time you monkeypatch
# make sure we have actually logged in- so we fail fast if not
Object, a kitten dies.”
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

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

Saturday, March 14, 2009


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")
end
end

Saturday, March 14, 2009


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")
end
end

Saturday, March 14, 2009


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")
end
end

World { |world| world.extend UserHelpers }

Saturday, March 14, 2009


I can skp teh
unit testz?

Saturday, March 14, 2009


Acceptance Tests Unit Tests

Application Level Object Level- Isolated!


For Customers For developers
Slow FAST! (should be at least)
Good confidence - Tighter Feedback Loop
Prevent against More about design!!!!!!!!!!!!
regression

Will need both gears!


Some things are easier to
test at the application
level and vice-versa.

Saturday, March 14, 2009


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

Saturday, March 14, 2009


Saturday, March 14, 2009
Saturday, March 14, 2009
Saturday, March 14, 2009
Saturday, March 14, 2009
W
Saturday, March 14, 2009
M
More tests ==
More Maintenance

Saturday, March 14, 2009


Test Value =
Design +
Documentation +
Defence
(regression)

Saturday, March 14, 2009


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

Saturday, March 14, 2009


KTHXBYE!
BenMabey.com
github.com/bmabey
Twitter: bmabey
IRC: mabes
Saturday, March 14, 2009

You might also like