Andrew Larcombe @andrewl
BDD?

You’re doing it all wrong!
(perhaps)
Who am I?!
Software Delivery Professional"
Engineering: Drupal (nodejs, go-lang, solr, geospatial, ruby-on-rails, perl, c++)

Process: Agile, Scrum, BDD"
t: @andrewl

w: andrewl.net

e: andrew@andrewl.net"
"
fluxus.io
"
"
What is Behavioural Driven Development?	

Some common anti-patterns
BDD - you're doing it all wrong!
“BDD is a second-generation,
outside–in, pull-based, multiple-
stakeholder, multiple-scale, high-
automation, agile methodology.” 

(Dan North)
BDD - you're doing it all wrong!
The Problem!
We have complex communication problems, not technical
problems (mostly)."
Jargon, ‘Chinese Whispers’, early solutionising"
Consequences: Locked in to delivering late, delayed or
the wrong product, before we’ve even written a line of
code.
BDD - you're doing it all wrong!
“If I asked my customers what they
wanted they would have said ‘a faster
horse’” 

(Henry Ford)
Behat
Requirement
Conversation
Discovery
Specification
Automation
For all, in a common language
Behat
BDD leads to Executable Specifications with Examples for
features that deliver business value and that are written in
the domain language of the business!
"
Behat is a tool for automating these specifications.!
Some BDD & Behat Antipatterns
"


All journeys sold between Brussels and
Chicago with a child ticket should have at
least one accompanying adult or senior
ticket.
As a user
I want to be prevented from purchasing a
child only journey from Brussels to
Chicago
So that…errr…???
Antipattern #1:

“As a User”!
As the Company Lawyer
I want to prevent customers purchasing a
child only ticket on flights from Brussels
to Chicago
So that we’re compliant with regulations
This is the person that cares
This is why they care
Given I go to ‘/tickets.php’

And I select ‘0’ from ‘xpath://ticket-form/adults’

And I select ‘2’ from ‘xpath://ticket-form/children’

And I select ‘0’ from ‘xpath://ticket-form/youths’

And I select ‘0’ from ‘xpath://ticket-form/seniors’

And I click ‘xpath://ticket-form/submit’

Then I should see “You cannot purchase child-only
tickets for this journey”

And I should be on ‘/tickets.php’

Antipattern #2:

“Writing Brittle Tests not Specifications”!
Tight coupling with DOM
Tight coupling with URLs
Hard-coded

messages?!?!!
Given I go to ‘/tickets.php’

And I select ‘0’ from ‘xpath://ticket-form/adults’

And I select ‘2’ from ‘xpath://ticket-form/children’

And I select ‘0’ from ‘xpath://ticket-form/youths’

And I select ‘0’ from ‘xpath://ticket-form/seniors’

And I click ‘xpath://ticket-form/submit’

Then I should see “You cannot purchase child-only
tickets for this journey”

And I should be on ‘/tickets.php’

Repetition
Who even understands this??!?!!
Antipattern #2:

“Writing Brittle Tests not Specifications”!
Given I am on the ticket search page

When search for tickets from “<origin>” to “<destination>” for
“<num_adults”> adults, “<num_children>” children and
“<num_seniors> seniors

Then I should see the child fare policy message

And be on the ticket search page
Examples:

|origin |destination|num_adults|num_children|num_seniors|

|Brussels|Chicago |0 |1 |0 |

|Brussels|Chicago |0 |2 |0 |

|Brussels|Chicago |0 |3 |0 |

|Brussels|Chicago |0 |4 |0 |

|Brussels|Chicago |0 |5 |0 |
Page Objects!
Separation of Concerns"
Encapsulation"
DRY (Don’t Repeat Yourself)"
Hides implementation details"
An API for the things you do on a page"
e.g. class TicketSearchPage: it’s where you search for
tickets (that’s what you do on the ticket search page)
§
class SearchPage
function search($origin, $dest, …) {

$this->get(‘Search Form’)

->setOrigin($origin);
function warningMessage() {

return $this->get
class SearchForm {

function setOrigin($origin) {

$this

->fillField(“From”, $origin); …etc…

class SearchContext {

function iShouldSeePolicyMessage() {

expect($this->getPage(‘search’)->warningMessage())->toBe(‘You cannot
purchase child-only tickets for this journey’)

…Page Object Contexts
Hide the Complexity - Feature Contexts…
Page Objects…an approach!
Start with wireframe/ui."
"
Describe in English what you do on the page."
"
Write a function in your Page object that maps onto a ‘real world’
action that you might perform on the page"
eg search(), register(), uploadAnImage(), addAComment()."
"
Write a function in your Context that maps requirements into these
actions and throws exceptions where required."
"
Refactor, refactor, refactor
"


All journeys sold between Brussels and
Capetown with 2 or more child tickets should
have at least one accompanying adult or
senior ticket.
Given I am on the ticket search page

When search for tickets from “<origin>” to “<destination>” for
“<num_adults”> adults, “<num_children>” children and
“<num_seniors> seniors

Then I should see the child fare policy message

And be on the ticket search page
Examples:

|origin |destination|num_adults|num_children|num_seniors|

|Brussels|Chicago |0 |1 |0 |

|Brussels|Chicago |0 |2 |0 |

|Brussels|Chicago |0 |3 |0 |

|Brussels|Chicago |0 |4 |0 |

|Brussels|Chicago |0 |5 |0 |

|Brussels|Capetown |0 |2 |0 |

|Brussels|Capetown |0 |3 |0 |

|Brussels|Capetown |0 |4 |0 |

|Brussels|Capetown |0 |5 |0 |
"


Add some front-end validation…after
the user selects the origin and destination,
load the rules determining child ticket policies
using AJAX
Given I go to ‘/tickets.php’

And I select ‘Brussels’ from ‘xpath://ticket-form/
origin’

And I select ‘Chicago’ from ‘xpath://ticket-form/
destination’

And I wait 3 seconds
Given I go to ‘/tickets.php’

And I select ‘Brussels’ from ‘xpath://ticket-form/
origin’

And I select ‘Chicago’ from ‘xpath://ticket-form/
destination’

And I wait 5 seconds
Never part of anyone’s specification, ever!
Antipattern #3:

“And I wait…”!
public function spin ($lambda) {

while (true) {

try {

if ($lambda($this)) {

return true;

}

}

catch (Exception $e) {

//and do nothing here

}
sleep(1); //wait and try again in a second

}

}
$this->spin(function($context) {

$context->getSession()->getPage()->findById('adults');

});
"
Spin functions!
In review…not writing tests,
discovering the specification
As a user
I want to be prevented from purchasing a
child only journey from Brussels to
Chicago
So that…errr…???
As the Company Lawyer
I want to prevent customers purchasing a
child only ticket on flights from Brussels
to Chicago
So that we’re compliant with regulations
Given I go to ‘/tickets.php’

And I select ‘0’ from ‘xpath://ticket-form/adults’

And I select ‘2’ from ‘xpath://ticket-form/children’

And I select ‘0’ from ‘xpath://ticket-form/youths’

And I select ‘0’ from ‘xpath://ticket-form/seniors’

And I click ‘xpath://ticket-form/submit’

Then I should see “You cannot purchase child-only
tickets for this journey”

And I should be on ‘/tickets.php’

Given I am on the ticket search page

When search for tickets from “<origin>” to “<destination>” for
“<num_adults”> adults, “<num_children>” and “<num_seniors>
seniors

Then I should see the child fare policy message

And be on the ticket search page
Examples:

|origin |destination|num_adults|num_children|num_seniors|

|Brussels|Chicago |0 |1 |0 |

|Brussels|Chicago |0 |2 |0 |

|Brussels|Chicago |0 |3 |0 |

|Brussels|Chicago |0 |4 |0 |

|Brussels|Chicago |0 |5 |0 |

|Brussels|Capetown |0 |2 |0 |

|Brussels|Capetown |0 |3 |0 |

|Brussels|Capetown |0 |4 |0 |

|Brussels|Capetown |0 |5 |0 |
Requirement
Conversation
Discovery
Specification
Automation
For all, in a common language
Behat
Links!
Reading

dannorth.net/introducing-bdd

dannorth.net/2010/08/30/introducing-deliberate-discovery

specificationbyexample.com/key_ideas.html

“Domain Driven Design” Eric Evans (domainlanguage.com)

lizkeogh.com/2010/02/02/theyre-not-user-stories
Playing

behat.org

drupal.org/project/drupalextension

code.google.com/p/selenium/wiki/PageObjects

github.com/orangedigital/business-selector-extension

github.com/BossaConsulting/phpspec2-expect


More Related Content

PPTX
My Reading Specs - Refactoring Patterns for Gherkin Scenarios
PDF
TК°Conf. Impact Mapping: планирование разработки продукта с учетом бизнес цел...
PDF
Dev ops with smell v1.2
PDF
BDD Anti-patterns
PDF
Sql Antipatterns Strike Back
PPTX
Micro frontends
ODP
Scout xss csrf_security_presentation_chicago
PDF
Crafting Quality PHP Applications (Bucharest Tech Week 2017)
My Reading Specs - Refactoring Patterns for Gherkin Scenarios
TК°Conf. Impact Mapping: планирование разработки продукта с учетом бизнес цел...
Dev ops with smell v1.2
BDD Anti-patterns
Sql Antipatterns Strike Back
Micro frontends
Scout xss csrf_security_presentation_chicago
Crafting Quality PHP Applications (Bucharest Tech Week 2017)

Similar to BDD - you're doing it all wrong! (20)

PDF
Crafting Quality PHP Applications: an overview (PHPSW March 2018)
PDF
Crafting Quality PHP Applications (PHPkonf 2018)
PDF
4Developers 2015: Jak (w końcu) zacząć pracować z DDD wykorzystując BDD - Kac...
PDF
Crafting Quality PHP Applications (ConFoo YVR 2017)
PDF
Crafting Quality PHP Applications (PHP Benelux 2018)
PDF
Best practices for crafting high quality PHP apps (PHP Yorkshire 2018)
PDF
Best practices for crafting high quality PHP apps (PHP South Africa 2018)
KEY
JavaScript Neednt Hurt - JavaBin talk
PDF
A simple html login page using java s
PDF
[FOSS4G 2015] GIS policy map for local government in korea story of Dobong-gu...
PPTX
Real World Test Automation
PDF
Best practices for crafting high quality PHP apps (ScotlandPHP 2018)
PDF
Best practices for crafting high quality PHP apps (php[world] 2019)
PDF
JavaScript isn't evil.
PDF
Best practices for crafting high quality PHP apps (Bulgaria 2019)
PDF
Full-Text Search Explained - Philipp Krenn - Codemotion Rome 2017
PDF
Speed Grooming Requirements with SAFe
PDF
Cleanliness is Next to Domain-Specificity
PDF
Cleanliness is Next to Domain-Specificity
PDF
Best practices for crafting high quality PHP apps - PHP UK 2019
Crafting Quality PHP Applications: an overview (PHPSW March 2018)
Crafting Quality PHP Applications (PHPkonf 2018)
4Developers 2015: Jak (w końcu) zacząć pracować z DDD wykorzystując BDD - Kac...
Crafting Quality PHP Applications (ConFoo YVR 2017)
Crafting Quality PHP Applications (PHP Benelux 2018)
Best practices for crafting high quality PHP apps (PHP Yorkshire 2018)
Best practices for crafting high quality PHP apps (PHP South Africa 2018)
JavaScript Neednt Hurt - JavaBin talk
A simple html login page using java s
[FOSS4G 2015] GIS policy map for local government in korea story of Dobong-gu...
Real World Test Automation
Best practices for crafting high quality PHP apps (ScotlandPHP 2018)
Best practices for crafting high quality PHP apps (php[world] 2019)
JavaScript isn't evil.
Best practices for crafting high quality PHP apps (Bulgaria 2019)
Full-Text Search Explained - Philipp Krenn - Codemotion Rome 2017
Speed Grooming Requirements with SAFe
Cleanliness is Next to Domain-Specificity
Cleanliness is Next to Domain-Specificity
Best practices for crafting high quality PHP apps - PHP UK 2019
Ad

More from Andrew Larcombe (7)

PDF
impact_mapping
KEY
Don't let maps cramp your style - Prague
ZIP
Don't Let Maps Cramp Your Style
KEY
Location, Maps, Drupal and You
PDF
Geobrainstorming
PPT
AGI09 Soapbox Slides
PDF
A New Way To Amsterdam
impact_mapping
Don't let maps cramp your style - Prague
Don't Let Maps Cramp Your Style
Location, Maps, Drupal and You
Geobrainstorming
AGI09 Soapbox Slides
A New Way To Amsterdam
Ad

Recently uploaded (20)

PPTX
Build Your First AI Agent with UiPath.pptx
PDF
sbt 2.0: go big (Scala Days 2025 edition)
PDF
The influence of sentiment analysis in enhancing early warning system model f...
PDF
Developing a website for English-speaking practice to English as a foreign la...
PDF
ENT215_Completing-a-large-scale-migration-and-modernization-with-AWS.pdf
PPT
Module 1.ppt Iot fundamentals and Architecture
PPTX
Microsoft Excel 365/2024 Beginner's training
PDF
A proposed approach for plagiarism detection in Myanmar Unicode text
PDF
Flame analysis and combustion estimation using large language and vision assi...
PPTX
MicrosoftCybserSecurityReferenceArchitecture-April-2025.pptx
PDF
How ambidextrous entrepreneurial leaders react to the artificial intelligence...
PDF
NewMind AI Weekly Chronicles – August ’25 Week III
PDF
sustainability-14-14877-v2.pddhzftheheeeee
PPTX
TEXTILE technology diploma scope and career opportunities
PDF
Credit Without Borders: AI and Financial Inclusion in Bangladesh
PDF
OpenACC and Open Hackathons Monthly Highlights July 2025
PDF
A contest of sentiment analysis: k-nearest neighbor versus neural network
PPTX
The various Industrial Revolutions .pptx
PDF
Consumable AI The What, Why & How for Small Teams.pdf
PDF
A review of recent deep learning applications in wood surface defect identifi...
Build Your First AI Agent with UiPath.pptx
sbt 2.0: go big (Scala Days 2025 edition)
The influence of sentiment analysis in enhancing early warning system model f...
Developing a website for English-speaking practice to English as a foreign la...
ENT215_Completing-a-large-scale-migration-and-modernization-with-AWS.pdf
Module 1.ppt Iot fundamentals and Architecture
Microsoft Excel 365/2024 Beginner's training
A proposed approach for plagiarism detection in Myanmar Unicode text
Flame analysis and combustion estimation using large language and vision assi...
MicrosoftCybserSecurityReferenceArchitecture-April-2025.pptx
How ambidextrous entrepreneurial leaders react to the artificial intelligence...
NewMind AI Weekly Chronicles – August ’25 Week III
sustainability-14-14877-v2.pddhzftheheeeee
TEXTILE technology diploma scope and career opportunities
Credit Without Borders: AI and Financial Inclusion in Bangladesh
OpenACC and Open Hackathons Monthly Highlights July 2025
A contest of sentiment analysis: k-nearest neighbor versus neural network
The various Industrial Revolutions .pptx
Consumable AI The What, Why & How for Small Teams.pdf
A review of recent deep learning applications in wood surface defect identifi...

BDD - you're doing it all wrong!

  • 1. Andrew Larcombe @andrewl BDD?
 You’re doing it all wrong! (perhaps)
  • 2. Who am I?! Software Delivery Professional" Engineering: Drupal (nodejs, go-lang, solr, geospatial, ruby-on-rails, perl, c++)
 Process: Agile, Scrum, BDD" t: @andrewl
 w: andrewl.net
 e: andrew@andrewl.net" " fluxus.io
  • 3. " " What is Behavioural Driven Development? Some common anti-patterns
  • 5. “BDD is a second-generation, outside–in, pull-based, multiple- stakeholder, multiple-scale, high- automation, agile methodology.” 
 (Dan North)
  • 7. The Problem! We have complex communication problems, not technical problems (mostly)." Jargon, ‘Chinese Whispers’, early solutionising" Consequences: Locked in to delivering late, delayed or the wrong product, before we’ve even written a line of code.
  • 9. “If I asked my customers what they wanted they would have said ‘a faster horse’” 
 (Henry Ford)
  • 10. Behat
  • 12. BDD leads to Executable Specifications with Examples for features that deliver business value and that are written in the domain language of the business! " Behat is a tool for automating these specifications.!
  • 13. Some BDD & Behat Antipatterns
  • 14. " 
 All journeys sold between Brussels and Chicago with a child ticket should have at least one accompanying adult or senior ticket.
  • 15. As a user I want to be prevented from purchasing a child only journey from Brussels to Chicago So that…errr…??? Antipattern #1:
 “As a User”!
  • 16. As the Company Lawyer I want to prevent customers purchasing a child only ticket on flights from Brussels to Chicago So that we’re compliant with regulations This is the person that cares This is why they care
  • 17. Given I go to ‘/tickets.php’
 And I select ‘0’ from ‘xpath://ticket-form/adults’
 And I select ‘2’ from ‘xpath://ticket-form/children’
 And I select ‘0’ from ‘xpath://ticket-form/youths’
 And I select ‘0’ from ‘xpath://ticket-form/seniors’
 And I click ‘xpath://ticket-form/submit’
 Then I should see “You cannot purchase child-only tickets for this journey”
 And I should be on ‘/tickets.php’
 Antipattern #2:
 “Writing Brittle Tests not Specifications”!
  • 18. Tight coupling with DOM Tight coupling with URLs Hard-coded
 messages?!?!! Given I go to ‘/tickets.php’
 And I select ‘0’ from ‘xpath://ticket-form/adults’
 And I select ‘2’ from ‘xpath://ticket-form/children’
 And I select ‘0’ from ‘xpath://ticket-form/youths’
 And I select ‘0’ from ‘xpath://ticket-form/seniors’
 And I click ‘xpath://ticket-form/submit’
 Then I should see “You cannot purchase child-only tickets for this journey”
 And I should be on ‘/tickets.php’
 Repetition Who even understands this??!?!! Antipattern #2:
 “Writing Brittle Tests not Specifications”!
  • 19. Given I am on the ticket search page
 When search for tickets from “<origin>” to “<destination>” for “<num_adults”> adults, “<num_children>” children and “<num_seniors> seniors
 Then I should see the child fare policy message
 And be on the ticket search page Examples:
 |origin |destination|num_adults|num_children|num_seniors|
 |Brussels|Chicago |0 |1 |0 |
 |Brussels|Chicago |0 |2 |0 |
 |Brussels|Chicago |0 |3 |0 |
 |Brussels|Chicago |0 |4 |0 |
 |Brussels|Chicago |0 |5 |0 |
  • 20. Page Objects! Separation of Concerns" Encapsulation" DRY (Don’t Repeat Yourself)" Hides implementation details" An API for the things you do on a page" e.g. class TicketSearchPage: it’s where you search for tickets (that’s what you do on the ticket search page)
  • 21. § class SearchPage function search($origin, $dest, …) {
 $this->get(‘Search Form’)
 ->setOrigin($origin); function warningMessage() {
 return $this->get class SearchForm {
 function setOrigin($origin) {
 $this
 ->fillField(“From”, $origin); …etc…
 class SearchContext {
 function iShouldSeePolicyMessage() {
 expect($this->getPage(‘search’)->warningMessage())->toBe(‘You cannot purchase child-only tickets for this journey’)
 …Page Object Contexts Hide the Complexity - Feature Contexts…
  • 22. Page Objects…an approach! Start with wireframe/ui." " Describe in English what you do on the page." " Write a function in your Page object that maps onto a ‘real world’ action that you might perform on the page" eg search(), register(), uploadAnImage(), addAComment()." " Write a function in your Context that maps requirements into these actions and throws exceptions where required." " Refactor, refactor, refactor
  • 23. " 
 All journeys sold between Brussels and Capetown with 2 or more child tickets should have at least one accompanying adult or senior ticket.
  • 24. Given I am on the ticket search page
 When search for tickets from “<origin>” to “<destination>” for “<num_adults”> adults, “<num_children>” children and “<num_seniors> seniors
 Then I should see the child fare policy message
 And be on the ticket search page Examples:
 |origin |destination|num_adults|num_children|num_seniors|
 |Brussels|Chicago |0 |1 |0 |
 |Brussels|Chicago |0 |2 |0 |
 |Brussels|Chicago |0 |3 |0 |
 |Brussels|Chicago |0 |4 |0 |
 |Brussels|Chicago |0 |5 |0 |
 |Brussels|Capetown |0 |2 |0 |
 |Brussels|Capetown |0 |3 |0 |
 |Brussels|Capetown |0 |4 |0 |
 |Brussels|Capetown |0 |5 |0 |
  • 25. " 
 Add some front-end validation…after the user selects the origin and destination, load the rules determining child ticket policies using AJAX
  • 26. Given I go to ‘/tickets.php’
 And I select ‘Brussels’ from ‘xpath://ticket-form/ origin’
 And I select ‘Chicago’ from ‘xpath://ticket-form/ destination’
 And I wait 3 seconds
  • 27. Given I go to ‘/tickets.php’
 And I select ‘Brussels’ from ‘xpath://ticket-form/ origin’
 And I select ‘Chicago’ from ‘xpath://ticket-form/ destination’
 And I wait 5 seconds Never part of anyone’s specification, ever! Antipattern #3:
 “And I wait…”!
  • 28. public function spin ($lambda) {
 while (true) {
 try {
 if ($lambda($this)) {
 return true;
 }
 }
 catch (Exception $e) {
 //and do nothing here
 } sleep(1); //wait and try again in a second
 }
 } $this->spin(function($context) {
 $context->getSession()->getPage()->findById('adults');
 }); " Spin functions!
  • 29. In review…not writing tests, discovering the specification
  • 30. As a user I want to be prevented from purchasing a child only journey from Brussels to Chicago So that…errr…???
  • 31. As the Company Lawyer I want to prevent customers purchasing a child only ticket on flights from Brussels to Chicago So that we’re compliant with regulations
  • 32. Given I go to ‘/tickets.php’
 And I select ‘0’ from ‘xpath://ticket-form/adults’
 And I select ‘2’ from ‘xpath://ticket-form/children’
 And I select ‘0’ from ‘xpath://ticket-form/youths’
 And I select ‘0’ from ‘xpath://ticket-form/seniors’
 And I click ‘xpath://ticket-form/submit’
 Then I should see “You cannot purchase child-only tickets for this journey”
 And I should be on ‘/tickets.php’

  • 33. Given I am on the ticket search page
 When search for tickets from “<origin>” to “<destination>” for “<num_adults”> adults, “<num_children>” and “<num_seniors> seniors
 Then I should see the child fare policy message
 And be on the ticket search page Examples:
 |origin |destination|num_adults|num_children|num_seniors|
 |Brussels|Chicago |0 |1 |0 |
 |Brussels|Chicago |0 |2 |0 |
 |Brussels|Chicago |0 |3 |0 |
 |Brussels|Chicago |0 |4 |0 |
 |Brussels|Chicago |0 |5 |0 |
 |Brussels|Capetown |0 |2 |0 |
 |Brussels|Capetown |0 |3 |0 |
 |Brussels|Capetown |0 |4 |0 |
 |Brussels|Capetown |0 |5 |0 |
  • 35. Links! Reading
 dannorth.net/introducing-bdd
 dannorth.net/2010/08/30/introducing-deliberate-discovery
 specificationbyexample.com/key_ideas.html
 “Domain Driven Design” Eric Evans (domainlanguage.com)
 lizkeogh.com/2010/02/02/theyre-not-user-stories Playing
 behat.org
 drupal.org/project/drupalextension
 code.google.com/p/selenium/wiki/PageObjects
 github.com/orangedigital/business-selector-extension
 github.com/BossaConsulting/phpspec2-expect