cucumber

57
Writing runnable acceptance criteria in plain text with Farooq Ali

Upload: farooq-ali

Post on 02-Nov-2014

12 views

Category:

Technology


3 download

DESCRIPTION

Writing runnable acceptance criteria in plain text with Cucumber.

TRANSCRIPT

Page 1: Cucumber

Writing runnable acceptance criteria in plain text with

Farooq Ali

Page 2: Cucumber

The YawningCrevasse of Doom

Page 3: Cucumber

fluffy high-level needs

Page 4: Cucumber

<technical_babble />

Page 5: Cucumber

[Test][ExpectedException(typeof(InsufficientFundsException))]public void TransferWithInsufficientFunds(){

Account source = new Account();source.Deposit(200.00F);Account destination = new Account();destination.Deposit(150.00F);

}

Page 6: Cucumber
Page 7: Cucumber

the convergence of two movements

Page 8: Cucumber

the convergence of two movementsBehavior-Driven Development (BDD)& Domain-Specific Languages (DSLs)

Page 9: Cucumber

BDD movement

“Acceptance criteria should be executable”

“…a ubiquitous language for analysis”

Page 10: Cucumber

what are we really trying to describe?

Page 11: Cucumber

what are we really trying to describe?

the human concept of causality

Page 12: Cucumber

Precondition -> Given

Action -> When

Outcome -> Then

Causality

Page 13: Cucumber

Setup Data/State -> Given

Call Method -> When

Assert -> Then

Causality

Page 14: Cucumber

“…a computer language that's targeted to a particular kind of problem, rather than a general purpose language that's aimed at any kind of software problem.”

DSL movement

Page 15: Cucumber

“The sweet spot, however is in making DSLs business-readable rather than business-writeable.”

DSL movement

Page 16: Cucumber

BDD + DSL

Page 17: Cucumber

Feature: AdditionAs a math moronI want to add two numbers togetherSo that I can better use my scarce brain processing power Scenario: Adding positive numbers together Given I enter 1 into the calculator When I add 1 to it Then the calculator should show 2

Gherkin

Page 18: Cucumber

Acceptance Criteria

Page 19: Cucumber

Shared Vocabulary

Page 20: Cucumber

Documentation

Page 21: Cucumber

Traceability

Page 22: Cucumber

Bug Tracking

Page 23: Cucumber

Using Cucumber

Page 24: Cucumber

Acceptance Criteria(Plain Text)

Step Definitions(Ruby)

ComponentsBuilding Blocks

Page 25: Cucumber

Acceptance Criteria

Feature: AdditionAs a math moronI want to add two numbers togetherSo that I can better use my scarce brain processing power Scenario: Adding positive numbers together Given I enter 1 into the calculator When I add 1 to it Then the calculator should show 2

Acceptance Criteria

Page 26: Cucumber

Acceptance Criteria

Feature: AdditionAs a math moronI want to add two numbers togetherSo that I can better use my scarce brain processing power Scenario: Adding positive numbers together Given I enter 1 into the calculator When I add 1 to it Then the calculator should show 2

Acceptance Criteria

Page 27: Cucumber

Acceptance Criteria

Feature: AdditionAs a math moronI want to add two numbers togetherSo that I can better use my scarce brain processing power Scenario: Adding positive numbers together Given I enter 1 into the calculator When I add 1 to it Then the calculator should show 2

Acceptance Criteria

Page 28: Cucumber

Acceptance Criteria

Feature: AdditionAs a math moronI want to add two numbers togetherSo that I can better use my scarce brain processing power Scenario: Adding positive numbers together Given I enter 1 into the calculator When I add 1 to it Then the calculator should show 2

Acceptance Criteria

Page 29: Cucumber

Acceptance Criteria

Feature: AdditionAs a math moronI want to add two numbers togetherSo that I can better use my scarce brain processing power Scenario: Adding positive numbers together Given I enter 1 into the calculator When I add 1 to it Then the calculator should show 2

Acceptance Criteria

Page 30: Cucumber

KeywordsKeyword Localized

name ‘English’

native ‘English’

encoding ‘UTF-8’

feature ‘Feature’

background ‘Background’

scenario ‘Scenario’

scenario_outline ‘Scenario Outline’

examples ‘Examples’

given ‘Given’

when ‘When’

then ’Then’

and ‘And’

but ‘But’

Keywords

Page 31: Cucumber

LanguagesMacintosh-9:calculator ThoughtWorks$ cucumber --language help| ar | Arabic | العربية| bg | Bulgarian | български | cat | Catalan | català | cy | Welsh | Cymraeg | cz | Czech | Česky | da | Danish | dansk | de | German | Deutsch | en | English | English | en-au | Australian | Australian | en-lol | LOLCAT | LOLCAT | en-tx | Texan | Texan | es | Spanish | español | et | Estonian | eesti keel | fi | Finnish | suomi | fr | French | français | he | Hebrew | עברית | hr | Croatian | hrvatski | hu | Hungarian | magyar | id | Indonesian | Bahasa Indonesia

Languages

Page 32: Cucumber

Given I enter 1 into the calculatorWhen I add 1 to itThen the calculator should show 2

Acceptance Criteria(Plain Text)

Step DefinitionsBuilding Blocks

Page 33: Cucumber

Given I enter 1 into the calculatorWhen I add 1 to itThen the calculator should show 2

Given /^I enter (.+) into the calculator$/ do |number| @calculator = Calculator.new @calculator.enter(number.to_i)end

When /^I add (.+) to it$/ do |number| @calculator.add(number.to_i)end

When /^the calculator should show (.+)$/ do |number| @calculator.number.should == number.to_iend

Acceptance Criteria(Plain Text)

Step Definitions(Ruby)

Step DefinitionsBuilding Blocks

Page 34: Cucumber

Step Definitions

Given /^I enter (.+) into the calculator$/ do |number| @calculator = Calculator.new @calculator.enter(number.to_i)end

When /^I add (.+) to it$/ do |number| @calculator.add(number.to_i)end

Then /^the calculator should show (.+)$/ do |number| @calculator.number.should == number.to_iend

Step Definitions

Page 35: Cucumber

Step Definitions

Then /^the calculator should show (.+)$/ do |number| @calculator.number.should == number.to_iend

Step Definitions

Page 36: Cucumber

Step DefinitionsStep Definitions

When I give a 45-minute long talk on Cucumber at 10:30am

Page 37: Cucumber

Step DefinitionsStep Definitions

When I give a 45-minute long talk on Cucumber at 10:30am

Page 38: Cucumber

Step Definitions

/I give a (\d+)-minute long talk on (.+) at (\d+):(\d+)(am|pm)/

Step Definitions

When I give a 45-minute long talk on Cucumber at 10:30am

Page 39: Cucumber

Step Definitions

/I give a (\d+)-minute long talk on (.+) at (\d+):(\d+)(am|pm)/

Step Definitions

When I give a 45-minute long talk on Cucumber at 10:30am

Page 40: Cucumber

Step DefinitionsStep Definitions

do |duration_in_minutes, topic, start_hour, start_minute, am_pm| end

/I give a (\d+)-minute long talk on (.+) at (\d+):(\d+)(am|pm)/

When I give a 45-minute long talk on Cucumber at 10:30am

Page 41: Cucumber

Multiple Given-When-Thens

Scenario: Multiple Givens Given one thing Given another thing Given yet another thing When I open my eyes Then I see something Then I don't see something else

Multiple Given-When-Thens

Page 42: Cucumber

Or use And / But

Scenario: Multiple Givens Given one thing And another thing And yet another thing When I open my eyes Then I see something But I don't see something else

Or use And/But

Page 43: Cucumber

Reuse

Given /^the user (.*) exists$/ do |name|#...

end

Given /^I log in as (.*)$/ do |name| #...end

Given /^(.*) is logged in$/ do |name| Given "the user #{name} exists" Given "I log in as #{name}"end

Calling steps from within steps

Page 44: Cucumber

ReuseMultiline step arguments - Tables

Given the following people exist: | name | email | phone | | Farooq | [email protected] | 123 | | Mary | [email protected] | 234 | | Bob | [email protected] | 456 |

Page 45: Cucumber

ReuseMultiline step arguments - Tables

Given the following people exist: | name | email | phone | | Farooq | [email protected] | 123 | | Mary | [email protected] | 234 | | Bob | [email protected] | 456 |

Given /the following people exist:/ do |people_table| people_table.hashes.each do |hash| # 1st: {'name' => ’Farooq', 'email' => ’[email protected]’, ... } # 2nd: {'name' => ’Mary', 'email' => ’[email protected]', ... } # ... endend

Page 46: Cucumber

ReuseMultiline step arguments - Strings

Given a blog post named "Random" with Markdown body """ Some Title, Eh? ============== Here is the first paragraph of my blog post. Lorem ipsum dolor sit amet, consectetur adipiscing elit. """

Page 47: Cucumber

ReuseMultiline step arguments - Strings

Given a blog post named "Random" with Markdown body """ Some Title, Eh? ============== Here is the first paragraph of my blog post. Lorem ipsum dolor sit amet, consectetur adipiscing elit. """

Given /^a blog post named "([^\"]*)" with Markdown body$/ do |title, markdown| Post.create!(:title => title, :body => markdown)end

Page 48: Cucumber

Tags

@billingFeature: Enter billing info

@creditcard Scenario: Credit card @paypal Scenario: PayPal

Tags

Page 49: Cucumber

Hooks

Before do # do something before first step of scenarioend

After do # do something after each scenarioend

Hooks

Page 50: Cucumber

Tagged Hooks

Before('@billing', '@calculations') do # This will only run before scenarios tagged

# with @billing or @calculations. end

Tagged Hooks

Page 51: Cucumber

Global Hooks

browser = Selenium::SeleniumDriver.new("localhost", 4444, "*chrome",

"http://localhost", 15000)

Given 'I am on the Google search page' do browser.open('http://www.google.com/’)end

When /I search for "(.*)"/ do |query| browser.type('q', query) browser.click 'btnG’ browser.wait_for_page_to_loadend

Then /I should see a link to (.*)/ do |expected_url| browser.is_element_present("css=a[href='#{expected_url}']").should be_trueend

Global Hooks

Page 52: Cucumber

Tags

Feature: Multiple site support As a Mephisto site owner I want to host blogs for different people In order to make gigantic piles of money

Background: Given a global administrator named “Greg” And a blog named “Greg’s anti-tax rants” And a customer named “Dr. Bill” And a blog named “Expensive Therapy” owned by “Dr. Bill”

Scenario: Dr. Bill posts to his own blog Given I am logged in as Dr. Bill When I try to post to “Expensive Therapy” Then I should see “Your article was published.”

Backgrounds

Page 53: Cucumber

Global Hooks

# support fileTransform /^user (\w+)$/ do |username| User.find_by_username(username) end

# step definition fileThen /^(user \w+) should be friends with (user \w+)$/ do |user,friend| user.should be_friends_with(friend)end

Step Argument Transforms

Page 54: Cucumber

Formatters

cucumber -f junit -–out <output_dir>

Page 55: Cucumber

Formatters: StepsFeature: --formatter steps option - Steps Formatter

In order to easily see which steps are already defined, specially when using 3rd party steps libraries, Cucumber should show the available steps in a user-friendly format

Background: Given I am in steps_library

Scenario: Printing steps When I run cucumber -f steps features Then it should pass with """ features/step_definitions/steps_lib1.rb /^I defined a first step$/ # features/step_definitions/steps_lib1.rb:1 /^I define a second step$/ # features/step_definitions/steps_lib1.rb:4 /^I should also have a third step$/ # features/step_definitions/steps_lib1.rb:7 features/step_definitions/steps_lib2.rb /^I defined a step 4$/ # features/step_definitions/steps_lib2.rb:1 /^I create a step 5$/ # features/step_definitions/steps_lib2.rb:4 /^I should be too tired for step 6$/ # features/step_definitions/steps_lib2.rb:7 6 step definition(s) in 2 source file(s).

"""

Page 56: Cucumber

Formatters : JUnitFeature: JUnit output formatter In order for developers to create test reports with ant Cucumber should be able to output JUnit xml files Background: Given I am in junit And the tmp directory is empty @mri186 Scenario: one feature, one passing scenario, one failing scenario When I run cucumber --format junit --out tmp/ features/one_passing_one_failing.feature Then it should fail with """

""" And "examples/junit/tmp/TEST-one_passing_one_failing.xml" with junit duration "0.005" should contain """ <?xml version="1.0" encoding="UTF-8"?> <testsuite errors="0" failures="1" name="One passing scenario, one failing scenario" tests="2"

time="0.005"> <testcase classname="One passing scenario, one failing scenario.Passing" name="Passing"

time="0.005"> </testcase> <testcase classname="One passing scenario, one failing scenario.Failing" name="Failing"

time="0.005"> <failure message="failed Failing" type="failed"> Scenario: Failing

Given a failing scenario

Message: (RuntimeError) features/one_passing_one_failing.feature:7:in `Given a failing scenario' </failure> </testcase> </testsuite>

""" Scenario: pending steps are simply skipped When I run cucumber --format junit --out tmp/ features/pending.feature Then it should pass with """ """ And "examples/junit/tmp/TEST-pending.xml" with junit duration "0.009" should contain """ <?xml version="1.0" encoding="UTF-8"?> <testsuite errors="0" failures="0" name="Pending step" tests="0" time="0.009"> </testsuite> """

Scenario: pending step with strict option should fail When I run cucumber --format junit --out tmp/ features/pending.feature --strict Then it should fail with """

""" And "examples/junit/tmp/TEST-pending.xml" with junit duration "0.000160" should contain """ <?xml version="1.0" encoding="UTF-8"?> <testsuite errors="0" failures="1" name="Pending step" tests="1" time="0.000160"> <testcase classname="Pending step.Pending" name="Pending" time="0.000160"> <failure message="pending Pending" type="pending"> Scenario: Pending

TODO (Cucumber::Pending) features/pending.feature:4:in `Given a pending step' </failure> </testcase> </testsuite>

""" Scenario: run all features When I run cucumber --format junit --out tmp/ features Then it should fail with """ """ And "examples/junit/tmp/TEST-one_passing_one_failing.xml" should exist And "examples/junit/tmp/TEST-pending.xml" should exist Scenario: show correct error message if no --out is passed When I run cucumber --format junit features Then STDERR should not match """can't convert .* into String \(TypeError\) """ And STDERR should match """You \*must\* specify \-\-out DIR for the junit formatter """

Page 57: Cucumber

Formatters : HTML

Feature: HTML formatter In order to make it easy to read Cucumber results there should be a HTML formatter with an awesome CSS

Scenario: Everything in examples/self_test When I run cucumber -q --format html --out tmp/a.html features Then "examples/self_test/tmp/a.html" should have the same contents as

"features/html_formatter/a.html"