object-oriented bdd w/ cucumber by matt van horn

82
OBJECT ORIENTED BDD with CUCUMBER Thursday, October 3, 13

Upload: solano-labs

Post on 28-Nov-2014

10.303 views

Category:

Technology


1 download

DESCRIPTION

Here are the slides that Matt van Horn from New Relic presented at last night's Automated Testing San Francisco meetup, hosted by Constant Contact. This presentation briefly covers continuous integration at New Relic, and then dives deeper into Object-Oriented BDD with Cucumber. We thank Matt for the great presentation. Please feel free to connect with Matt on Github or Twitter: github.com/mattvanhorn or @nycplayer http://www.meetup.com/Automated-Testing-San-Francisco/

TRANSCRIPT

Page 1: Object-Oriented BDD w/ Cucumber by Matt van Horn

OBJECT ORIENTED BDD

with CUCUMBER

Thursday, October 3, 13

Page 2: Object-Oriented BDD w/ Cucumber by Matt van Horn

Who Am I?

Senior  So(ware  Engineer  at  New  Relic

20  years  of  web  applica9on  development

12  years  of  TDD

5  years  of  BDD

github.com/maFvanhorn  or  @nycplayer

Thursday, October 3, 13

Page 3: Object-Oriented BDD w/ Cucumber by Matt van Horn

New Relic CI

Thursday, October 3, 13

Page 4: Object-Oriented BDD w/ Cucumber by Matt van Horn

New Relic CI

Github,  TDDium,  Jenkins

Feature  branches,  Pull  Requests

Automa9c  builds,  Code  reviews

Automated  deploys,  but  some  manual  control

Thursday, October 3, 13

Page 5: Object-Oriented BDD w/ Cucumber by Matt van Horn

New Relic CI

We  deploy  3x  per  day

Automated  tes9ng  is  part  of  the  process

However...

Thursday, October 3, 13

Page 6: Object-Oriented BDD w/ Cucumber by Matt van Horn

New Relic CI

We  have  a  large,  slow  test  suite

We  have  a  large,  legacy  Rails  app

We  have  a  lack  of  up-­‐to-­‐date  documenta9on

We  o(en  have  communica9on  issues

Thursday, October 3, 13

Page 7: Object-Oriented BDD w/ Cucumber by Matt van Horn

New Relic CI

We  want  to  go  from  3x/day  to  ‘at  will’

We  are  dedica9ng  9me  to  improving  our  tests

Automated  acceptance  tests  are  key

(Faster  unit  tests  are  also  important)

Thursday, October 3, 13

Page 8: Object-Oriented BDD w/ Cucumber by Matt van Horn

BehaviorDrivendevelopment

Thursday, October 3, 13

Page 9: Object-Oriented BDD w/ Cucumber by Matt van Horn

BehaviorDrivendevelopmentBDD  is  a  second-­‐genera9on,  outside–in,  pull-­‐based,  mul9ple-­‐stakeholder,  mul9ple-­‐scale,  high-­‐automa9on,  agile  methodology.  It  describes  a  cycle  of  interac9ons  with  well-­‐defined  outputs,  resul9ng  in  the  delivery  of  working,  tested  so(ware  that  maFers.

-­‐  Dan  North

Thursday, October 3, 13

Page 10: Object-Oriented BDD w/ Cucumber by Matt van Horn

BehaviorDrivenDevelopment

“BDD  describes  TDD  done  well”

-­‐  MaF  Wynne

Thursday, October 3, 13

Page 11: Object-Oriented BDD w/ Cucumber by Matt van Horn

BehaviorDrivenDevelopment“Can  you  give  me  some  examples  (of  using  it)?”

vs.

“What  are  the  requirements  (for  implemen9ng  it)?”

Thursday, October 3, 13

Page 12: Object-Oriented BDD w/ Cucumber by Matt van Horn

Outside In

Start  with  a  conversa9on

Determine  the  business  value

Provide  examples  of  use

Thursday, October 3, 13

Page 13: Object-Oriented BDD w/ Cucumber by Matt van Horn

Outside In  User  Interface

Browser

Views

Controllers

Models

Thursday, October 3, 13

Page 14: Object-Oriented BDD w/ Cucumber by Matt van Horn

Outside In  User  Interface

Browser

Views

Controllers

Models

Cucumber

RSpec

Thursday, October 3, 13

Page 15: Object-Oriented BDD w/ Cucumber by Matt van Horn

Outside InRed,  Green,  REFACTOR

Outer  loop:  Features,  stories,  scenarios

Inner  loop:  Unit  tests,  classes,  methods

Cucumber

Thursday, October 3, 13

Page 16: Object-Oriented BDD w/ Cucumber by Matt van Horn

Red,  Green,  REFACTOR

Outer  loop:  Features,  stories,  scenarios

Inner  loop:  Unit  tests,  classes,  methods

Outside In Cucumber

RSpec

Thursday, October 3, 13

Page 17: Object-Oriented BDD w/ Cucumber by Matt van Horn

Outside In Cucumber

RSpecRed,  Green,  REFACTOR

Outer  loop:  Features,  stories,  scenarios

Inner  loop:  Unit  tests,  classes,  methods

Thursday, October 3, 13

Page 18: Object-Oriented BDD w/ Cucumber by Matt van Horn

Outside In Cucumber

RSpecRed,  Green,  REFACTOR

Outer  loop:  Features,  stories,  scenarios

Inner  loop:  Unit  tests,  classes,  methods

Thursday, October 3, 13

Page 19: Object-Oriented BDD w/ Cucumber by Matt van Horn

BDD TOOLS

Cucumber,  RSpec,  FitNesse

Gherkin

Spinach,  Turnip,  Steak,  Filet

Capybara,  Wa9r,  WebRAT

Selenium,  Webkit,  PhantomJS,  Rack::Test

Thursday, October 3, 13

Page 20: Object-Oriented BDD w/ Cucumber by Matt van Horn

Cucumber Complaints

Don’t  need  English,  code  is  fine

Doesn’t  save  developer  9me

BriFle  tests,  needing  constant  maintenance

Thursday, October 3, 13

Page 21: Object-Oriented BDD w/ Cucumber by Matt van Horn

You’reDoING ITWRONG

Thursday, October 3, 13

Page 22: Object-Oriented BDD w/ Cucumber by Matt van Horn

Cucumber Done right

Minimizes  miscommunica9on

Hides  implementa9on  details

Provides  robust  regression  tests

Communicates  inten9ons

Thursday, October 3, 13

Page 23: Object-Oriented BDD w/ Cucumber by Matt van Horn

Cucumber Done right

Cucumber  allows  us  to  inform,  in  plain  English,  the  intended  behavior  of  applica9ons  we  build  to  future  developers,  rather  than  forcing  them  to  spelunk  through  code  to  figure  it  out.

-­‐  Ma,  Polito

Thursday, October 3, 13

Page 24: Object-Oriented BDD w/ Cucumber by Matt van Horn

Object ORientedCucumber

Thursday, October 3, 13

Page 25: Object-Oriented BDD w/ Cucumber by Matt van Horn

Object ORientedCucumber

Keep  data  and  behavior  together

Hide  implementa9on  details

Send  messages  to  accomplish  tasks

Thursday, October 3, 13

Page 26: Object-Oriented BDD w/ Cucumber by Matt van Horn

Page Object

URLs

UI Elements

Page Sections

DomainAction

Methods

BrowserDriver

Thursday, October 3, 13

Page 27: Object-Oriented BDD w/ Cucumber by Matt van Horn

Page Object

Provides  a  model  for  a  web  UI

Hides  details  of  dealing  with  browser

Keeps  UI  details  in  one  place

Enables  expressive  test  code

Thursday, October 3, 13

Page 28: Object-Oriented BDD w/ Cucumber by Matt van Horn

Site Prism

Open  source  Ruby  gem  

Provides  simple  DSL  for  page  Objects

Exposes  Capybara  nodes

Thursday, October 3, 13

Page 29: Object-Oriented BDD w/ Cucumber by Matt van Horn

Technique

Plain  English,  not  code  (or  pseudo-­‐code)

Domain  concepts,  not  implementa9on  details

Focus  on  the  value,  not  the  incidentals

Thursday, October 3, 13

Page 30: Object-Oriented BDD w/ Cucumber by Matt van Horn

Stories & Scenarios Impera9ve

Scenario: Typical Meetup

Given I am on the estimate page When I fill in "Guest count" with "10" And I fill in "Slice count" with "2" And I press "Get Estimate" Then I should see "You will need to order 3 pizzas"

Thursday, October 3, 13

Page 31: Object-Oriented BDD w/ Cucumber by Matt van Horn

“English  -­‐  we  hateses  it”

Scenario: Typical Meetup

Given I am on “/estimates/new” And I fill in "input#guests" with "10" And I fill in "input#slices" with "2" And I press "input[type=’submit’]" Then I should see "You will need to order 3 pizzas"

Stories & Scenarios

Thursday, October 3, 13

Page 32: Object-Oriented BDD w/ Cucumber by Matt van Horn

Stories & Scenarios

Declara9ve

Scenario: Typical Meetup (Guests eat 2 slices each)

Given There are 10 guests expected When I ask how much to order Then I will know I need to buy 3 pizzas

Thursday, October 3, 13

Page 33: Object-Oriented BDD w/ Cucumber by Matt van Horn

ExamplesFeature: Estimating Pizza Requirements In order to avoid wasting either pizza or money As an organizer I want to know how many pizzas I need to order

Background: Given there are 10 guests expected

Scenario: Typical meetup (Guests eat 2 slices) Given the guests are hungry When I ask how much to order Then I will know I need to buy 3 pizzas

Scenario: Late-night meetup (Guests eat 3 slices) Given the guests are starving When I ask how much to order Then I will know I need to buy 4 pizzas

Scenario: After-lunch meetup (Guests eat 1 slice) Given the guests are full When I ask how much to order Then I will know I need to buy 2 pizzas

Thursday, October 3, 13

Page 34: Object-Oriented BDD w/ Cucumber by Matt van Horn

Step Definitions

Use  methods  that  relate  to  the  domain

Avoid  nes9ng  steps

Mostly  black  box

Some  white  box  can  be  very  useful

Thursday, October 3, 13

Page 35: Object-Oriented BDD w/ Cucumber by Matt van Horn

ExamplesGiven(/^there are (\d+) guests expected$/) do |guest_count| Site.new_estimate_page.guests_expected = guest_countend

Given(/^the guests are (full|hungry|starving)$/) do |hunger_level| Site.new_estimate_page.hunger_level = hunger_levelend

When 'I ask how much to order' do Site.new_estimate_page.request_estimateend

Then(/^I will know I need to buy (\d+ pizzas)$/) do |pie_count| expect(Site.new_estimate_page).to have_text("#{pie_count}")end

Thursday, October 3, 13

Page 36: Object-Oriented BDD w/ Cucumber by Matt van Horn

ExamplesGiven(/^there are (\d+) guests expected$/) do |guest_count| Site.new_estimate_page.guests_expected = guest_countend

Given(/^the guests are (full|hungry|starving)$/) do |hunger_level| Site.new_estimate_page.hunger_level = hunger_levelend

When 'I ask how much to order' do Site.new_estimate_page.request_estimateend

Then(/^I will know I need to buy (\d+ pizzas)$/) do |pie_count| expect(Site.new_estimate_page).to have_text("#{pie_count}")end

Thursday, October 3, 13

Page 37: Object-Oriented BDD w/ Cucumber by Matt van Horn

Examples# Utility class to provide easy access to page objects.class Site def self.current_page @current_page end

def self.method_missing(meth_name, *args) klass = meth_name.to_s.classify @current_page = klass.constantize.new endend

Thursday, October 3, 13

Page 38: Object-Oriented BDD w/ Cucumber by Matt van Horn

Examplesclass NewEstimatePage < SitePrism::Page URL = Rails.application.routes.url_helpers.root_path

set_url URL set_url_matcher %r(#{URL})

element :guests_field, "input[name='estimate[guest_count]']" element :slices_field, "input[name='estimate[slice_count]']" element :submit_btn, "input[name='commit']"

# ... instance methods elided ...

end

Thursday, October 3, 13

Page 39: Object-Oriented BDD w/ Cucumber by Matt van Horn

Examplesclass NewEstimatePage < SitePrism::Page URL = Rails.application.routes.url_helpers.root_path

set_url URL set_url_matcher %r(#{URL})

element :guests_field, "input[name='estimate[guest_count]']" element :slices_field, "input[name='estimate[slice_count]']" element :submit_btn, "input[name='commit']"

# ... instance methods elided ...

end

Thursday, October 3, 13

Page 40: Object-Oriented BDD w/ Cucumber by Matt van Horn

Examplesclass NewEstimatePage < SitePrism::Page URL = Rails.application.routes.url_helpers.root_path

set_url URL set_url_matcher %r(#{URL})

element :guests_field, "input[name='estimate[guest_count]']" element :slices_field, "input[name='estimate[slice_count]']" element :submit_btn, "input[name='commit']"

# ... instance methods elided ...

end

Thursday, October 3, 13

Page 41: Object-Oriented BDD w/ Cucumber by Matt van Horn

Examplesclass NewEstimatePage < SitePrism::Page # ... DSL elided ...

def guests_expected=(guest_count) load unless displayed? guests_field.set guest_count end

def hunger_level=(hunger) load unless displayed? slices_per_person = case hunger when 'full' then 1 when 'hungry' then 2 when 'starving' then 3 end slices_field.set slices_per_person end

def request_estimate load unless displayed? submit_btn.click endend

Thursday, October 3, 13

Page 42: Object-Oriented BDD w/ Cucumber by Matt van Horn

DEMO

Thursday, October 3, 13

Page 43: Object-Oriented BDD w/ Cucumber by Matt van Horn

DEMO

Thursday, October 3, 13

Page 44: Object-Oriented BDD w/ Cucumber by Matt van Horn

Changes

Thursday, October 3, 13

Page 45: Object-Oriented BDD w/ Cucumber by Matt van Horn

Product Manager:

“We  should  es9mate  beer  as  well”

“It  should  work  the  same  way  as  pizza”

Thursday, October 3, 13

Page 46: Object-Oriented BDD w/ Cucumber by Matt van Horn

Application Changes:

Change  es9mate  model

Change  form  view

Change  es9mate  view

Change  es9mate  view  helper

Thursday, October 3, 13

Page 47: Object-Oriented BDD w/ Cucumber by Matt van Horn

Cucumber Changes:

Change  scenarios

Add  steps  for  new  scenario  changes

Add  elements  to  page  model

Add  methods  to  page  model  to  use  elements

Thursday, October 3, 13

Page 48: Object-Oriented BDD w/ Cucumber by Matt van Horn

Examples Scenario: Typical meetup Given the guests are hungry And the guests love beer When I ask how much to order Then I will know I need to buy 3 pizza pies And I will know I need to buy 1 case and 1 six-pack of beer

Scenario: Late-night meetup Given the guests are starving And the guests like beer When I ask how much to order Then I will know I need to buy 4 pizza pies And I will know I need to buy 1 case of beer

Scenario: After-lunch meetup Given the guests are full And the guests are underage When I ask how much to order Then I will know I need to buy 2 pizza pies And I will know I don't need to buy beer

Thursday, October 3, 13

Page 49: Object-Oriented BDD w/ Cucumber by Matt van Horn

ExamplesGiven(/^the guests (like|love) beer$/) do |thirst| Site.new_estimate_page.thirst_level = thirstend

Given(/^the guests are underage$/) do Site.new_estimate_page.thirst_level = 'none'end

Then(/^I will know I need to buy ((?:\d+ cases?)?(?: and )?(?:\d+ six\-packs?)? of beer)$/) do |content| expect(Site.new_estimate_page).to have_text(content)end

Then(/^I will know I don't need to buy beer$/) do expect(Site.new_estimate_page).to have_text("no beer")end

Thursday, October 3, 13

Page 50: Object-Oriented BDD w/ Cucumber by Matt van Horn

Examplesclass NewEstimatePage < SitePrism::Page

# ... URL matchers elided ...

element :guests_field, "input[name='estimate[guest_count]']" element :slices_field, "input[name='estimate[slice_count]']" element :beers_field, "input[name='estimate[beer_count]']" element :submit_btn, "input[name='commit']"

# ... other methods elided ...

def thirst_level=(thirst) load unless displayed? beer_count = case thirst when 'none' then 0 when 'like' then 2 when 'love' then 3 end beers_field.set beer_count endend

Thursday, October 3, 13

Page 51: Object-Oriented BDD w/ Cucumber by Matt van Horn

Examples

Thursday, October 3, 13

Page 52: Object-Oriented BDD w/ Cucumber by Matt van Horn

Examples

Thursday, October 3, 13

Page 53: Object-Oriented BDD w/ Cucumber by Matt van Horn

Refactor

Thursday, October 3, 13

Page 54: Object-Oriented BDD w/ Cucumber by Matt van Horn

ExamplesGiven(/^there are (\d+) guests expected$/) do |guest_count| Site.new_estimate_page.guests_expected = guest_countend

Given(/^the guests are (full|hungry|starving)$/) do |hunger_level| Site.new_estimate_page.hunger_level = hunger_levelend

When 'I ask how much to order' do Site.new_estimate_page.request_estimateend

Then(/^I will know I need to buy (\d+ pizza pies)$/) do |pie_count| expect(Site.new_estimate_page).to have_text("#{pie_count}")end

Thursday, October 3, 13

Page 55: Object-Oriented BDD w/ Cucumber by Matt van Horn

HELPER ModulesHelpers  are  glue  between  inten9on  and  implementa9on  

Swapping  out  helpers  can  adapt  your  suite  to  different  plajorms  or  devices

Page  Objects  are  for  page  based  UIs,  but  the  principles  can  be  applied  to  other  domains

Thursday, October 3, 13

Page 56: Object-Oriented BDD w/ Cucumber by Matt van Horn

Examplesmodule WebHelper def guests_expected count Site.new_estimate_page.guests_expected = count end

def general_hunger_level hunger Site.new_estimate_page.hunger_level = hunger end

def general_thirst_level thirst Site.new_estimate_page.thirst_level = thirst end

def submit_request_for_estimate Site.new_estimate_page.request_estimate end

def verify_pizzas_needed num_pies expect(Site.new_estimate_page).to have_text("#{num_pies} pizza pies") end

def verify_beer_needed beer_text expect(Site.new_estimate_page).to have_text(beer_text) endendWorld(WebHelper)

Thursday, October 3, 13

Page 57: Object-Oriented BDD w/ Cucumber by Matt van Horn

ExamplesTransform /(\d+)/ do |num| num.to_iend

Given /^there are (\d+) guests expected$/ do |guest_count| guests_expected guest_countend

Given /^the guests are (full|hungry|starving)$/ do |hunger| general_hunger_level hungerend

Given /^the guests (like|love) beer$/ do |thirst| general_thirst_level thirstend

When 'I ask how much to order' do submit_request_for_estimateend

Then(/^I will know I need to buy (\d+) pizza pies$/) do |pie_count| verify_pizzas_needed pie_countend

Then(/^I will know I need to buy ((?:\d+ cases?)?(?: and )?(?:\d+ six\-packs?)? of beer)$/) do |beer_text| verify_beer_needed beer_textend

Thursday, October 3, 13

Page 58: Object-Oriented BDD w/ Cucumber by Matt van Horn

Product Manager:

“It’s  too  easy  to  make  typos.”

“Last  week  Ted  ordered  33  beers  per  person.”

“The  carpet  is  s9ll  not  completely  clean.”

Thursday, October 3, 13

Page 59: Object-Oriented BDD w/ Cucumber by Matt van Horn

Application Changes:

Change  form  view  to  use  different  widgets

Thursday, October 3, 13

Page 60: Object-Oriented BDD w/ Cucumber by Matt van Horn

Cucumber Changes:

Update  page  object  to  use  new  elements

Thursday, October 3, 13

Page 61: Object-Oriented BDD w/ Cucumber by Matt van Horn

Examples element :slices_field, "input[name='estimate[slice_count]']" element :beers_field, "input[name='estimate[beer_count]']"

def hunger_level=(hunger) load unless displayed? slices_per_person = case hunger when 'full' then 1 when 'hungry' then 2 when 'starving' then 3 end slices_field.set slices_per_person end

def thirst_level=(thirst) load unless displayed? beer_count = case thirst when 'none' then 0 when 'like' then 2 when 'love' then 3 end beers_field.set beer_count end

Thursday, October 3, 13

Page 62: Object-Oriented BDD w/ Cucumber by Matt van Horn

Examplesclass NewEstimatePage < SitePrism::Page

element :hunger_select, "select[name='estimate[slice_count]']" element :thirst_select, "select[name='estimate[beer_count]']"

def hunger_level=(hunger) load unless displayed? hunger_select.select hunger end

def thirst_level=(thirst) load unless displayed? thirst_select.select case thirst when 'like' then 'thirsty' when 'love' then 'extremely thirsty' else 'none' end endend

Thursday, October 3, 13

Page 63: Object-Oriented BDD w/ Cucumber by Matt van Horn

Examples

Thursday, October 3, 13

Page 64: Object-Oriented BDD w/ Cucumber by Matt van Horn

MORE Changes

Thursday, October 3, 13

Page 65: Object-Oriented BDD w/ Cucumber by Matt van Horn

Product Manager:

“We’re  adding  a  registra9on  feature.”

“Entering  the  number  of  guests  is  redundant.”

“We’ll  count  the  guests  in  the  database.”

Thursday, October 3, 13

Page 66: Object-Oriented BDD w/ Cucumber by Matt van Horn

Application Changes:Create  Guest  model,  with  db  migra9on

Add  guest  list  view  with  add  guest  form

Add  guests  controller

Change  routes  to  add  guest  routes

Change  es9mate  form  view

Change  es9mate  controller

Thursday, October 3, 13

Page 67: Object-Oriented BDD w/ Cucumber by Matt van Horn

Cucumber Changes:

Change  the  step  that  sets  up  the  number  of  guests.

Thursday, October 3, 13

Page 68: Object-Oriented BDD w/ Cucumber by Matt van Horn

Examples

Given /^there are (\d+) guests expected$/ do |guest_count| guests_expected guest_countend

Thursday, October 3, 13

Page 69: Object-Oriented BDD w/ Cucumber by Matt van Horn

Examples

Given /^there are (\d+) guests expected$/ do |guest_count| guest_count.times{ Fabricate(:guest) }end

Thursday, October 3, 13

Page 70: Object-Oriented BDD w/ Cucumber by Matt van Horn

Alternative

Change  the  implementa9on  of  the  method  the  step  calls.

Thursday, October 3, 13

Page 71: Object-Oriented BDD w/ Cucumber by Matt van Horn

Alternative

def guests_expected guest_count Site.new_estimate_page.guests_expected = count end

Thursday, October 3, 13

Page 72: Object-Oriented BDD w/ Cucumber by Matt van Horn

Alternative

def guests_expected guest_count guest_count.times{ Fabricate(:guest) } end

Thursday, October 3, 13

Page 73: Object-Oriented BDD w/ Cucumber by Matt van Horn

Alternative

module DatabaseHelper def guests_expected guest_count guest_count.times{ Fabricate(:guest) } endend

Thursday, October 3, 13

Page 74: Object-Oriented BDD w/ Cucumber by Matt van Horn

Alternative# support/helpers/database_helper.rb

module DatabaseHelper def guests_expected guest_count guest_count.times{ Fabricate(:guest) } endend

# support/helpers/helper_setup.rb

require_relative 'web_helper'require_relative 'database_helper'

World(WebHelper)World(DatabaseHelper)

Thursday, October 3, 13

Page 75: Object-Oriented BDD w/ Cucumber by Matt van Horn

Examples

Thursday, October 3, 13

Page 76: Object-Oriented BDD w/ Cucumber by Matt van Horn

Examples

Thursday, October 3, 13

Page 77: Object-Oriented BDD w/ Cucumber by Matt van Horn

Examples

Thursday, October 3, 13

Page 78: Object-Oriented BDD w/ Cucumber by Matt van Horn

platform changes

Thursday, October 3, 13

Page 79: Object-Oriented BDD w/ Cucumber by Matt van Horn

Examplesmodule PersonalAssistantHelper def general_hunger_level hunger PersonalAssistant.tell "Guests will be #{hunger}" end

def general_thirst_level thirst PersonalAssistant.tell "Guests will #{thirst} beer" unless thirst == 'none' end

def submit_request_for_estimate PersonalAssistant.ask "How much do I need?" end

def verify_pizzas_needed num_pies expect(PersonalAssistant.guess_pizza).to eq(num_pies) end

def verify_beer_needed beer_text expect(PersonalAssistant.guess_beer).to eq(beer_text) endend

Thursday, October 3, 13

Page 80: Object-Oriented BDD w/ Cucumber by Matt van Horn

SUMMARY

Keep  implementa9on  details  in  one  place

Use  objects  to  model  the  system

Use  abstrac9on  levels  to  scope  changes

Express  your  intent  throughout  the  code

Thursday, October 3, 13

Page 81: Object-Oriented BDD w/ Cucumber by Matt van Horn

QUESTIONS?

Thursday, October 3, 13

Page 82: Object-Oriented BDD w/ Cucumber by Matt van Horn

RESOURCESSource  Code:

github.com/maFvanhorn/pizza_beergithub.com/natritmeyer/site_prism

Further  Reading:mar9nfowler.com/bliki/PageObject.htmlblog.maFwynne.net/2012/11/20/tdd-­‐vs-­‐bdddannorth.net/2012/05/31/bdd-­‐is-­‐like-­‐tdd-­‐ifwww.elabs.se/blog/15-­‐you-­‐re-­‐cuking-­‐it-­‐wronggojko.net/2013/09/30/wri9ng-­‐as-­‐a-­‐user-­‐does-­‐not-­‐make-­‐it-­‐a-­‐user-­‐story

Contact  Me:web:  maFvanhorn.comgithub:  maFvanhorntwiFer:  @nycplayeremail:  mvanhorn@newrelic  or  [email protected]

Thursday, October 3, 13