Behaviour-driven
development with
   Cucumber
        Kerry Buckley
  BT DevCon6, 4 February 2013


       http://www.flickr.com/photos/yogendra174/4665988849
A developer tool for
end-to-end testing of
ruby web applications
A developer tool for
end-to-end testing of
ruby web applications
 LIE
Basics
Feature: DevCon talk
  In order to fill the DevCon6 schedule
  As a Cucumber user
  I want to talk about BDD with Cucumber

  Scenario: "BDD with Cucumber" talk
    Given I have managed to prepare a talk
    And there are people there to hear it
    When I give the talk
    Then the audience should learn something
Feature: DevCon talk
  In order to fill the DevCon6 schedule
  As a Cucumber user
  I want to talk about BDD with Cucumber

  Scenario: "BDD with Cucumber" talk
    Given I have managed to prepare a talk
    And there are people there to hear it
    When I give the talk
    Then the audience should learn something
Feature: DevCon talk
  In order to fill the DevCon6 schedule
  As a Cucumber user
  I want to talk about BDD with Cucumber

  Scenario: "BDD with Cucumber" talk
    Given I have managed to prepare a talk
    And there are people there to hear it
    When I give the talk
    Then the audience should learn something
Feature: DevCon talk
  In order to fill the DevCon6 schedule
  As a Cucumber user
  I want to talk about BDD with Cucumber

  Scenario: "BDD with Cucumber" talk
    Given I have managed to prepare a talk
    And there are people there to hear it
    When I give the talk
    Then the audience should learn something
Feature: DevCon talk
  In order to fill the DevCon6 schedule
  As a Cucumber user
  I want to talk about BDD with Cucumber

  Scenario: "BDD with Cucumber" talk
    Given I have managed to prepare a talk
    And there are people there to hear it
    When I give the talk
    Then the audience should learn something
Feature: Withdraw cash from account

  Scenario: Successful withdrawal
    Given I have £100 in my account
    When I request a withdrawal of £20
    Then I should receive £20
    And my balance should be £80
$ cucumber withdraw_cash.feature
Feature: Withdraw cash from account

  Scenario: Successful withdrawal        #   withdraw_cash.feature:3
    Given I have £100 in my account      #   withdraw_cash.feature:4
    When I request a withdrawal of £20   #   withdraw_cash.feature:5
    Then I should receive £20            #   withdraw_cash.feature:6
    And my balance should be £80         #   withdraw_cash.feature:7

1 scenario (1 undefined)
4 steps (4 undefined)
0m0.002s

You can implement step definitions for undefined steps with these snippets:

Given /^I have £(d+) in my account$/ do |arg1|
  pending # express the regexp above with the code you wish you had
end

...
Scenario: Successful login
  Given a user "Fred" with password "secret"
  When I go to the login page
  And I fill in "User name" with "Fred"
  And I fill in "Password" with "secret"
  And I press "Log in"
  Then I should see "Welcome, Fred"
Scenario: Adding a CaaS Linux Service in a production (or test) environment
  Given a fred production environment exists
  And I am on the last deployment page

  When I select "CaaS Linux Service" from "Add a new"
  And I press "Add service"
  And I fill in the following:
    | Role                           | FTP Server |
    | Application Installed Software | None       |
  And I select "SC3 (redside)" from "Security Domain"
  And I select "2" from "Virtual CPUs"
  And I select "2" from "Virtual Memory"
  And I select "OEL 5u6 32bit" from "Operating System"
  And I select "None" from "MaaS(EMB) MQ Client"
  And I select "None" from "Oracle Client"
  And I check "Netbackup Client"
  And I check "XFB Client"
  And I check "BT Hunter Client"
  And I check "BTBPTM Client"
  And I check "Web Tier"
  And I press "Save"

  Then I should be on the last deployment page
  And I should see "Service saved"
  And I should see ...
Scenario: Successful login
  Given a user "Fred" with password "secret"
  When I go to the login page
  And I fill in "User name" with "Fred"
  And I fill in "Password" with "secret"
  And I press "Log in"
  Then I should see "Welcome, Fred"
Scenario: User is greeted upon login
  Given the user "Fred" has an account
  When he logs in
  Then he should see "Welcome, Fred"
Given /^the user "(.*?)" has an account$/ do |name|
  @user = User.find_or_create_by_name name, password: "secret"
end

When /^he logs in$/ do
  visit "/login"
  fill_in "User name", with: @user.name
  fill_in "Password", with: @user.password
  click_button "Log in"
end

Then /^he should see "(.*?)"$/ do |text|
  page.should have_content(text)
end
Scenario: User is greeted upon login
  Given the user "Fred" has an account
  When he logs in
  Then he should see "Welcome, Fred"


Scenario: Secure pages require login
  When I visit a secure page as a guest
  Then I should be asked to log in

 When I log in with a valid account
 Then I should see the secure page
Feature: My awesome system

 Scenario: Using the system
   Given the system exists
   When I use it
   Then everything should work perfectly
A developer tool for
end-to-end testing
of web applications
A developer tool for
      LIE

end-to-end testing
of web applications
Scenario: create a dir
  Given a directory named "foo/bar"
  When I run `file foo/bar`
  Then the stdout should contain "foo/bar: directory"

Scenario: create a file
  Given a file named "foo/bar/example.txt" with:
    """
    hello world
    """
  When I run `cat foo/bar/example.txt`
  Then the output should contain exactly "hello world"
A tool for end-to-
end testing of web
   applications
A tool for end-to-
end testing of web
                 LIE
   applications
More feature
  … er …
 features
Feature: Posting messages to friends

 Scenario: Posting a text message
   Given I am logged in
   When I post a text message
   Then my friends should see my message

 Scenario: Posting a photo
   Given I am logged in
   When I post a photo
   Then my friends should see a thumbnail of my photo
   And clicking the thumbnail should show the photo
Feature: Posting messages to friends

 Scenario: Posting a text message
   Given I am logged in
   When I post a text message
   Then my friends should see my message

 Scenario: Posting a photo
   Given I am logged in
   When I post a photo
   Then my friends should see a thumbnail of my photo
   And clicking the thumbnail should show the photo
Feature: Posting messages to friends
  Background:
    Given I am logged in

 Scenario: Posting a text message
   When I post a text message
   Then my friends should see my message

 Scenario: Posting a photo
   When I post a photo
   Then my friends should see a thumbnail of my photo
   And clicking the thumbnail should show the photo
Scenario:
  When I add 1 widget to my order
  And I add 5 doodahs to my order
  And I add 2 thingummies to my order
  Then my basket total should be £12.34
Scenario:
  When I add the   following to my order:
    | Quantity |   Item      |
    | 1        |   widget    |
    | 5        |   doodah    |
    | 2        |   thingummy |
  Then my basket   total should be £12.34
Scenario: Simple addition
  When I calculate 2 + 2
  Then the answer should be 4

 When I calculate 10 + 5
 Then the answer should be 15

Scenario: Simple multiplication
  When I calculate 2 * 2
  Then the answer should be 4

 When I calculate 6 * 7
 Then the answer should be 42
Scenario Outline: Simple arithmetic
  When I calculate <first> <operation> <second>
  Then the answer should be <answer>

 Examples:
   | first   |   operation   |   second   |   answer   |
   | 2       |   +           |   2        |   4        |
   | 10      |   +           |   5        |   15       |
   | 2       |   *           |   2        |   4        |
   | 6       |   *           |   7        |   42       |
http://www.flickr.com/photos/yogendra174/4665988849
# language: fr
Fonctionnalité: Addition
  Afin de financer mon bonus avec l'argent des pigeons
  En tant que trader
  Je souhaite pouvoir additionner 2 chiffres

 Plan du Scénario: Addition de produits dérivés
   Soit une calculatrice
   Etant donné qu'on tape <a>
   Et qu'on tape <b>
   Lorsqu'on tape additionner
   Alors le résultat doit être <somme>

 Exemples:
   | a | b | somme |
   | 2 | 2 | 4     |
   | 2 | 3 | 5     |
# language: es
Característica: adición
  Para evitar hacer errores tontos
  Como un matemático idiota
  Quiero saber la suma de los números

 Esquema del escenario: Sumar dos números
   Dado que he introducido <entrada_1> en la calculadora
   Y que he introducido <entrada_2> en la calculadora
   Cuando oprimo el <botón>
   Entonces el resultado debe ser <resultado> en la pantalla

 Ejemplos:
   | entrada_1   |   entrada_2   |   botón   |   resultado   |
   | 20          |   30          |   add     |   50          |
   | 2           |   5           |   add     |   7           |
   | 0           |   40          |   add     |   40          |
# language: de
Funktionalität: Addition
  Um dumme Fehler zu vermeiden
  möchte ich als Matheidiot
  die Summe zweier Zahlen gesagt bekommen

 Szenariogrundriss: Zwei Zahlen hinzufügen
   Angenommen ich habe <Eingabe_1> in den Taschenrechner eingegeben
   Und ich habe <Eingabe_2> in den Taschenrechner eingegeben
   Wenn ich <Knopf> drücke
   Dann sollte das Ergebniss auf dem Bildschirm <Ausgabe> sein

 Beispiele:
   | Eingabe_1   |   Eingabe_2   |   Knopf   |   Ausgabe   |
   | 20          |   30          |   add     |   50        |
   | 2           |   5           |   add     |   7         |
   | 0           |   40          |   add     |   40        |
# language: en-lol
OH HAI: STUFFING

 MISHUN:   CUCUMBR
   I CAN   HAZ IN TEH BEGINNIN 3 CUCUMBRZ
   WEN I   EAT 2 CUCUMBRZ
   DEN I   HAS 2 CUCUMBERZ IN MAH BELLY
   AN IN   TEH END 1 CUCUMBRZ KTHXBAI
Getting the most
out of Cucumber
http://www.flickr.com/photos/oskay/2156888497
Given /^the user "(.*?)" has an account$/ do |name|
  @user = User.find_or_create_by_name name, password: "secret"
end

Given /^a logged-in user$/ do
  @user = User.find_or_create_by_name "Fred", password: "secret"
  visit "/login"
  fill_in "User name", :with => @user.name
  fill_in "Password", :with => @user.password
  click_button "Log in"
end

When /^he logs in$/ do
  visit "/login"
  fill_in "User name", with: @user.name
  fill_in "Password", with: @user.password
  click_button "Log in"
end

Then /^he should see "(.*?)"$/ do |text|
  page.should have_content(text)
end
Given /^the user "(.*?)" has an account$/ do |name|
  @user = User.find_or_create_by_name name, password: "secret"
end

Given /^a logged-in user$/ do
  @user = User.find_or_create_by_name "Fred", password: "secret"
  visit "/login"
  fill_in "User name", :with => @user.name
  fill_in "Password", :with => @user.password
  click_button "Log in"
end

When /^he logs in$/ do
  visit "/login"
  fill_in "User name", with: @user.name
  fill_in "Password", with: @user.password
  click_button "Log in"
end

Then /^he should see "(.*?)"$/ do |text|
  page.should have_content(text)
end
module LoginSteps
  def login(name, password)
    visit "/login"
    fill_in "User name", with: name
    fill_in "Password", with: password
    click_button "Log in"
  end
end

World(LoginSteps)

Given /^a logged in user$/ do
  @user = User.find_or_create_by_name name, password: "secret"
  login(@user.name, @user.password)
end

When /^he logs in$/ do
  login(@user.name, @user.password)
end
http://tooky.co.uk/2013/01/18/cucumber-and-full-stack-testing.html
http://blog.mattwynne.net/2012/05/31/hexagonal-rails-objects-values-and-hexagons/
A tool for
end-to-end testing
  of applications
A tool for
end-to-end testing
     LIE
  of applications
A tool for testing
  applications
A tool for testingRELY
               TI
  applications
        N
            EN HER
          OT EIT
            UE
         TR
http://www.flickr.com/photos/elycefeliz/3224486233
Made-up statistics

                        Identifying scenarios
                                 25%
   Automated tests
        35%




                     Agreeing steps
                         40%
$ cucumber talk.feature
Feature: DevCon talk
  In order to fill the DevCon6 schedule
  As a Cucumber user
  I want to talk about BDD with Cucumber

  Scenario: "BDD with Cucumber" talk                # talk.feature:6
    Given I have managed to prepare my talk on time # talk_steps.rb:1
    And there are people there to hear it           # talk_steps.rb:4
    When I give the talk                            # talk_steps.rb:7
    Then the audience should learn something        # talk_steps.rb:10

1 scenario (1 passed)
4 steps (4 passed)
0m0.002s
http://www.flickr.com/photos/erix/3780828260

BDD with cucumber

  • 1.
    Behaviour-driven development with Cucumber Kerry Buckley BT DevCon6, 4 February 2013 http://www.flickr.com/photos/yogendra174/4665988849
  • 3.
    A developer toolfor end-to-end testing of ruby web applications
  • 4.
    A developer toolfor end-to-end testing of ruby web applications LIE
  • 5.
  • 6.
    Feature: DevCon talk In order to fill the DevCon6 schedule As a Cucumber user I want to talk about BDD with Cucumber Scenario: "BDD with Cucumber" talk Given I have managed to prepare a talk And there are people there to hear it When I give the talk Then the audience should learn something
  • 7.
    Feature: DevCon talk In order to fill the DevCon6 schedule As a Cucumber user I want to talk about BDD with Cucumber Scenario: "BDD with Cucumber" talk Given I have managed to prepare a talk And there are people there to hear it When I give the talk Then the audience should learn something
  • 8.
    Feature: DevCon talk In order to fill the DevCon6 schedule As a Cucumber user I want to talk about BDD with Cucumber Scenario: "BDD with Cucumber" talk Given I have managed to prepare a talk And there are people there to hear it When I give the talk Then the audience should learn something
  • 9.
    Feature: DevCon talk In order to fill the DevCon6 schedule As a Cucumber user I want to talk about BDD with Cucumber Scenario: "BDD with Cucumber" talk Given I have managed to prepare a talk And there are people there to hear it When I give the talk Then the audience should learn something
  • 10.
    Feature: DevCon talk In order to fill the DevCon6 schedule As a Cucumber user I want to talk about BDD with Cucumber Scenario: "BDD with Cucumber" talk Given I have managed to prepare a talk And there are people there to hear it When I give the talk Then the audience should learn something
  • 11.
    Feature: Withdraw cashfrom account Scenario: Successful withdrawal Given I have £100 in my account When I request a withdrawal of £20 Then I should receive £20 And my balance should be £80
  • 12.
    $ cucumber withdraw_cash.feature Feature:Withdraw cash from account Scenario: Successful withdrawal # withdraw_cash.feature:3 Given I have £100 in my account # withdraw_cash.feature:4 When I request a withdrawal of £20 # withdraw_cash.feature:5 Then I should receive £20 # withdraw_cash.feature:6 And my balance should be £80 # withdraw_cash.feature:7 1 scenario (1 undefined) 4 steps (4 undefined) 0m0.002s You can implement step definitions for undefined steps with these snippets: Given /^I have £(d+) in my account$/ do |arg1| pending # express the regexp above with the code you wish you had end ...
  • 13.
    Scenario: Successful login Given a user "Fred" with password "secret" When I go to the login page And I fill in "User name" with "Fred" And I fill in "Password" with "secret" And I press "Log in" Then I should see "Welcome, Fred"
  • 14.
    Scenario: Adding aCaaS Linux Service in a production (or test) environment Given a fred production environment exists And I am on the last deployment page When I select "CaaS Linux Service" from "Add a new" And I press "Add service" And I fill in the following: | Role | FTP Server | | Application Installed Software | None | And I select "SC3 (redside)" from "Security Domain" And I select "2" from "Virtual CPUs" And I select "2" from "Virtual Memory" And I select "OEL 5u6 32bit" from "Operating System" And I select "None" from "MaaS(EMB) MQ Client" And I select "None" from "Oracle Client" And I check "Netbackup Client" And I check "XFB Client" And I check "BT Hunter Client" And I check "BTBPTM Client" And I check "Web Tier" And I press "Save" Then I should be on the last deployment page And I should see "Service saved" And I should see ...
  • 16.
    Scenario: Successful login Given a user "Fred" with password "secret" When I go to the login page And I fill in "User name" with "Fred" And I fill in "Password" with "secret" And I press "Log in" Then I should see "Welcome, Fred"
  • 17.
    Scenario: User isgreeted upon login Given the user "Fred" has an account When he logs in Then he should see "Welcome, Fred"
  • 18.
    Given /^the user"(.*?)" has an account$/ do |name| @user = User.find_or_create_by_name name, password: "secret" end When /^he logs in$/ do visit "/login" fill_in "User name", with: @user.name fill_in "Password", with: @user.password click_button "Log in" end Then /^he should see "(.*?)"$/ do |text| page.should have_content(text) end
  • 19.
    Scenario: User isgreeted upon login Given the user "Fred" has an account When he logs in Then he should see "Welcome, Fred" Scenario: Secure pages require login When I visit a secure page as a guest Then I should be asked to log in When I log in with a valid account Then I should see the secure page
  • 21.
    Feature: My awesomesystem Scenario: Using the system Given the system exists When I use it Then everything should work perfectly
  • 22.
    A developer toolfor end-to-end testing of web applications
  • 23.
    A developer toolfor LIE end-to-end testing of web applications
  • 24.
    Scenario: create adir Given a directory named "foo/bar" When I run `file foo/bar` Then the stdout should contain "foo/bar: directory" Scenario: create a file Given a file named "foo/bar/example.txt" with: """ hello world """ When I run `cat foo/bar/example.txt` Then the output should contain exactly "hello world"
  • 25.
    A tool forend-to- end testing of web applications
  • 26.
    A tool forend-to- end testing of web LIE applications
  • 27.
    More feature … er … features
  • 28.
    Feature: Posting messagesto friends Scenario: Posting a text message Given I am logged in When I post a text message Then my friends should see my message Scenario: Posting a photo Given I am logged in When I post a photo Then my friends should see a thumbnail of my photo And clicking the thumbnail should show the photo
  • 29.
    Feature: Posting messagesto friends Scenario: Posting a text message Given I am logged in When I post a text message Then my friends should see my message Scenario: Posting a photo Given I am logged in When I post a photo Then my friends should see a thumbnail of my photo And clicking the thumbnail should show the photo
  • 30.
    Feature: Posting messagesto friends Background: Given I am logged in Scenario: Posting a text message When I post a text message Then my friends should see my message Scenario: Posting a photo When I post a photo Then my friends should see a thumbnail of my photo And clicking the thumbnail should show the photo
  • 31.
    Scenario: WhenI add 1 widget to my order And I add 5 doodahs to my order And I add 2 thingummies to my order Then my basket total should be £12.34
  • 32.
    Scenario: WhenI add the following to my order: | Quantity | Item | | 1 | widget | | 5 | doodah | | 2 | thingummy | Then my basket total should be £12.34
  • 33.
    Scenario: Simple addition When I calculate 2 + 2 Then the answer should be 4 When I calculate 10 + 5 Then the answer should be 15 Scenario: Simple multiplication When I calculate 2 * 2 Then the answer should be 4 When I calculate 6 * 7 Then the answer should be 42
  • 34.
    Scenario Outline: Simplearithmetic When I calculate <first> <operation> <second> Then the answer should be <answer> Examples: | first | operation | second | answer | | 2 | + | 2 | 4 | | 10 | + | 5 | 15 | | 2 | * | 2 | 4 | | 6 | * | 7 | 42 |
  • 35.
  • 36.
    # language: fr Fonctionnalité:Addition Afin de financer mon bonus avec l'argent des pigeons En tant que trader Je souhaite pouvoir additionner 2 chiffres Plan du Scénario: Addition de produits dérivés Soit une calculatrice Etant donné qu'on tape <a> Et qu'on tape <b> Lorsqu'on tape additionner Alors le résultat doit être <somme> Exemples: | a | b | somme | | 2 | 2 | 4 | | 2 | 3 | 5 |
  • 37.
    # language: es Característica:adición Para evitar hacer errores tontos Como un matemático idiota Quiero saber la suma de los números Esquema del escenario: Sumar dos números Dado que he introducido <entrada_1> en la calculadora Y que he introducido <entrada_2> en la calculadora Cuando oprimo el <botón> Entonces el resultado debe ser <resultado> en la pantalla Ejemplos: | entrada_1 | entrada_2 | botón | resultado | | 20 | 30 | add | 50 | | 2 | 5 | add | 7 | | 0 | 40 | add | 40 |
  • 38.
    # language: de Funktionalität:Addition Um dumme Fehler zu vermeiden möchte ich als Matheidiot die Summe zweier Zahlen gesagt bekommen Szenariogrundriss: Zwei Zahlen hinzufügen Angenommen ich habe <Eingabe_1> in den Taschenrechner eingegeben Und ich habe <Eingabe_2> in den Taschenrechner eingegeben Wenn ich <Knopf> drücke Dann sollte das Ergebniss auf dem Bildschirm <Ausgabe> sein Beispiele: | Eingabe_1 | Eingabe_2 | Knopf | Ausgabe | | 20 | 30 | add | 50 | | 2 | 5 | add | 7 | | 0 | 40 | add | 40 |
  • 39.
    # language: en-lol OHHAI: STUFFING MISHUN: CUCUMBR I CAN HAZ IN TEH BEGINNIN 3 CUCUMBRZ WEN I EAT 2 CUCUMBRZ DEN I HAS 2 CUCUMBERZ IN MAH BELLY AN IN TEH END 1 CUCUMBRZ KTHXBAI
  • 40.
  • 41.
  • 42.
    Given /^the user"(.*?)" has an account$/ do |name| @user = User.find_or_create_by_name name, password: "secret" end Given /^a logged-in user$/ do @user = User.find_or_create_by_name "Fred", password: "secret" visit "/login" fill_in "User name", :with => @user.name fill_in "Password", :with => @user.password click_button "Log in" end When /^he logs in$/ do visit "/login" fill_in "User name", with: @user.name fill_in "Password", with: @user.password click_button "Log in" end Then /^he should see "(.*?)"$/ do |text| page.should have_content(text) end
  • 43.
    Given /^the user"(.*?)" has an account$/ do |name| @user = User.find_or_create_by_name name, password: "secret" end Given /^a logged-in user$/ do @user = User.find_or_create_by_name "Fred", password: "secret" visit "/login" fill_in "User name", :with => @user.name fill_in "Password", :with => @user.password click_button "Log in" end When /^he logs in$/ do visit "/login" fill_in "User name", with: @user.name fill_in "Password", with: @user.password click_button "Log in" end Then /^he should see "(.*?)"$/ do |text| page.should have_content(text) end
  • 44.
    module LoginSteps def login(name, password) visit "/login" fill_in "User name", with: name fill_in "Password", with: password click_button "Log in" end end World(LoginSteps) Given /^a logged in user$/ do @user = User.find_or_create_by_name name, password: "secret" login(@user.name, @user.password) end When /^he logs in$/ do login(@user.name, @user.password) end
  • 45.
  • 46.
  • 47.
    A tool for end-to-endtesting of applications
  • 48.
    A tool for end-to-endtesting LIE of applications
  • 49.
    A tool fortesting applications
  • 50.
    A tool fortestingRELY TI applications N EN HER OT EIT UE TR
  • 51.
  • 52.
    Made-up statistics Identifying scenarios 25% Automated tests 35% Agreeing steps 40%
  • 53.
    $ cucumber talk.feature Feature:DevCon talk In order to fill the DevCon6 schedule As a Cucumber user I want to talk about BDD with Cucumber Scenario: "BDD with Cucumber" talk # talk.feature:6 Given I have managed to prepare my talk on time # talk_steps.rb:1 And there are people there to hear it # talk_steps.rb:4 When I give the talk # talk_steps.rb:7 Then the audience should learn something # talk_steps.rb:10 1 scenario (1 passed) 4 steps (4 passed) 0m0.002s
  • 54.