SlideShare a Scribd company logo
1 of 85
Cucumber
collaboration   language
discussion      value
customers       acceptance


                             Joseph Wilk
Why are you here?
Why are you here?
In order ...
Why are you here?
In order ...
As a Underground attendee
Why are you here?
In order ...
As a Underground attendee
I want ...
Why are you here?
In order ...
As a Underground attendee
I want ...
                    I’ll show you a
                        good time
What’s your acceptance
       criteria?
Scenario: Ecstatic Underground attendees
 Given people turned up
 When Joseph talks
 Then everyone should learn something new
 And no-one should fall asleep
 And no cucumbers should be thrown
Pass
Fail
Pass
 Fail
How do you know
  your finished?
           You’ll know
            when I’m
             finished
Outside-in
    User
   Browser
Outside-in
    User
   Browser

   Views
Outside-in
     User
   Browser

    Views


  Controllers
   Models
“I believe that the hardest part of software projects, the
most common source of project failure, is
communication with the customers and users of
that software.

By providing a clear yet precise language to deal
with domains, a DSL can help improve this
communication.”

                                          Martin Fowler
def given_ruby_provides_a_great_dsl(*arg)
  developers.should be_happy
end

given_ruby_provides_a_great_dsl 'run away!'
def given_ruby_provides_a_great_dsl(*arg)
  developers.should be_happy
end

given_ruby_provides_a_great_dsl 'run away!'




                    Developer
Why do I
                          quote things?

                            Why can
Underscores!              I not use ‘ $




               Customer
Customer            Developer




           Tester
Customer            Developer




           Tester
Customer                    Developer



           Microsoft Word




                   Tester
Customer                 Developer



           Cucumber




                Tester
Customer                        Developer

           Plaintext     Ruby




                       Tester
For Cuke Sake Why?
• Token Conversation
• Acceptance Criteria
• Design
• Documentation
• Functional test
• Integration test
Cucumber Feature
             Feature: Be awesome          Not
               Narrative                executed
Example of
             Scenario: title
behaviour
                      which rocks
               Given <some context>
               And <yet more context>
               When <some action>
 Steps
               And <more actions>
               Then <some outcome>
               And <more outcomes>
Cucumber Feature
             Feature: Be awesome          Not
               Narrative                executed
Example of
             Scenario: title
behaviour
                      which rocks
               Given <some context>
               And <yet more context>
               When <some action>
 Steps
               And <more actions>
               Then <some outcome>
               And <more outcomes>
Plaintext




Ruby               Plaintext
       Plaintext


        Ruby
        Ruby
Plaintext

Step   Given a foaming cuke




              Ruby               Plaintext
                     Plaintext


                      Ruby
                      Ruby
Plaintext

  Step      Given a foaming cuke




                   Ruby               Plaintext
                          Plaintext
            Given /^a foaming (.*)$/i do |fruit|
  Step        fruit.should == 'cukes'
              #assert_equal(fruit, 'cukes')
definition   end

                           Ruby
                           Ruby
Plaintext

  Step      Given a foaming cuke




                                               regexp match
                   Ruby               Plaintext
                          Plaintext
            Given /^a foaming (.*)$/i do |fruit|
  Step        fruit.should == 'cukes'
              #assert_equal(fruit, 'cukes')
definition   end

                           Ruby
                           Ruby
Cucumber provides the
      venue

                       Sinatra




                        Rails
           Cuke4Duke
Cucumber Gateway?
                               World
                             domination?




                           Cucumber

    Java Virtual Machine




                                Clojure
Cucumber   English
Cucumber   English
огурец       Russian
concombre    French
             Japanese
Okurkový     Czech
Gurke        German
Cucumber     English
pepino       Spanish
cetriolo     Italian
agurk        Danish
‫ﺍﳋﻴﺎﺭ‬        Arabic
ketimun      Indonesian
‫מְלָפְפֹון‬   Hebrew
Cogombre     Catalan
CUCUMBR      LOLCats
Agurk        Norwegian
огурец       Russian                     Korean
concombre    French
                          gurka          Swedish
             Japanese
                          castravete     Romanian
Okurkový     Czech
                          ogórek         Polish
Gurke        German
Cucumber     English      Kurk           Estonian
pepino       Spanish      dưa chuột      Vietnamese
cetriolo     Italian      uhorka         Slovak
agurk        Danish       gurķis         Latvian
‫ﺍﳋﻴﺎﺭ‬        Arabic       Agurkas        Lithuanian
ketimun      Indonesian   Salátauborka   Hungarian
‫מְלָפְפֹון‬   Hebrew
                          Kurkku         Finnish
Cogombre     Catalan
                          Краставица     Bulgarian
CUCUMBR      LOLCats
Agurk        Norwegian    Pepino         Portuguese
# language: en-au
Crikey: Eating

  Mate: cucumbers
    Ya now how I have 3 cucumbers
    When I eat 2 cucumbers
    Ya gotta have 2 cucumbers in the belly
    N I have 1 cucumber left



YaNowHow /^I have (d+) cucumbers$/ do |n|
  @basket = Basket.new(n.to_i)
end

When /^I eat (d+) cucumbers$/ do |n|
  @belly = Belly.new
  @belly.eat(@basket.take(n.to_i))
end

YaGotta /^have (d+) cucumbers in the belly$/ do |n|
  @belly.cukes.should == n.to_i
end
How Cucumber
supports 28+ languages
How Cucumber
     supports 28+ languages


grammar Feature
  ...
end
How Cucumber
       supports 28+ languages


grammar Feature
  ...
end


compiled



       Ruby
How Cucumber
       supports 28+ languages


grammar Feature   grammar <%= keywords('grammar_name', true) %>
  ...               rule step_keyword
end                   (<%= keywords('given') %>) /
                      (<%= keywords('when') %>) /
                      (<%= keywords('then') %>) /
compiled
                      (<%= keywords('and') %>) /
                      (<%= keywords('but') %>)
                    end
       Ruby         ...
                  end
"en-lol":                          "en-au":
  name: LOLCAT                       name: Australian
  native: LOLCAT                     native: Australian
  encoding: UTF-8                    encoding: UTF-8
  feature: OH HAI                    feature: Crikey
  background: B4                     background: Background
  scenario: MISHUN                   scenario: Mate
  scenario_outline: MISHUN SRSLY     scenario_outline: Blokes
  examples: EXAMPLZ                  examples: Cobber
  given: I CAN HAZ                   given: Ya know how
  when: WEN                          when: When
  then: DEN                          then: Ya gotta
  and: AN                            and: N
  but: BUT                           but: Cept
  space_after_keyword: true          space_after_keyword: true
Webrat
 Love
visit home_path
click_link "Web"
fill_in "Email", :with => "Rat”
click_button "Love"
                                 Bansky
Once more
    unto the breach,
      dear friends
brace yourself
§
Feature Request
I want members to be able to
rent a movie with a priority
indicating how much they
want to see the film
Talk
                   to me




Token for Conversation
Story

Story: Film Member selects a movie to rent with priority
  As a Film member
  I want to add movies to my rental list with a priority
  So that ...
Story

Story: Film Member selects a movie to rent with priority
  As a Film member
  I want to add movies to my rental list with a priority
  So that ...




          Give me the movie
               NOW!
Feature Injection

Feature: Film Member selects a movie to rent with priority
  In order to maximise allocation of films
  The Stock department
  Wants Film members to add movies to their rental list with
  a priority
Feature Injection
Value
        Feature: Film Member selects a movie to rent with priority
          In order to maximise allocation of films
          The Stock department
          Wants Film members to add movies to their rental list with
          a priority
Feature Injection
Value
        Feature: Film Member selects a movie to rent with priority
          In order to maximise allocation of films
          The Stock department
          Wants Film members to add movies to their rental list with
Role      a priority
Feature Injection
Value
        Feature: Film Member selects a movie to rent with priority
          In order to maximise allocation of films
          The Stock department
          Wants Film members to add movies to their rental list with
Role      a priority



                          Role
Feature Injection
Value
        Feature: Film Member selects a movie to rent with priority
          In order to maximise allocation of films
          The Stock department
          Wants Film members to add movies to their rental list with
Role      a priority



                          Role                                Feature
Are we


   Acceptance
                     done yet?




Definition of Done.
Scenarios
Feature: Film Member selects a movie to rent with priority
  In order to maximise allocation of films
  The Stock department
  Wants Film members to add movies to their rental list with
  a priority

  Scenario: High priority
Scenarios
Feature: Film Member selects a movie to rent with priority
  In order to maximise allocation of films
  The Stock department
  Wants Film members to add movies to their rental list with
  a priority

  Scenario: High priority
   Given I'm logged in
   And I am viewing the movie "Casshern"
   When I choose "High priority"
   And I press "Rent"
   Then I should see "My rental list"
   And I should see "Casshern" in my rental list
   And "Casshern" should be marked as "High priority"
http://iphonemockup.lkmc.ch
Cuking time

   About
cuking time!
High Res: http://www.screencast.com/t/HbvPTbGy

   Low Res: http://www.vimeo.com/5751831
Here’s one I Cuked
      earlier

 Tasty
High Res: http://www.screencast.com/t/2E4nfzXotZ

    Low Res: http://www.vimeo.com/5751873
Getting Customers
 using Cucumber
Getting Customers
 using Cucumber

           I don’t
            bite
The Art of
       War Plaintext
                   ,                                               ,
                  @"===,                                  ,_____cctI
                  "?AAAAAAAAAAAAAAAA,,,,,,,,,,,,,,,,,,,,,;LLLLLLLLLL
       ~",,,       1""""""""""""###OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO
        '"EEEEE, !'"***"~~~~~~"OOOIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII
           ,EEEEE)>"'''???????"WWW!MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
             "E.,)+="WWW~~~~~~#"OOO1OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO
         ,~:#")LLL!"+++???????"$$$1==========##/
          &LLLLLLLLL;;;;;;;;;;;;,,,/
          1#LLLLLLLLLLLLLLLLLLLLLL!
        ,!###LLLLLL"'EEEE,'"LLLLL!
        !######LLL" "EEE" "LLLL"
       !#########L!    "EEJ. "LL!
      !##########1       "JJ*,l"
    !############"!         ,l"
    1##########" 1"~~,~~"
   !##########"
  !###########!
  !###########1
 !############!
 1#############
!"#############"
!##############!
1##########"'                               A magnum, By calendron
1#####"'
"""""
Don’t force
              Feature: Title
                In order to <value>
                As a <role>

 structure      I want <feature>
Avoid Noise!
               Given I am able to login
               Given I am able to login
Avoid       Given I login
                Given I authenticate

Inconsistency   Given I gain access
Given   I go to the login page


 Balance
              And I   fill in "username" with "cuke"
              And I   fill in "password" with "cuker"
              And I   click "login"

Abstraction   Given I'm logged in
Use Language
               Building blocks
Given /I’m logged in/ do
  User.create!(:user => 'josephwilk', :password => "pass")
  Given 'I fill in "password" with "josephwilk"'
  Given 'I fill in "password" with "pass"'
  Given 'I click "login"'
end
Email        Email-spec

Webpages     Webrat

Forms        Webrat




Java/Swing   Swinger
Gherkin Metrics?
             Lack of narrative
# language: en-au
Crikey: Eating

  Mate: cucumbers                            Number
    Ya now how I have 3 cucumbers
    When I eat 2 cucumbers                   of steps
    Ya gotta have 2 cucumbers in the belly
    N I have 1 cucumber left




Number of                   Semantically
noise words                similar words
Need for SPEED


Slick wheels!
Spork
require 'rubygems'
require 'spork'

# Sets up the Rails environment for Cucumber
ENV["RAILS_ENV"] ||= "cucumber"

Spork.prefork do
                                                   $ spork cuc
  # Load all the heavy stuff...
end

Spork.each_run do
                                               $ cucumber --drb ...
  # Load the stuff just for this run...

  Before do
    Pages.delete_all
  end
end
Scaling - TestJour

                        slaves


    master




             features


                                 Bonjour
Need for speed
 Webrat 0.8



Celerity                                   12




  Watir                                    12




Selenium                                    12.9


           0   3.75        7.5       11.25         15
                 start-up time (seconds)
Tagging
Eye   Head

         Teeth
        Foam
        Dribble
Tagging
Feature: Verify billing

 @javascript
 Scenario: Missing product description

  Scenario: Several products




 $ cucumber --tags ~@javascript

 $ cucumber --tags @javascript
Tag Hooks             Before(‘@teleport’) do
                        teleport.prepare
Attach code to tags   end
Focused Testing
                          @teleport
                          Feature: Invent teleportation


  Run just enough tests   @money
                          Feature: Make lots of money
Continuous Integration(WIP)
    Fail
  Work in    Pass
             Done
  Pending
  progress

    add       list    $ cucumber --wip
   movies    movies
                                 --tags @WIP
                                 features/
    edit
   movies


   delete
   movies
Limiting Tags in Flow
   Work in
                    Done
   progress

 add add add add
movies movies
   movies movies           $ cucumber --tags @WIP:3
                                      features/
 add add add edit
movies movies
   movies movies                              limit 3 tags


 add add add
           delete
movies movies
   movies movies
Avoiding Unrealistic expectations
Further reading

•   http://cukes.info

•   http://wiki.github.com/
    aslakhellesoy/cucumber

•   http://blog.josephwilk.net
Thanks,
                           Call me
                          sometime



                      joe@josephwilk.net
             http://github.com/josephwilk
http://github.com/aslakhellesoy/cucumber

More Related Content

What's hot

Hybrid Web Applications
Hybrid Web ApplicationsHybrid Web Applications
Hybrid Web ApplicationsJames Da Costa
 
BDD with Behat and Symfony2
BDD with Behat and Symfony2BDD with Behat and Symfony2
BDD with Behat and Symfony2katalisha
 
Selenium Sandwich Part 1: Data driven Selenium
Selenium Sandwich Part 1: Data driven Selenium Selenium Sandwich Part 1: Data driven Selenium
Selenium Sandwich Part 1: Data driven Selenium Workhorse Computing
 
You're Doing It Wrong
You're Doing It WrongYou're Doing It Wrong
You're Doing It Wrongbostonrb
 
Copycopter Presentation by Joe Ferris at BostonRB
Copycopter Presentation by Joe Ferris at BostonRBCopycopter Presentation by Joe Ferris at BostonRB
Copycopter Presentation by Joe Ferris at BostonRBbostonrb
 
Behat - Drupal South 2018
Behat  - Drupal South 2018Behat  - Drupal South 2018
Behat - Drupal South 2018Berend de Boer
 
"Managing API Complexity". Matthew Flaming, Temboo
"Managing API Complexity". Matthew Flaming, Temboo"Managing API Complexity". Matthew Flaming, Temboo
"Managing API Complexity". Matthew Flaming, TembooYandex
 
Behaviour driven infrastructure
Behaviour driven infrastructureBehaviour driven infrastructure
Behaviour driven infrastructureLindsay Holmwood
 
5 Reasons To Love CodeIgniter
5 Reasons To Love CodeIgniter5 Reasons To Love CodeIgniter
5 Reasons To Love CodeIgniternicdev
 
Testing web APIs
Testing web APIsTesting web APIs
Testing web APIsFDConf
 
So, you want to be a plugin developer?
So, you want to be a plugin developer?So, you want to be a plugin developer?
So, you want to be a plugin developer?ylefebvre
 
What you can do In WatiR
What you can do In WatiRWhat you can do In WatiR
What you can do In WatiRWesley Chen
 
Drupal8 Front-end Automated Testing
Drupal8 Front-end Automated TestingDrupal8 Front-end Automated Testing
Drupal8 Front-end Automated TestingRuben Teijeiro
 

What's hot (19)

Hybrid Web Applications
Hybrid Web ApplicationsHybrid Web Applications
Hybrid Web Applications
 
RSpec 2 Best practices
RSpec 2 Best practicesRSpec 2 Best practices
RSpec 2 Best practices
 
BDD with Behat and Symfony2
BDD with Behat and Symfony2BDD with Behat and Symfony2
BDD with Behat and Symfony2
 
Selenium Sandwich Part 1: Data driven Selenium
Selenium Sandwich Part 1: Data driven Selenium Selenium Sandwich Part 1: Data driven Selenium
Selenium Sandwich Part 1: Data driven Selenium
 
You're Doing It Wrong
You're Doing It WrongYou're Doing It Wrong
You're Doing It Wrong
 
Cucumber testing
Cucumber testingCucumber testing
Cucumber testing
 
Copycopter Presentation by Joe Ferris at BostonRB
Copycopter Presentation by Joe Ferris at BostonRBCopycopter Presentation by Joe Ferris at BostonRB
Copycopter Presentation by Joe Ferris at BostonRB
 
Selenium sandwich-2
Selenium sandwich-2Selenium sandwich-2
Selenium sandwich-2
 
Behat - Drupal South 2018
Behat  - Drupal South 2018Behat  - Drupal South 2018
Behat - Drupal South 2018
 
"Managing API Complexity". Matthew Flaming, Temboo
"Managing API Complexity". Matthew Flaming, Temboo"Managing API Complexity". Matthew Flaming, Temboo
"Managing API Complexity". Matthew Flaming, Temboo
 
Behaviour driven infrastructure
Behaviour driven infrastructureBehaviour driven infrastructure
Behaviour driven infrastructure
 
5 Reasons To Love CodeIgniter
5 Reasons To Love CodeIgniter5 Reasons To Love CodeIgniter
5 Reasons To Love CodeIgniter
 
I Love codeigniter, You?
I Love codeigniter, You?I Love codeigniter, You?
I Love codeigniter, You?
 
Testing web APIs
Testing web APIsTesting web APIs
Testing web APIs
 
So, you want to be a plugin developer?
So, you want to be a plugin developer?So, you want to be a plugin developer?
So, you want to be a plugin developer?
 
What you can do In WatiR
What you can do In WatiRWhat you can do In WatiR
What you can do In WatiR
 
Qpsmtpd
QpsmtpdQpsmtpd
Qpsmtpd
 
Drupal8 Front-end Automated Testing
Drupal8 Front-end Automated TestingDrupal8 Front-end Automated Testing
Drupal8 Front-end Automated Testing
 
Code smells in PHP
Code smells in PHPCode smells in PHP
Code smells in PHP
 

Similar to Here is a draft acceptance criteria for the feature:Scenario: Film member selects movie to rent with priority Given the film member has an account And there are movies available to rent When the member selects a movie And assigns it a priority of "High", "Medium", or "Low" Then the movie is added to their rental list And the priority is recordedScenario: Movies allocated by priority Given there are members with rental requests And some requests have "High" priority And some have "Medium" And some have "Low" When movies become available to allocate Then movies are allocated to "High" priority requests first And then "Medium" And then "Low

Cucumber: 小黃瓜驗收測試工具
Cucumber: 小黃瓜驗收測試工具Cucumber: 小黃瓜驗收測試工具
Cucumber: 小黃瓜驗收測試工具Wen-Tien Chang
 
Rocket Fuelled Cucumbers
Rocket Fuelled CucumbersRocket Fuelled Cucumbers
Rocket Fuelled CucumbersJoseph Wilk
 
Behavior driven development with calabash for android
Behavior driven development with calabash for androidBehavior driven development with calabash for android
Behavior driven development with calabash for androidTeresa Holfeld
 
Behaviour driven development present
Behaviour driven development presentBehaviour driven development present
Behaviour driven development presentRaul Panjiyar
 
CoffeeScript-Ruby-Tuesday
CoffeeScript-Ruby-TuesdayCoffeeScript-Ruby-Tuesday
CoffeeScript-Ruby-TuesdayEddie Kao
 
Testing with Docker
Testing with DockerTesting with Docker
Testing with Dockertoffermann
 
Ruby for PHP developers
Ruby for PHP developersRuby for PHP developers
Ruby for PHP developersMax Titov
 
Javascriptbootcamp
JavascriptbootcampJavascriptbootcamp
Javascriptbootcamposcon2007
 
Ruby for .NET developers
Ruby for .NET developersRuby for .NET developers
Ruby for .NET developersMax Titov
 
Ruby Programming Language - Introduction
Ruby Programming Language - IntroductionRuby Programming Language - Introduction
Ruby Programming Language - IntroductionKwangshin Oh
 
ManagingPuppetConf 2017: Multiple Configuration Management Tools- Sally Lehma...
ManagingPuppetConf 2017: Multiple Configuration Management Tools- Sally Lehma...ManagingPuppetConf 2017: Multiple Configuration Management Tools- Sally Lehma...
ManagingPuppetConf 2017: Multiple Configuration Management Tools- Sally Lehma...Puppet
 
Happy Programming with CoffeeScript
Happy Programming with CoffeeScriptHappy Programming with CoffeeScript
Happy Programming with CoffeeScriptEddie Kao
 
Testing outside of the Ruby World
Testing outside of the Ruby WorldTesting outside of the Ruby World
Testing outside of the Ruby WorldJoseph Wilk
 

Similar to Here is a draft acceptance criteria for the feature:Scenario: Film member selects movie to rent with priority Given the film member has an account And there are movies available to rent When the member selects a movie And assigns it a priority of "High", "Medium", or "Low" Then the movie is added to their rental list And the priority is recordedScenario: Movies allocated by priority Given there are members with rental requests And some requests have "High" priority And some have "Medium" And some have "Low" When movies become available to allocate Then movies are allocated to "High" priority requests first And then "Medium" And then "Low (20)

Cucumbered
CucumberedCucumbered
Cucumbered
 
Cucumber: 小黃瓜驗收測試工具
Cucumber: 小黃瓜驗收測試工具Cucumber: 小黃瓜驗收測試工具
Cucumber: 小黃瓜驗收測試工具
 
Spa2011
Spa2011Spa2011
Spa2011
 
Rocket Fuelled Cucumbers
Rocket Fuelled CucumbersRocket Fuelled Cucumbers
Rocket Fuelled Cucumbers
 
Behavior driven development with calabash for android
Behavior driven development with calabash for androidBehavior driven development with calabash for android
Behavior driven development with calabash for android
 
Behaviour driven development present
Behaviour driven development presentBehaviour driven development present
Behaviour driven development present
 
CoffeeScript-Ruby-Tuesday
CoffeeScript-Ruby-TuesdayCoffeeScript-Ruby-Tuesday
CoffeeScript-Ruby-Tuesday
 
Ruby Kaigi 2008 LT
Ruby Kaigi 2008 LTRuby Kaigi 2008 LT
Ruby Kaigi 2008 LT
 
Testing with Docker
Testing with DockerTesting with Docker
Testing with Docker
 
Ruby for PHP developers
Ruby for PHP developersRuby for PHP developers
Ruby for PHP developers
 
Cucumber & BDD
Cucumber & BDDCucumber & BDD
Cucumber & BDD
 
Javascriptbootcamp
JavascriptbootcampJavascriptbootcamp
Javascriptbootcamp
 
Ruby for .NET developers
Ruby for .NET developersRuby for .NET developers
Ruby for .NET developers
 
Smalltalk on rubinius
Smalltalk on rubiniusSmalltalk on rubinius
Smalltalk on rubinius
 
Cucumber
CucumberCucumber
Cucumber
 
Ruby Programming Language - Introduction
Ruby Programming Language - IntroductionRuby Programming Language - Introduction
Ruby Programming Language - Introduction
 
ManagingPuppetConf 2017: Multiple Configuration Management Tools- Sally Lehma...
ManagingPuppetConf 2017: Multiple Configuration Management Tools- Sally Lehma...ManagingPuppetConf 2017: Multiple Configuration Management Tools- Sally Lehma...
ManagingPuppetConf 2017: Multiple Configuration Management Tools- Sally Lehma...
 
Cucumber testing
Cucumber testingCucumber testing
Cucumber testing
 
Happy Programming with CoffeeScript
Happy Programming with CoffeeScriptHappy Programming with CoffeeScript
Happy Programming with CoffeeScript
 
Testing outside of the Ruby World
Testing outside of the Ruby WorldTesting outside of the Ruby World
Testing outside of the Ruby World
 

More from Joseph Wilk

Acceptance testing in the land of the startup
Acceptance testing in the land of the startup Acceptance testing in the land of the startup
Acceptance testing in the land of the startup Joseph Wilk
 
Rubykaigi 2011 Limited Red talk
Rubykaigi 2011 Limited Red talkRubykaigi 2011 Limited Red talk
Rubykaigi 2011 Limited Red talkJoseph Wilk
 
The Limited Red Society
The Limited Red SocietyThe Limited Red Society
The Limited Red SocietyJoseph Wilk
 
The Limited Red Society
The Limited Red Society The Limited Red Society
The Limited Red Society Joseph Wilk
 
Rubyconf lightning talk
Rubyconf lightning talkRubyconf lightning talk
Rubyconf lightning talkJoseph Wilk
 
Acceptance testing in the land of the startup
Acceptance testing in the land of the startupAcceptance testing in the land of the startup
Acceptance testing in the land of the startupJoseph Wilk
 
Cucumber Patterns Workshop
Cucumber Patterns WorkshopCucumber Patterns Workshop
Cucumber Patterns WorkshopJoseph Wilk
 
Dynamic Workflow Pulling the Strings
Dynamic Workflow Pulling the StringsDynamic Workflow Pulling the Strings
Dynamic Workflow Pulling the StringsJoseph Wilk
 
Testing with Ruby
Testing with RubyTesting with Ruby
Testing with RubyJoseph Wilk
 

More from Joseph Wilk (11)

Frozenrails2011
Frozenrails2011Frozenrails2011
Frozenrails2011
 
Acceptance testing in the land of the startup
Acceptance testing in the land of the startup Acceptance testing in the land of the startup
Acceptance testing in the land of the startup
 
Rubykaigi 2011 Limited Red talk
Rubykaigi 2011 Limited Red talkRubykaigi 2011 Limited Red talk
Rubykaigi 2011 Limited Red talk
 
The Limited Red Society
The Limited Red SocietyThe Limited Red Society
The Limited Red Society
 
The Limited Red Society
The Limited Red Society The Limited Red Society
The Limited Red Society
 
Rubyconf lightning talk
Rubyconf lightning talkRubyconf lightning talk
Rubyconf lightning talk
 
Acceptance testing in the land of the startup
Acceptance testing in the land of the startupAcceptance testing in the land of the startup
Acceptance testing in the land of the startup
 
Cucumber Patterns Workshop
Cucumber Patterns WorkshopCucumber Patterns Workshop
Cucumber Patterns Workshop
 
Musichackday
MusichackdayMusichackday
Musichackday
 
Dynamic Workflow Pulling the Strings
Dynamic Workflow Pulling the StringsDynamic Workflow Pulling the Strings
Dynamic Workflow Pulling the Strings
 
Testing with Ruby
Testing with RubyTesting with Ruby
Testing with Ruby
 

Recently uploaded

Dev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebDev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebUiPathCommunity
 
WordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your BrandWordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your Brandgvaughan
 
TrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data PrivacyTrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data PrivacyTrustArc
 
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024BookNet Canada
 
From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .Alan Dix
 
Moving Beyond Passwords: FIDO Paris Seminar.pdf
Moving Beyond Passwords: FIDO Paris Seminar.pdfMoving Beyond Passwords: FIDO Paris Seminar.pdf
Moving Beyond Passwords: FIDO Paris Seminar.pdfLoriGlavin3
 
Time Series Foundation Models - current state and future directions
Time Series Foundation Models - current state and future directionsTime Series Foundation Models - current state and future directions
Time Series Foundation Models - current state and future directionsNathaniel Shimoni
 
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024BookNet Canada
 
Advanced Computer Architecture – An Introduction
Advanced Computer Architecture – An IntroductionAdvanced Computer Architecture – An Introduction
Advanced Computer Architecture – An IntroductionDilum Bandara
 
"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr BaganFwdays
 
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptxThe Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptxLoriGlavin3
 
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek SchlawackFwdays
 
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptx
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptxPasskey Providers and Enabling Portability: FIDO Paris Seminar.pptx
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptxLoriGlavin3
 
DevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsDevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsSergiu Bodiu
 
Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!Manik S Magar
 
How to write a Business Continuity Plan
How to write a Business Continuity PlanHow to write a Business Continuity Plan
How to write a Business Continuity PlanDatabarracks
 
Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 365Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 3652toLead Limited
 
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptxUse of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptxLoriGlavin3
 
unit 4 immunoblotting technique complete.pptx
unit 4 immunoblotting technique complete.pptxunit 4 immunoblotting technique complete.pptx
unit 4 immunoblotting technique complete.pptxBkGupta21
 
SALESFORCE EDUCATION CLOUD | FEXLE SERVICES
SALESFORCE EDUCATION CLOUD | FEXLE SERVICESSALESFORCE EDUCATION CLOUD | FEXLE SERVICES
SALESFORCE EDUCATION CLOUD | FEXLE SERVICESmohitsingh558521
 

Recently uploaded (20)

Dev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebDev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio Web
 
WordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your BrandWordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your Brand
 
TrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data PrivacyTrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data Privacy
 
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
 
From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .
 
Moving Beyond Passwords: FIDO Paris Seminar.pdf
Moving Beyond Passwords: FIDO Paris Seminar.pdfMoving Beyond Passwords: FIDO Paris Seminar.pdf
Moving Beyond Passwords: FIDO Paris Seminar.pdf
 
Time Series Foundation Models - current state and future directions
Time Series Foundation Models - current state and future directionsTime Series Foundation Models - current state and future directions
Time Series Foundation Models - current state and future directions
 
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
 
Advanced Computer Architecture – An Introduction
Advanced Computer Architecture – An IntroductionAdvanced Computer Architecture – An Introduction
Advanced Computer Architecture – An Introduction
 
"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan
 
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptxThe Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
 
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
 
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptx
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptxPasskey Providers and Enabling Portability: FIDO Paris Seminar.pptx
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptx
 
DevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsDevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platforms
 
Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!
 
How to write a Business Continuity Plan
How to write a Business Continuity PlanHow to write a Business Continuity Plan
How to write a Business Continuity Plan
 
Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 365Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 365
 
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptxUse of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
 
unit 4 immunoblotting technique complete.pptx
unit 4 immunoblotting technique complete.pptxunit 4 immunoblotting technique complete.pptx
unit 4 immunoblotting technique complete.pptx
 
SALESFORCE EDUCATION CLOUD | FEXLE SERVICES
SALESFORCE EDUCATION CLOUD | FEXLE SERVICESSALESFORCE EDUCATION CLOUD | FEXLE SERVICES
SALESFORCE EDUCATION CLOUD | FEXLE SERVICES
 

Here is a draft acceptance criteria for the feature:Scenario: Film member selects movie to rent with priority Given the film member has an account And there are movies available to rent When the member selects a movie And assigns it a priority of "High", "Medium", or "Low" Then the movie is added to their rental list And the priority is recordedScenario: Movies allocated by priority Given there are members with rental requests And some requests have "High" priority And some have "Medium" And some have "Low" When movies become available to allocate Then movies are allocated to "High" priority requests first And then "Medium" And then "Low

  • 1. Cucumber collaboration language discussion value customers acceptance Joseph Wilk
  • 2. Why are you here?
  • 3. Why are you here? In order ...
  • 4. Why are you here? In order ... As a Underground attendee
  • 5. Why are you here? In order ... As a Underground attendee I want ...
  • 6. Why are you here? In order ... As a Underground attendee I want ... I’ll show you a good time
  • 8. Scenario: Ecstatic Underground attendees Given people turned up When Joseph talks Then everyone should learn something new And no-one should fall asleep And no cucumbers should be thrown
  • 11. How do you know your finished? You’ll know when I’m finished
  • 12. Outside-in User Browser
  • 13. Outside-in User Browser Views
  • 14. Outside-in User Browser Views Controllers Models
  • 15. “I believe that the hardest part of software projects, the most common source of project failure, is communication with the customers and users of that software. By providing a clear yet precise language to deal with domains, a DSL can help improve this communication.” Martin Fowler
  • 16. def given_ruby_provides_a_great_dsl(*arg) developers.should be_happy end given_ruby_provides_a_great_dsl 'run away!'
  • 17. def given_ruby_provides_a_great_dsl(*arg) developers.should be_happy end given_ruby_provides_a_great_dsl 'run away!' Developer
  • 18. Why do I quote things? Why can Underscores! I not use ‘ $ Customer
  • 19. Customer Developer Tester
  • 20. Customer Developer Tester
  • 21. Customer Developer Microsoft Word Tester
  • 22. Customer Developer Cucumber Tester
  • 23. Customer Developer Plaintext Ruby Tester
  • 24. For Cuke Sake Why? • Token Conversation • Acceptance Criteria • Design • Documentation • Functional test • Integration test
  • 25. Cucumber Feature Feature: Be awesome Not Narrative executed Example of Scenario: title behaviour which rocks Given <some context> And <yet more context> When <some action> Steps And <more actions> Then <some outcome> And <more outcomes>
  • 26. Cucumber Feature Feature: Be awesome Not Narrative executed Example of Scenario: title behaviour which rocks Given <some context> And <yet more context> When <some action> Steps And <more actions> Then <some outcome> And <more outcomes>
  • 27. Plaintext Ruby Plaintext Plaintext Ruby Ruby
  • 28. Plaintext Step Given a foaming cuke Ruby Plaintext Plaintext Ruby Ruby
  • 29. Plaintext Step Given a foaming cuke Ruby Plaintext Plaintext Given /^a foaming (.*)$/i do |fruit| Step fruit.should == 'cukes' #assert_equal(fruit, 'cukes') definition end Ruby Ruby
  • 30. Plaintext Step Given a foaming cuke regexp match Ruby Plaintext Plaintext Given /^a foaming (.*)$/i do |fruit| Step fruit.should == 'cukes' #assert_equal(fruit, 'cukes') definition end Ruby Ruby
  • 31. Cucumber provides the venue Sinatra Rails Cuke4Duke
  • 32. Cucumber Gateway? World domination? Cucumber Java Virtual Machine Clojure
  • 33. Cucumber English
  • 34. Cucumber English
  • 35. огурец Russian concombre French Japanese Okurkový Czech Gurke German Cucumber English pepino Spanish cetriolo Italian agurk Danish ‫ﺍﳋﻴﺎﺭ‬ Arabic ketimun Indonesian ‫מְלָפְפֹון‬ Hebrew Cogombre Catalan CUCUMBR LOLCats Agurk Norwegian
  • 36. огурец Russian Korean concombre French gurka Swedish Japanese castravete Romanian Okurkový Czech ogórek Polish Gurke German Cucumber English Kurk Estonian pepino Spanish dưa chuột Vietnamese cetriolo Italian uhorka Slovak agurk Danish gurķis Latvian ‫ﺍﳋﻴﺎﺭ‬ Arabic Agurkas Lithuanian ketimun Indonesian Salátauborka Hungarian ‫מְלָפְפֹון‬ Hebrew Kurkku Finnish Cogombre Catalan Краставица Bulgarian CUCUMBR LOLCats Agurk Norwegian Pepino Portuguese
  • 37. # language: en-au Crikey: Eating Mate: cucumbers Ya now how I have 3 cucumbers When I eat 2 cucumbers Ya gotta have 2 cucumbers in the belly N I have 1 cucumber left YaNowHow /^I have (d+) cucumbers$/ do |n| @basket = Basket.new(n.to_i) end When /^I eat (d+) cucumbers$/ do |n| @belly = Belly.new @belly.eat(@basket.take(n.to_i)) end YaGotta /^have (d+) cucumbers in the belly$/ do |n| @belly.cukes.should == n.to_i end
  • 39. How Cucumber supports 28+ languages grammar Feature ... end
  • 40. How Cucumber supports 28+ languages grammar Feature ... end compiled Ruby
  • 41. How Cucumber supports 28+ languages grammar Feature grammar <%= keywords('grammar_name', true) %> ... rule step_keyword end (<%= keywords('given') %>) / (<%= keywords('when') %>) / (<%= keywords('then') %>) / compiled (<%= keywords('and') %>) / (<%= keywords('but') %>) end Ruby ... end
  • 42. "en-lol": "en-au": name: LOLCAT name: Australian native: LOLCAT native: Australian encoding: UTF-8 encoding: UTF-8 feature: OH HAI feature: Crikey background: B4 background: Background scenario: MISHUN scenario: Mate scenario_outline: MISHUN SRSLY scenario_outline: Blokes examples: EXAMPLZ examples: Cobber given: I CAN HAZ given: Ya know how when: WEN when: When then: DEN then: Ya gotta and: AN and: N but: BUT but: Cept space_after_keyword: true space_after_keyword: true
  • 43. Webrat Love visit home_path click_link "Web" fill_in "Email", :with => "Rat” click_button "Love" Bansky
  • 44. Once more unto the breach, dear friends brace yourself
  • 45. §
  • 46. Feature Request I want members to be able to rent a movie with a priority indicating how much they want to see the film
  • 47. Talk to me Token for Conversation
  • 48. Story Story: Film Member selects a movie to rent with priority As a Film member I want to add movies to my rental list with a priority So that ...
  • 49. Story Story: Film Member selects a movie to rent with priority As a Film member I want to add movies to my rental list with a priority So that ... Give me the movie NOW!
  • 50. Feature Injection Feature: Film Member selects a movie to rent with priority In order to maximise allocation of films The Stock department Wants Film members to add movies to their rental list with a priority
  • 51. Feature Injection Value Feature: Film Member selects a movie to rent with priority In order to maximise allocation of films The Stock department Wants Film members to add movies to their rental list with a priority
  • 52. Feature Injection Value Feature: Film Member selects a movie to rent with priority In order to maximise allocation of films The Stock department Wants Film members to add movies to their rental list with Role a priority
  • 53. Feature Injection Value Feature: Film Member selects a movie to rent with priority In order to maximise allocation of films The Stock department Wants Film members to add movies to their rental list with Role a priority Role
  • 54. Feature Injection Value Feature: Film Member selects a movie to rent with priority In order to maximise allocation of films The Stock department Wants Film members to add movies to their rental list with Role a priority Role Feature
  • 55. Are we Acceptance done yet? Definition of Done.
  • 56. Scenarios Feature: Film Member selects a movie to rent with priority In order to maximise allocation of films The Stock department Wants Film members to add movies to their rental list with a priority Scenario: High priority
  • 57. Scenarios Feature: Film Member selects a movie to rent with priority In order to maximise allocation of films The Stock department Wants Film members to add movies to their rental list with a priority Scenario: High priority Given I'm logged in And I am viewing the movie "Casshern" When I choose "High priority" And I press "Rent" Then I should see "My rental list" And I should see "Casshern" in my rental list And "Casshern" should be marked as "High priority"
  • 59. Cuking time About cuking time!
  • 60. High Res: http://www.screencast.com/t/HbvPTbGy Low Res: http://www.vimeo.com/5751831
  • 61. Here’s one I Cuked earlier Tasty
  • 62. High Res: http://www.screencast.com/t/2E4nfzXotZ Low Res: http://www.vimeo.com/5751873
  • 64. Getting Customers using Cucumber I don’t bite
  • 65. The Art of War Plaintext , , @"===, ,_____cctI "?AAAAAAAAAAAAAAAA,,,,,,,,,,,,,,,,,,,,,;LLLLLLLLLL ~",,, 1""""""""""""###OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO '"EEEEE, !'"***"~~~~~~"OOOIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII ,EEEEE)>"'''???????"WWW!MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM "E.,)+="WWW~~~~~~#"OOO1OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO ,~:#")LLL!"+++???????"$$$1==========##/ &LLLLLLLLL;;;;;;;;;;;;,,,/ 1#LLLLLLLLLLLLLLLLLLLLLL! ,!###LLLLLL"'EEEE,'"LLLLL! !######LLL" "EEE" "LLLL" !#########L! "EEJ. "LL! !##########1 "JJ*,l" !############"! ,l" 1##########" 1"~~,~~" !##########" !###########! !###########1 !############! 1############# !"#############" !##############! 1##########"' A magnum, By calendron 1#####"' """""
  • 66. Don’t force Feature: Title In order to <value> As a <role> structure I want <feature>
  • 67. Avoid Noise! Given I am able to login Given I am able to login
  • 68. Avoid Given I login Given I authenticate Inconsistency Given I gain access
  • 69. Given I go to the login page Balance And I fill in "username" with "cuke" And I fill in "password" with "cuker" And I click "login" Abstraction Given I'm logged in
  • 70. Use Language Building blocks Given /I’m logged in/ do User.create!(:user => 'josephwilk', :password => "pass") Given 'I fill in "password" with "josephwilk"' Given 'I fill in "password" with "pass"' Given 'I click "login"' end
  • 71. Email Email-spec Webpages Webrat Forms Webrat Java/Swing Swinger
  • 72. Gherkin Metrics? Lack of narrative # language: en-au Crikey: Eating Mate: cucumbers Number Ya now how I have 3 cucumbers When I eat 2 cucumbers of steps Ya gotta have 2 cucumbers in the belly N I have 1 cucumber left Number of Semantically noise words similar words
  • 74. Spork require 'rubygems' require 'spork' # Sets up the Rails environment for Cucumber ENV["RAILS_ENV"] ||= "cucumber" Spork.prefork do $ spork cuc # Load all the heavy stuff... end Spork.each_run do $ cucumber --drb ... # Load the stuff just for this run... Before do Pages.delete_all end end
  • 75. Scaling - TestJour slaves master features Bonjour
  • 76. Need for speed Webrat 0.8 Celerity 12 Watir 12 Selenium 12.9 0 3.75 7.5 11.25 15 start-up time (seconds)
  • 77. Tagging Eye Head Teeth Foam Dribble
  • 78. Tagging Feature: Verify billing @javascript Scenario: Missing product description Scenario: Several products $ cucumber --tags ~@javascript $ cucumber --tags @javascript
  • 79. Tag Hooks Before(‘@teleport’) do teleport.prepare Attach code to tags end
  • 80. Focused Testing @teleport Feature: Invent teleportation Run just enough tests @money Feature: Make lots of money
  • 81. Continuous Integration(WIP) Fail Work in Pass Done Pending progress add list $ cucumber --wip movies movies --tags @WIP features/ edit movies delete movies
  • 82. Limiting Tags in Flow Work in Done progress add add add add movies movies movies movies $ cucumber --tags @WIP:3 features/ add add add edit movies movies movies movies limit 3 tags add add add delete movies movies movies movies
  • 84. Further reading • http://cukes.info • http://wiki.github.com/ aslakhellesoy/cucumber • http://blog.josephwilk.net
  • 85. Thanks, Call me sometime joe@josephwilk.net http://github.com/josephwilk http://github.com/aslakhellesoy/cucumber