bdd - you're doing it all wrong!

Post on 16-Jul-2015

231 Views

Category:

Technology

1 Downloads

Preview:

Click to see full reader

TRANSCRIPT

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.nete: andrew@andrewl.net"

"

fluxus.io

"

"

What is Behavioural Driven Development?

Some common anti-patterns

“BDD is a second-generation, outside–in, pull-based, multiple-stakeholder, multiple-scale, high-automation, agile methodology.”

(Dan North)

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.

“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 URLsHard-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 messageAnd 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 messageAnd 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 messageAnd 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-bdddannorth.net/2010/08/30/introducing-deliberate-discoveryspecificationbyexample.com/key_ideas.html “Domain Driven Design” Eric Evans (domainlanguage.com) lizkeogh.com/2010/02/02/theyre-not-user-stories

Playingbehat.orgdrupal.org/project/drupalextensioncode.google.com/p/selenium/wiki/PageObjectsgithub.com/orangedigital/business-selector-extensiongithub.com/BossaConsulting/phpspec2-expect

top related