SlideShare a Scribd company logo
1 of 52
Download to read offline
Double Loop
TDD & BDD Done Right!
@jessicamauerhan | http://bit.ly/double-loop
@jessicamauerhan
PHP Engineer
Help Scout
https://helpscout.net/company/careers/
jessicamauerhan@gmail.com
jmauerhan.wordpress.com
https://bit.ly/double-loop
What is
Test Driven Development?
@jessicamauerhan | http://bit.ly/double-loop
Benefits of Test Driven Development
● Guides you to create a
well-abstracted and highly
modular system
● Makes software easier to change,
maintain and understand
● Promotes design patterns,
refactoring, and helps prevent
scope creep
● Complete test coverage
● Prevent and identify regressions
and mistakes
● Executable documentation
Primary Secondary
What is
Behavior Driven Development?
Behaviour-driven development is an “outside-in”
methodology. It starts at the outside by identifying
business outcomes, and then drills down into the
feature set that will achieve those outcomes. Each
feature is captured as a “story”, which defines the scope
of the feature along with its acceptance criteria.
Dan North, “What’s in a Story”
http://dannorth.net/whats-in-a-story
It’s the idea that you start by writing human-readable
sentences that describe a feature of your application
and how it should work, and only then implement this
behavior in software.
Behat Documentation
http://docs.behat.org/en/v2.5
@jessicamauerhan | http://bit.ly/double-loop
Why Practice BDD?
● Well Designed Code
● Automated Testing
● Implementation
● UI Testing
BDD Is Not About...
● Communication
● Collaboration
● Documentation
● Preventing Regressions
BDD Is About...
@jessicamauerhan | http://bit.ly/double-loop
Why Practice
Behavior Driven
Development?
“You can turn an idea for a
requirement into implemented,
tested, production-ready code
simply and effectively, as long as the
requirement is specific enough that
everyone knows what’s going on.”
Dan North, “What’s in a Story”
http://dannorth.net/whats-in-a-story
@jessicamauerhan | http://bit.ly/double-loop
Accuracy
Unit Tests describe accuracy
of code and prescribe
maintainable code
Suitability
Behavior Tests describe
suitability of software's
features for the end user
@jessicamauerhan | http://bit.ly/double-loop
Testing Pyramid
Maintenance
Coverage
Fragility
Duration
Cost
Number of Tests
Unit Tests
Behavior Tests
System Tests
(performance)
GUI
Tests
Unit
Behavior
System
GUI
Manual QA
Testing Ice Cream Cone
@jessicamauerhan | http://bit.ly/double-loop
The Vicious Cycle of the Testing Ice Cream Cone
Unit
Behavior
System
GUI
Manual QA
Non Testable
Code
More Expensive
Tests
Developers Don't
Run Tests
More Bugs
Developers Don't
Write Unit Tests
Add
Behavior
Test
Add
Unit
Test
Run Unit
Test
Add/Edit
Some Code
Refactor
Run All
Unit Tests
Run All
Behavior
Tests
Pass* Fail
Fail
Pass
Run
Behavior
Test Pass*
Fail
Fail Pass
Revert Changes
Jessica Mauerhan | @jessicamauerhan
Double Loop: TDD & BDD Done Right!
Feature
Done?
NoYes
* A test that passes the first time
before code has been written means
the test is inaccurate or poorly
written, not added to the test suite,
or the code/feature already exists.
Add
Behavior
Test
@jessicamauerhan | http://bit.ly/double-loop
Parts of
a Behavior Test
● Feature: Gherkin
● Test Code
● BDD Framework /
Test Runner
@jessicamauerhan | http://bit.ly/double-loop
Gherkin
● Business Readable, Domain
Specific Language
● Living Documentation / User
Manual
● User Story with Narrative
● Contains at least one
Scenario: Acceptance Criteria
@jessicamauerhan | http://bit.ly/double-loop
● Narrative
○ As a [role]
I want [feature]
So that [benefit / business reason]
○ Use “5 Whys” to determine narrative
As an Account Holder
I want to withdraw cash from an ATM
So that I can get money when the bank is closed
Scenario: Account has sufficient funds
Given the account has a balance
And the card is valid
And the machine contains at least the amount of my balance
When I request an amount less than or equal to my balance
Then the ATM should dispense that amount
And the amount should be subtracted from my account balance
And the card should be returned
Scenario: Account has insufficient funds
Given the card is valid
When I request an amount greater than my balance
Then the ATM should not dispense any money
And the ATM should say there are insufficient funds
And my account balance should not change
And the card should be returned
● Feature: Short, Descriptive, Action
● Acceptance Criteria: Scenarios
○ Given: Exact Context
○ When: Action/Event
○ Then: Outcomes
○ And/But: More of the same...
●
Feature: Account Holder Withdraws Cash
@jessicamauerhan | http://bit.ly/double-loop
As a user viewing a broadcast page before the broadcast starts
I want to see a countdown timer
So that I can know how long until the broadcast actually starts
Scenario: View Countdown before Broadcast
Given I view the “Future Broadcast” broadcast
Then I should see "Future Broadcast" on the page
And I should see "Future Broadcast Author" on the page
And I should see "This broadcast begins at 6:00 pm EST" on the
page
And I should see a countdown timer
Feature: Display Countdown Timer before Broadcast
Process
● Author describes Feature with
implementation specific
example
● Developer adds fixture data
Issues
● Test only works before 6pm
● What is the intent?
● Confusion for business users
@jessicamauerhan | http://bit.ly/double-loop
As a user viewing a broadcast page before the broadcast starts
I want to see a countdown timer
So that I can know how long until the broadcast actually starts
Scenario: View Countdown before Broadcast
Given there is a broadcast scheduled for the future
When I view that broadcast’s page
Then I should see the broadcast title
And I should see the broadcast author’s name
And I should see "This broadcast begins at" followed by the start
time in EST
And I should see a countdown timer
Feature: View Countdown before Broadcast Changes
● Given now explains exact
context
● Test is no longer
time-dependent
● Intent - not implementation
Why?
● Overall understanding
● Communication value
● Help identify poorly written
code
@jessicamauerhan | http://bit.ly/double-loop
Feature: Customer Views Product and Services Catalog
As a customer
I want to view the product catalog
So that I can browse products and services
Scenario: Customer views Product Catalog
Given I view the catalog
When I select a state from the list of states
Then I should see the list of products for sale
Scenario: Display Local Services in Product Catalog
Given the company has a regional office in a state
When I view the catalog
And I select that state from the list of states
Then I should see the list of services offered
echo '<h1>Products</h1>';
foreach ($products AS $product) {
echo '<p>' . $product->getName() . '</p>';
}
echo '<h1>Services</h1>';
foreach ($services AS $service) {
echo '<p>' . $service->getName() . '</p>';
}
Scenario: Don’t Display Local Services in Product Catalog For States
With No Regional Office
Given the company does not have a regional office in a
state
When I view the catalog
And I select that state from the list of states
Then I should not see a list of services offered
@jessicamauerhan | http://bit.ly/double-loop
Feature: Customer Views Product and Services Catalog
As a customer
I want to view the product catalog
So that I can browse products and services
Scenario: Customer views Product Catalog
Given I view the catalog
When I select a state from the list of states
Then I should see the list of products for sale
Scenario: Display Local Services in Product Catalog
Given the company has a regional office in a state
When I view the catalog
And I select that state from the list of states
Then I should see the list of services offered
Scenario: Don’t Display Local Services in Product Catalog For States
With No Regional Office
Given the company does not have a regional office in a
state
When I view the catalog
And I select that state from the list of states
Then I should not see a list of services offered
echo '<h1>Products</h1>';
foreach ($products AS $product) {
echo '<p>' . $product->getName() . '</p>';
}
if(count($services) > 0) {
echo '<h1>Services</h1>';
foreach ($services AS $service) {
echo '<p>' . $service->getName() . '</p>';
}
}
@jessicamauerhan | http://bit.ly/double-loop
Writing Great Features
● Exact Context
● Independent Scenarios &
Features
● Intention, not Implementation
● Defined Narrative
● All Paths Explored
Feature “Smells”
● Time Dependency
● Interdependency
● Multi-Scenario Scenarios
● Missing Scenarios
● Overuse of Variables
● Examples of Behavior
(Implementation, not Intention)
@jessicamauerhan | http://bit.ly/double-loop
Parts of
a Behavior Test
● Feature: Gherkin
● Test Code
● BDD Framework /
Test Runner
@jessicamauerhan | http://bit.ly/double-loop
BDD Frameworks / Test Runners
● Java - JBehave, Cucumber and more
● Ruby - Cucumber
● PHP - Behat
● JavaScript - cucumber.js, jasmine
● ...
@jessicamauerhan | http://bit.ly/double-loop
Scenario: Customer views
Product Catalog
Given I view the catalog
When I select a state from the list
of states
Then I should see the list of
products for sale
Behat Code/**
* @Given I view the catalog
*/
public function iViewTheCatalog()
{
$this->visit('catalog');
}
/**
* @When I select a state from the list of states
*/
public function iSelectAStateFromTheListOfStates()
{
$this->selectOption('states', rand(1, 52));
}
/**
* @Then I should see the list of products for sale
*/
public function iShouldSeeTheListOfProductsForSale()
{
$productsDiv = $this->getSession()
->getPage()
->find('css', '#products');
Assertion::notNull($productsDiv);
}
Add
Behavior
Test
Run
Behavior
Test Pass*
@jessicamauerhan | http://bit.ly/double-loop
Double Loop: TDD & BDD Done Right!
* A test that passes the first time
before code has been written means
the test is inaccurate or poorly
written, not added to the test suite,
or the code/feature already exists.
@jessicamauerhan | http://bit.ly/double-loop
Parts of
a Behavior Test
● Feature: Gerkhin
● Test Code
● BDD Framework /
Test Runner
Add
Behavior
Test
Add
Unit
Test
Run
Behavior
Test Pass*
Fail
Double Loop: TDD & BDD Done Right!
* A test that passes the first time
before code has been written means
the test is inaccurate or poorly
written, not added to the test suite,
or the code/feature already exists.
@jessicamauerhan | http://bit.ly/double-loop
@jessicamauerhan | http://bit.ly/double-loop
Writing Unit Tests
What is a unit?
● Unit: As small as possible
● Design and Describe behavior
○ Setup scenario for behavior
○ Cause behavior to occur
○ Assert result is as expected
● Verbose and Descriptive
Names
Add
Behavior
Test
Add
Unit
Test
Run Unit
Test
Run
Behavior
Test Pass*
Fail
Double Loop: TDD & BDD Done Right!
* A test that passes the first time
before code has been written means
the test is inaccurate or poorly
written, not added to the test suite,
or the code/feature already exists.
@jessicamauerhan | http://bit.ly/double-loop
@jessicamauerhan | http://bit.ly/double-loop
Executing Unit
Tests
● Ensures test fails
when code is broken
● Ensures test is added
to suite
● Tells you exactly what
to do next
Always execute before writing
production code
Add
Behavior
Test
Add
Unit
Test
Run Unit
Test
Add/Edit
Some Code
Fail
Run
Behavior
Test Pass*
Fail
Double Loop: TDD & BDD Done Right!
* A test that passes the first time
before code has been written means
the test is inaccurate or poorly
written, not added to the test suite,
or the code/feature already exists.
@jessicamauerhan | http://bit.ly/double-loop
@jessicamauerhan | http://bit.ly/double-loop
Writing Code
Just Enough
● Add just enough code to pass
the test
● Avoid over abstracting or
adding untested logic
@jessicamauerhan | http://bit.ly/double-loop
Three "C" Types of Unit Tests
Contract
Unit adheres to
the contract
Correctness
Unit works
correctly
Collaboration
Unit talks to
collaborators
correctly
"Integration Testing"
Uses Assertions
Test Doubles: None, or Dummies, Stubs
and Fakes.
Or Expects Exception
Uses
Expectations
Test Doubles:
Mocks & Spies
New Class
For User
Registration
Class:
Registration
Service
Unit Tests
Registration Service
Correctness
Third Party
Service API
(Mailer)
Integrated
Test
MailChimp API
Forgot
Password
Weekly
Newsletter
Direct
Message
Exciting
Event
Reminder!
TDD: Integration Testing with Contract & Collaboration Tests
@jessicamauerhan | http://bit.ly/double-loop
New Class
For User
Registration
Class:
Registration
Service
Third Party
Service API
(Mailer)
Collaborator:
Mailer
Mailer
Contract
(Interface /
Abstract)
Mailer
Interface
Test Double
Persistence
Layer
Persistence
Layer
(Interface /
Abstract)
Persistence
Layer
Test Double
Fully Unit Tested &
Implemented Class:
Registration
Service
Unit Tests
Registration Service
Correctness
Collaboration
Tests
Collaboration
Tests
TDD: Integration Testing with Contract & Collaboration Tests
@jessicamauerhan | http://bit.ly/double-loop
Third Party
Service API
(Mailer)
Mailer
Implementation
Class:
Mailchimp
Adapter
New Class
For User
Registration
Class:
Registration
Service
Collaborator:
Mailer
Mailer
Contract
(Interface /
Abstract)
Mailer
Interface
Test Double
Persistence
Layer
Persistence
Layer
(Interface /
Abstract)
Persistence
Layer
Test Double
Fully Unit Tested &
Implemented Class:
Registration
Service
Unit Tests
Registration Service
Correctness
Collaboration
Tests
Collaboration
Tests
Third Party Tool:
MailChimp API
(This is a Contract)
Mailchimp
API Double
Fully Unit Tested &
Implemented Class:
Mailchimp
Adapter
Correctness
Unit Tests
Contract
Tests
Collaboration
Tests
TDD: Integration Testing with Contract & Collaboration Tests
@jessicamauerhan | http://bit.ly/double-loop
Mailer
Implementation
Class:
SendBlue
Adapter
New Class
For User
Registration
Class:
Registration
Service
Third Party
Service API
(Mailer)
Collaborator:
Mailer
Mailer
Contract
(Interface /
Abstract)
Mailer
Interface
Test Double
Persistence
Layer
Persistence
Layer
(Interface /
Abstract)
Persistence
Layer
Test Double
Fully Unit Tested &
Implemented Class:
Registration
Service
Unit Tests
Registration Service
Correctness
Collaboration
Tests
Collaboration
Tests
Third Party Tool:
SendBlue
(This is a Contract)
Third Party Tool:
SendBlue
(This is a Contract)
SendBlue
API Double
Fully Unit Tested &
Implemented Class:
SendBlue
Adapter
Class:
SendBlue
Adapter
Correctness
Unit Tests
Contract
Tests
Collaboration
Tests
TDD: Integration Testing with Contract & Collaboration Tests
Forgot
Password
Weekly
Newsletter
Direct
Message
Exciting
Event
Reminder!
@jessicamauerhan | http://bit.ly/double-loop
@jessicamauerhan | http://bit.ly/double-loop
Proof-Of-Concept (not tested)
$dsn = 'pgsql:dbname=test;host=db';
$dbUser = 'postgres';
$dbPass = 'postgres';
$pdo = new PDO($dsn, $dbUser, $dbPass);
$email = 'jane.doe@gmail.com';
$sql = "SELECT count(id) FROM users WHERE email = :email";
$statement = $pdo->prepare($sql);
$statement->execute(['email' => $email]);
$result = $statement->fetchColumn();
var_dump($result);
@jessicamauerhan | http://bit.ly/double-loop
PdoUserRepositoryTest.php
//Collaboration
public function testEmailExistsPreparesStatement()
{
$sql = "SELECT count(id) FROM users ".
"WHERE email = :email";
$stmt = $this->createMock(PDOStatement::class);
$pdo = this->createMock(PDO::class);
$pdo->expects($this->once())->method('prepare')
->with($sql)->willReturn($stmt);
$repo = new PdoUserRepository($pdo);
$repo->emailExists('test@gmail.com');
}
PdoUserRepository.php
public function emailExists(string $email): bool
{
$sql = "SELECT count(id) FROM users ".
"WHERE email = :email";
$statement = $this->pdo->prepare($sql);
}
@jessicamauerhan | http://bit.ly/double-loop
PdoUserRepositoryTest.php
//Collaboration
public function testEmailExistsExecutesStatement()
{
$email = 'jdoe@gmail.com';
$stmt = $this->createMock(PDOStatement::class);
$stmt>expects($this->once())
->method('execute')
->with(['email'=>$email]);
$pdo = this->createMock(PDO::class);
$pdo->method('prepare')->willReturn($statement);
$repo = new PdoUserRepository($pdo);
$repo->emailExists($email);
}
PdoUserRepository.php
public function emailExists(string $email): bool
{
$sql = "SELECT count(id) FROM users ".
"WHERE email = :email";
$statement = $this->pdo->prepare($sql);
}
public function emailExists(string $email): bool
{
$sql = "SELECT count(id) FROM users ".
"WHERE email = :email";
$statement = $this->pdo->prepare($sql);
$statement->execute(['email' => $email]);
}
@jessicamauerhan | http://bit.ly/double-loop
PdoUserRepositoryTest.php
//Correctness
public function
testEmailExistsReturnsTrueWhenCountGreaterThanZero()
{
$stmt = $this->createMock(PDOStatement::class);
$stmt->method('fetchColumn')
->willReturn(1);
$pdo = this->createMock(PDO::class);
$pdo->method('prepare')
->willReturn($statement);
$repo = new PdoUserRepository($pdo);
$this->assertTrue(
$repo->emailExists('test@gmail.com')
);
}
PdoUserRepository.php
public function emailExists(string $email): bool
{
$sql = "SELECT count(id) FROM users ".
"WHERE email = :email";
$statement = $this->pdo->prepare($sql);
$statement->execute(['email' => $email]);
}
public function emailExists(string $email): bool
{
$sql = "SELECT count(id) FROM users ".
"WHERE email = :email";
$statement = $this->pdo->prepare($sql);
$statement->execute(['email' => $email]);
$result = $statement->fetchColumn();
return $result > 0;
}
@jessicamauerhan | http://bit.ly/double-loop
PdoUserRepositoryTest.php
//Correctness
public function
testEmailExistsReturnsFalseWhenCountZero()
{
$stmt = $this->createMock(PDOStatement::class);
$stmt->method('fetchColumn')
->willReturn(0);
$pdo = this->createMock(PDO::class);
$pdo->method('prepare')
->willReturn($statement);
$repo = new PdoUserRepository($pdo);
$this->assertFalse(
$repo->emailExists('test@gmail.com')
);
}
PdoUserRepository.php
public function emailExists(string $email): bool
{
$sql = "SELECT count(id) FROM users ".
"WHERE email = :email";
$statement = $this->pdo->prepare($sql);
$statement->execute(['email' => $email]);
$result = $statement->fetchColumn();
return $result > 0;
}
@jessicamauerhan | http://bit.ly/double-loop
PdoUserRepositoryTest.php
//Contract
public function
testEmailExistsThrowsUnableToCheckEmailWhenPDOExcept
ion()
{
$this->expectException(UnableToCheckEmail::class);
$pdoException = new PdoException();
$pdo = this->createMock(PDO::class);
$pdo->method('prepare')
->willThrow($pdoException);
$repo = new PdoUserRepository($pdo);
$repo->emailExists('test@gmail.com');
}
PdoUserRepository.php
public function emailExists(string $email): bool
{
$sql = "SELECT count(id) FROM users ".
"WHERE email = :email";
$statement = $this->pdo->prepare($sql);
$statement->execute(['email' => $email]);
$result = $statement->fetchColumn();
return $result > 0;
}
public function emailExists(string $email): bool
{
$sql = "SELECT count(id) FROM users ".
"WHERE email = :email";
try {
$statement = $this->pdo->prepare($sql);
$statement->execute(['email' => $email]);
$result = $statement->fetchColumn();
return $result > 0;
} catch (PDOException $PDOException) {
throw new UnableToCheckEmail();
}
}
Maintenance
Coverage
Fragility
Duration
Cost
Number of Tests
Isolated Unit Tests
Correctness, Contract & Collaboration
Integration Testing
Multiple Components Integrated
Tested for Correctness & Communication
Behavior Tests
Fully Integrated User Experience
System Tests
load balance, performance, security
GUI
Tests
Add
Behavior
Test
Add
Unit
Test
Run Unit
Test
Add/Edit
Some Code
Fail
Run
Behavior
Test Pass*
Fail
Double Loop: TDD & BDD Done Right!
* A test that passes the first time
before code has been written means
the test is inaccurate or poorly
written, not added to the test suite,
or the code/feature already exists.
@jessicamauerhan | http://bit.ly/double-loop
@jessicamauerhan | http://bit.ly/double-loop
Failing Test or
Test Suite?
Revert!
● If the test fails, revert your
work
● Commit small changes, often!
Add
Behavior
Test
Add
Unit
Test
Run Unit
Test
Add/Edit
Some Code
Refactor
Run All
Unit Tests
Pass* Fail
Fail
Pass
Run
Behavior
Test Pass*
Fail
Revert Changes
Double Loop: TDD & BDD Done Right!
Feature
Done?
NoYes
* A test that passes the first time
before code has been written means
the test is inaccurate or poorly
written, not added to the test suite,
or the code/feature already exists.
@jessicamauerhan | http://bit.ly/double-loop
@jessicamauerhan | http://bit.ly/double-loop
Refactoring
The process of
restructuring code
without changing its
behavior
@jessicamauerhan | http://bit.ly/double-loop
Refactoring
● Improving
non-functional aspects
● Removing duplication
● Renaming
● Simplifying
Unit Tests Always Passing!
● Changes that would
break a unit test
● New functionality that
is not tested
New Unit Tests Fail, Then Pass
Adding Functionality
Add
Behavior
Test
Add
Unit
Test
Run Unit
Test
Add/Edit
Some Code
Refactor
Run All
Unit Tests
Run All
Behavior
Tests
Pass* Fail
Fail
Pass
Run
Behavior
Test Pass*
Fail
Fail Pass
Revert Changes
Double Loop: TDD & BDD Done Right!
Feature
Done?
NoYes
* A test that passes the first time
before code has been written means
the test is inaccurate or poorly
written, not added to the test suite,
or the code/feature already exists.
@jessicamauerhan | http://bit.ly/double-loop
@jessicamauerhan | http://bit.ly/double-loop
Thank You!
Double Loop:
TDD & BDD Done Right!
Feedback & Questions?
Welcome & Encouraged!
@jessicamauerhan
jessicamauerhan@gmail.com
jmauerhan.wordpress.com

More Related Content

What's hot

Code Review Tool Evaluation
Code Review Tool EvaluationCode Review Tool Evaluation
Code Review Tool EvaluationKate Semizhon
 
Introduction to web programming with JavaScript
Introduction to web programming with JavaScriptIntroduction to web programming with JavaScript
Introduction to web programming with JavaScriptT11 Sessions
 
Guide to Destroying Codebases The Demise of Clever Code
Guide to Destroying Codebases   The Demise of Clever CodeGuide to Destroying Codebases   The Demise of Clever Code
Guide to Destroying Codebases The Demise of Clever CodeGabor Varadi
 
Hexagonal architecture - message-oriented software design
Hexagonal architecture  - message-oriented software designHexagonal architecture  - message-oriented software design
Hexagonal architecture - message-oriented software designMatthias Noback
 
ATDD Using Robot Framework
ATDD Using Robot FrameworkATDD Using Robot Framework
ATDD Using Robot FrameworkPekka Klärck
 
Introduction to Kotlin Language and its application to Android platform
Introduction to Kotlin Language and its application to Android platformIntroduction to Kotlin Language and its application to Android platform
Introduction to Kotlin Language and its application to Android platformEastBanc Tachnologies
 
ePub 3, HTML 5 & CSS 3 (+ Fixed-Layout)
ePub 3, HTML 5 & CSS 3 (+ Fixed-Layout)ePub 3, HTML 5 & CSS 3 (+ Fixed-Layout)
ePub 3, HTML 5 & CSS 3 (+ Fixed-Layout)Clément Wehrung
 
BDD with SpecFlow and Selenium
BDD with SpecFlow and SeleniumBDD with SpecFlow and Selenium
BDD with SpecFlow and SeleniumLiraz Shay
 
Hexagonal Architecture.pdf
Hexagonal Architecture.pdfHexagonal Architecture.pdf
Hexagonal Architecture.pdfVladimirRadzivil
 
The Art of Unit Testing - Towards a Testable Design
The Art of Unit Testing - Towards a Testable DesignThe Art of Unit Testing - Towards a Testable Design
The Art of Unit Testing - Towards a Testable DesignVictor Rentea
 
Bdd – with cucumber and gherkin
Bdd – with cucumber and gherkinBdd – with cucumber and gherkin
Bdd – with cucumber and gherkinArati Joshi
 
Align Your Workflow in the Raiser's Edge for Maximum Impact
Align Your Workflow in the Raiser's Edge for Maximum ImpactAlign Your Workflow in the Raiser's Edge for Maximum Impact
Align Your Workflow in the Raiser's Edge for Maximum ImpactBlackbaud
 
Performance Tuning - Understanding Garbage Collection
Performance Tuning - Understanding Garbage CollectionPerformance Tuning - Understanding Garbage Collection
Performance Tuning - Understanding Garbage CollectionHaribabu Nandyal Padmanaban
 
Bloc for Pharo: Current State and Future Perspective
Bloc for Pharo: Current State and Future PerspectiveBloc for Pharo: Current State and Future Perspective
Bloc for Pharo: Current State and Future PerspectiveESUG
 

What's hot (20)

Introduction to robot framework
Introduction to robot frameworkIntroduction to robot framework
Introduction to robot framework
 
Code Review Tool Evaluation
Code Review Tool EvaluationCode Review Tool Evaluation
Code Review Tool Evaluation
 
Introduction to web programming with JavaScript
Introduction to web programming with JavaScriptIntroduction to web programming with JavaScript
Introduction to web programming with JavaScript
 
Guide to Destroying Codebases The Demise of Clever Code
Guide to Destroying Codebases   The Demise of Clever CodeGuide to Destroying Codebases   The Demise of Clever Code
Guide to Destroying Codebases The Demise of Clever Code
 
Hexagonal architecture - message-oriented software design
Hexagonal architecture  - message-oriented software designHexagonal architecture  - message-oriented software design
Hexagonal architecture - message-oriented software design
 
Nunit
NunitNunit
Nunit
 
ATDD Using Robot Framework
ATDD Using Robot FrameworkATDD Using Robot Framework
ATDD Using Robot Framework
 
Testing Tools
Testing ToolsTesting Tools
Testing Tools
 
Introduction to Kotlin Language and its application to Android platform
Introduction to Kotlin Language and its application to Android platformIntroduction to Kotlin Language and its application to Android platform
Introduction to Kotlin Language and its application to Android platform
 
ePub 3, HTML 5 & CSS 3 (+ Fixed-Layout)
ePub 3, HTML 5 & CSS 3 (+ Fixed-Layout)ePub 3, HTML 5 & CSS 3 (+ Fixed-Layout)
ePub 3, HTML 5 & CSS 3 (+ Fixed-Layout)
 
BDD with SpecFlow and Selenium
BDD with SpecFlow and SeleniumBDD with SpecFlow and Selenium
BDD with SpecFlow and Selenium
 
Hexagonal Architecture.pdf
Hexagonal Architecture.pdfHexagonal Architecture.pdf
Hexagonal Architecture.pdf
 
ENOVIA v6 R2013x Tips and Tricks
ENOVIA v6 R2013x Tips and TricksENOVIA v6 R2013x Tips and Tricks
ENOVIA v6 R2013x Tips and Tricks
 
The Art of Unit Testing - Towards a Testable Design
The Art of Unit Testing - Towards a Testable DesignThe Art of Unit Testing - Towards a Testable Design
The Art of Unit Testing - Towards a Testable Design
 
Bdd – with cucumber and gherkin
Bdd – with cucumber and gherkinBdd – with cucumber and gherkin
Bdd – with cucumber and gherkin
 
Align Your Workflow in the Raiser's Edge for Maximum Impact
Align Your Workflow in the Raiser's Edge for Maximum ImpactAlign Your Workflow in the Raiser's Edge for Maximum Impact
Align Your Workflow in the Raiser's Edge for Maximum Impact
 
BDD & Cucumber
BDD & CucumberBDD & Cucumber
BDD & Cucumber
 
Api Testing.pdf
Api Testing.pdfApi Testing.pdf
Api Testing.pdf
 
Performance Tuning - Understanding Garbage Collection
Performance Tuning - Understanding Garbage CollectionPerformance Tuning - Understanding Garbage Collection
Performance Tuning - Understanding Garbage Collection
 
Bloc for Pharo: Current State and Future Perspective
Bloc for Pharo: Current State and Future PerspectiveBloc for Pharo: Current State and Future Perspective
Bloc for Pharo: Current State and Future Perspective
 

Similar to Double Loop: TDD & BDD Done Right

Double Loop: TDD & BDD Done Right!
Double Loop: TDD & BDD Done Right!Double Loop: TDD & BDD Done Right!
Double Loop: TDD & BDD Done Right!Jessica Mauerhan
 
BDD Selenium for Agile Teams - User Stories
BDD Selenium for Agile Teams - User StoriesBDD Selenium for Agile Teams - User Stories
BDD Selenium for Agile Teams - User StoriesSauce Labs
 
Behat - Beyond the Basics (2016 - SunshinePHP)
Behat - Beyond the Basics (2016 - SunshinePHP)Behat - Beyond the Basics (2016 - SunshinePHP)
Behat - Beyond the Basics (2016 - SunshinePHP)Jessica Mauerhan
 
PHPSpec & Behat: Two Testing Tools That Write Code For You (#phptek edition)
PHPSpec & Behat: Two Testing Tools That Write Code For You (#phptek edition)PHPSpec & Behat: Two Testing Tools That Write Code For You (#phptek edition)
PHPSpec & Behat: Two Testing Tools That Write Code For You (#phptek edition)Joshua Warren
 
pnwphp - PHPSpec & Behat: Two Testing Tools That Write Code For You
pnwphp - PHPSpec & Behat: Two Testing Tools That Write Code For Youpnwphp - PHPSpec & Behat: Two Testing Tools That Write Code For You
pnwphp - PHPSpec & Behat: Two Testing Tools That Write Code For YouJoshua Warren
 
Behavior Driven Development with Cucumber
Behavior Driven Development with CucumberBehavior Driven Development with Cucumber
Behavior Driven Development with CucumberBrandon Keepers
 
Writing Software not Code with Cucumber
Writing Software not Code with CucumberWriting Software not Code with Cucumber
Writing Software not Code with CucumberBen Mabey
 
Talkin bout Flow - Meighan Brodkey WIT Devs
Talkin bout Flow - Meighan Brodkey WIT Devs Talkin bout Flow - Meighan Brodkey WIT Devs
Talkin bout Flow - Meighan Brodkey WIT Devs Meighan Brodkey
 
Using Error Budgets to Prioritize Work
Using Error Budgets to Prioritize WorkUsing Error Budgets to Prioritize Work
Using Error Budgets to Prioritize WorkNathen Harvey
 
Testing C# and ASP.net using Ruby
Testing C# and ASP.net using RubyTesting C# and ASP.net using Ruby
Testing C# and ASP.net using RubyBen Hall
 
Moving away from legacy code with BDD
Moving away from legacy code with BDDMoving away from legacy code with BDD
Moving away from legacy code with BDDKonstantin Kudryashov
 
BDD / cucumber /Capybara
BDD / cucumber /CapybaraBDD / cucumber /Capybara
BDD / cucumber /CapybaraShraddhaSF
 
Testable Requirements
Testable Requirements Testable Requirements
Testable Requirements Bharti Rupani
 
User Story Splitting
User Story SplittingUser Story Splitting
User Story Splittingtrishly
 

Similar to Double Loop: TDD & BDD Done Right (20)

Double Loop: TDD & BDD Done Right!
Double Loop: TDD & BDD Done Right!Double Loop: TDD & BDD Done Right!
Double Loop: TDD & BDD Done Right!
 
Double Loop
Double LoopDouble Loop
Double Loop
 
BDD Selenium for Agile Teams - User Stories
BDD Selenium for Agile Teams - User StoriesBDD Selenium for Agile Teams - User Stories
BDD Selenium for Agile Teams - User Stories
 
Behat - Beyond the Basics (2016 - SunshinePHP)
Behat - Beyond the Basics (2016 - SunshinePHP)Behat - Beyond the Basics (2016 - SunshinePHP)
Behat - Beyond the Basics (2016 - SunshinePHP)
 
PHPSpec & Behat: Two Testing Tools That Write Code For You (#phptek edition)
PHPSpec & Behat: Two Testing Tools That Write Code For You (#phptek edition)PHPSpec & Behat: Two Testing Tools That Write Code For You (#phptek edition)
PHPSpec & Behat: Two Testing Tools That Write Code For You (#phptek edition)
 
pnwphp - PHPSpec & Behat: Two Testing Tools That Write Code For You
pnwphp - PHPSpec & Behat: Two Testing Tools That Write Code For Youpnwphp - PHPSpec & Behat: Two Testing Tools That Write Code For You
pnwphp - PHPSpec & Behat: Two Testing Tools That Write Code For You
 
Behavior Driven Development with Cucumber
Behavior Driven Development with CucumberBehavior Driven Development with Cucumber
Behavior Driven Development with Cucumber
 
Continuous Quality
Continuous QualityContinuous Quality
Continuous Quality
 
Writing Software not Code with Cucumber
Writing Software not Code with CucumberWriting Software not Code with Cucumber
Writing Software not Code with Cucumber
 
User Stories
User StoriesUser Stories
User Stories
 
Talkin bout Flow - Meighan Brodkey WIT Devs
Talkin bout Flow - Meighan Brodkey WIT Devs Talkin bout Flow - Meighan Brodkey WIT Devs
Talkin bout Flow - Meighan Brodkey WIT Devs
 
Testable requirements
Testable requirementsTestable requirements
Testable requirements
 
Behat: Beyond the Basics
Behat: Beyond the BasicsBehat: Beyond the Basics
Behat: Beyond the Basics
 
Using Error Budgets to Prioritize Work
Using Error Budgets to Prioritize WorkUsing Error Budgets to Prioritize Work
Using Error Budgets to Prioritize Work
 
Cqrs api v2
Cqrs api v2Cqrs api v2
Cqrs api v2
 
Testing C# and ASP.net using Ruby
Testing C# and ASP.net using RubyTesting C# and ASP.net using Ruby
Testing C# and ASP.net using Ruby
 
Moving away from legacy code with BDD
Moving away from legacy code with BDDMoving away from legacy code with BDD
Moving away from legacy code with BDD
 
BDD / cucumber /Capybara
BDD / cucumber /CapybaraBDD / cucumber /Capybara
BDD / cucumber /Capybara
 
Testable Requirements
Testable Requirements Testable Requirements
Testable Requirements
 
User Story Splitting
User Story SplittingUser Story Splitting
User Story Splitting
 

Recently uploaded

Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmaticsKotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmaticscarlostorres15106
 
Maximizing Board Effectiveness 2024 Webinar.pptx
Maximizing Board Effectiveness 2024 Webinar.pptxMaximizing Board Effectiveness 2024 Webinar.pptx
Maximizing Board Effectiveness 2024 Webinar.pptxOnBoard
 
The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024Rafal Los
 
Pigging Solutions Piggable Sweeping Elbows
Pigging Solutions Piggable Sweeping ElbowsPigging Solutions Piggable Sweeping Elbows
Pigging Solutions Piggable Sweeping ElbowsPigging Solutions
 
08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking MenDelhi Call girls
 
Swan(sea) Song – personal research during my six years at Swansea ... and bey...
Swan(sea) Song – personal research during my six years at Swansea ... and bey...Swan(sea) Song – personal research during my six years at Swansea ... and bey...
Swan(sea) Song – personal research during my six years at Swansea ... and bey...Alan Dix
 
Factors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptxFactors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptxKatpro Technologies
 
08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking MenDelhi Call girls
 
GenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationGenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationMichael W. Hawkins
 
How to Remove Document Management Hurdles with X-Docs?
How to Remove Document Management Hurdles with X-Docs?How to Remove Document Management Hurdles with X-Docs?
How to Remove Document Management Hurdles with X-Docs?XfilesPro
 
SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024Scott Keck-Warren
 
Key Features Of Token Development (1).pptx
Key  Features Of Token  Development (1).pptxKey  Features Of Token  Development (1).pptx
Key Features Of Token Development (1).pptxLBM Solutions
 
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptxHampshireHUG
 
Human Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsHuman Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsMark Billinghurst
 
Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...
Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...
Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...HostedbyConfluent
 
Slack Application Development 101 Slides
Slack Application Development 101 SlidesSlack Application Development 101 Slides
Slack Application Development 101 Slidespraypatel2
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)Gabriella Davis
 
Handwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsHandwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsMaria Levchenko
 
Scaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationScaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationRadu Cotescu
 
Pigging Solutions in Pet Food Manufacturing
Pigging Solutions in Pet Food ManufacturingPigging Solutions in Pet Food Manufacturing
Pigging Solutions in Pet Food ManufacturingPigging Solutions
 

Recently uploaded (20)

Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmaticsKotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
 
Maximizing Board Effectiveness 2024 Webinar.pptx
Maximizing Board Effectiveness 2024 Webinar.pptxMaximizing Board Effectiveness 2024 Webinar.pptx
Maximizing Board Effectiveness 2024 Webinar.pptx
 
The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024
 
Pigging Solutions Piggable Sweeping Elbows
Pigging Solutions Piggable Sweeping ElbowsPigging Solutions Piggable Sweeping Elbows
Pigging Solutions Piggable Sweeping Elbows
 
08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men
 
Swan(sea) Song – personal research during my six years at Swansea ... and bey...
Swan(sea) Song – personal research during my six years at Swansea ... and bey...Swan(sea) Song – personal research during my six years at Swansea ... and bey...
Swan(sea) Song – personal research during my six years at Swansea ... and bey...
 
Factors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptxFactors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptx
 
08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men
 
GenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationGenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day Presentation
 
How to Remove Document Management Hurdles with X-Docs?
How to Remove Document Management Hurdles with X-Docs?How to Remove Document Management Hurdles with X-Docs?
How to Remove Document Management Hurdles with X-Docs?
 
SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024
 
Key Features Of Token Development (1).pptx
Key  Features Of Token  Development (1).pptxKey  Features Of Token  Development (1).pptx
Key Features Of Token Development (1).pptx
 
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
 
Human Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsHuman Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR Systems
 
Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...
Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...
Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...
 
Slack Application Development 101 Slides
Slack Application Development 101 SlidesSlack Application Development 101 Slides
Slack Application Development 101 Slides
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)
 
Handwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsHandwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed texts
 
Scaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationScaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organization
 
Pigging Solutions in Pet Food Manufacturing
Pigging Solutions in Pet Food ManufacturingPigging Solutions in Pet Food Manufacturing
Pigging Solutions in Pet Food Manufacturing
 

Double Loop: TDD & BDD Done Right

  • 1. Double Loop TDD & BDD Done Right! @jessicamauerhan | http://bit.ly/double-loop
  • 3. What is Test Driven Development?
  • 4. @jessicamauerhan | http://bit.ly/double-loop Benefits of Test Driven Development ● Guides you to create a well-abstracted and highly modular system ● Makes software easier to change, maintain and understand ● Promotes design patterns, refactoring, and helps prevent scope creep ● Complete test coverage ● Prevent and identify regressions and mistakes ● Executable documentation Primary Secondary
  • 5. What is Behavior Driven Development?
  • 6. Behaviour-driven development is an “outside-in” methodology. It starts at the outside by identifying business outcomes, and then drills down into the feature set that will achieve those outcomes. Each feature is captured as a “story”, which defines the scope of the feature along with its acceptance criteria. Dan North, “What’s in a Story” http://dannorth.net/whats-in-a-story
  • 7. It’s the idea that you start by writing human-readable sentences that describe a feature of your application and how it should work, and only then implement this behavior in software. Behat Documentation http://docs.behat.org/en/v2.5
  • 8. @jessicamauerhan | http://bit.ly/double-loop Why Practice BDD? ● Well Designed Code ● Automated Testing ● Implementation ● UI Testing BDD Is Not About... ● Communication ● Collaboration ● Documentation ● Preventing Regressions BDD Is About...
  • 9. @jessicamauerhan | http://bit.ly/double-loop Why Practice Behavior Driven Development? “You can turn an idea for a requirement into implemented, tested, production-ready code simply and effectively, as long as the requirement is specific enough that everyone knows what’s going on.” Dan North, “What’s in a Story” http://dannorth.net/whats-in-a-story
  • 10. @jessicamauerhan | http://bit.ly/double-loop Accuracy Unit Tests describe accuracy of code and prescribe maintainable code Suitability Behavior Tests describe suitability of software's features for the end user
  • 11. @jessicamauerhan | http://bit.ly/double-loop Testing Pyramid Maintenance Coverage Fragility Duration Cost Number of Tests Unit Tests Behavior Tests System Tests (performance) GUI Tests Unit Behavior System GUI Manual QA Testing Ice Cream Cone
  • 12. @jessicamauerhan | http://bit.ly/double-loop The Vicious Cycle of the Testing Ice Cream Cone Unit Behavior System GUI Manual QA Non Testable Code More Expensive Tests Developers Don't Run Tests More Bugs Developers Don't Write Unit Tests
  • 13. Add Behavior Test Add Unit Test Run Unit Test Add/Edit Some Code Refactor Run All Unit Tests Run All Behavior Tests Pass* Fail Fail Pass Run Behavior Test Pass* Fail Fail Pass Revert Changes Jessica Mauerhan | @jessicamauerhan Double Loop: TDD & BDD Done Right! Feature Done? NoYes * A test that passes the first time before code has been written means the test is inaccurate or poorly written, not added to the test suite, or the code/feature already exists.
  • 15. @jessicamauerhan | http://bit.ly/double-loop Parts of a Behavior Test ● Feature: Gherkin ● Test Code ● BDD Framework / Test Runner
  • 16. @jessicamauerhan | http://bit.ly/double-loop Gherkin ● Business Readable, Domain Specific Language ● Living Documentation / User Manual ● User Story with Narrative ● Contains at least one Scenario: Acceptance Criteria
  • 17. @jessicamauerhan | http://bit.ly/double-loop ● Narrative ○ As a [role] I want [feature] So that [benefit / business reason] ○ Use “5 Whys” to determine narrative As an Account Holder I want to withdraw cash from an ATM So that I can get money when the bank is closed Scenario: Account has sufficient funds Given the account has a balance And the card is valid And the machine contains at least the amount of my balance When I request an amount less than or equal to my balance Then the ATM should dispense that amount And the amount should be subtracted from my account balance And the card should be returned Scenario: Account has insufficient funds Given the card is valid When I request an amount greater than my balance Then the ATM should not dispense any money And the ATM should say there are insufficient funds And my account balance should not change And the card should be returned ● Feature: Short, Descriptive, Action ● Acceptance Criteria: Scenarios ○ Given: Exact Context ○ When: Action/Event ○ Then: Outcomes ○ And/But: More of the same... ● Feature: Account Holder Withdraws Cash
  • 18. @jessicamauerhan | http://bit.ly/double-loop As a user viewing a broadcast page before the broadcast starts I want to see a countdown timer So that I can know how long until the broadcast actually starts Scenario: View Countdown before Broadcast Given I view the “Future Broadcast” broadcast Then I should see "Future Broadcast" on the page And I should see "Future Broadcast Author" on the page And I should see "This broadcast begins at 6:00 pm EST" on the page And I should see a countdown timer Feature: Display Countdown Timer before Broadcast Process ● Author describes Feature with implementation specific example ● Developer adds fixture data Issues ● Test only works before 6pm ● What is the intent? ● Confusion for business users
  • 19. @jessicamauerhan | http://bit.ly/double-loop As a user viewing a broadcast page before the broadcast starts I want to see a countdown timer So that I can know how long until the broadcast actually starts Scenario: View Countdown before Broadcast Given there is a broadcast scheduled for the future When I view that broadcast’s page Then I should see the broadcast title And I should see the broadcast author’s name And I should see "This broadcast begins at" followed by the start time in EST And I should see a countdown timer Feature: View Countdown before Broadcast Changes ● Given now explains exact context ● Test is no longer time-dependent ● Intent - not implementation Why? ● Overall understanding ● Communication value ● Help identify poorly written code
  • 20. @jessicamauerhan | http://bit.ly/double-loop Feature: Customer Views Product and Services Catalog As a customer I want to view the product catalog So that I can browse products and services Scenario: Customer views Product Catalog Given I view the catalog When I select a state from the list of states Then I should see the list of products for sale Scenario: Display Local Services in Product Catalog Given the company has a regional office in a state When I view the catalog And I select that state from the list of states Then I should see the list of services offered echo '<h1>Products</h1>'; foreach ($products AS $product) { echo '<p>' . $product->getName() . '</p>'; } echo '<h1>Services</h1>'; foreach ($services AS $service) { echo '<p>' . $service->getName() . '</p>'; } Scenario: Don’t Display Local Services in Product Catalog For States With No Regional Office Given the company does not have a regional office in a state When I view the catalog And I select that state from the list of states Then I should not see a list of services offered
  • 21. @jessicamauerhan | http://bit.ly/double-loop Feature: Customer Views Product and Services Catalog As a customer I want to view the product catalog So that I can browse products and services Scenario: Customer views Product Catalog Given I view the catalog When I select a state from the list of states Then I should see the list of products for sale Scenario: Display Local Services in Product Catalog Given the company has a regional office in a state When I view the catalog And I select that state from the list of states Then I should see the list of services offered Scenario: Don’t Display Local Services in Product Catalog For States With No Regional Office Given the company does not have a regional office in a state When I view the catalog And I select that state from the list of states Then I should not see a list of services offered echo '<h1>Products</h1>'; foreach ($products AS $product) { echo '<p>' . $product->getName() . '</p>'; } if(count($services) > 0) { echo '<h1>Services</h1>'; foreach ($services AS $service) { echo '<p>' . $service->getName() . '</p>'; } }
  • 22. @jessicamauerhan | http://bit.ly/double-loop Writing Great Features ● Exact Context ● Independent Scenarios & Features ● Intention, not Implementation ● Defined Narrative ● All Paths Explored Feature “Smells” ● Time Dependency ● Interdependency ● Multi-Scenario Scenarios ● Missing Scenarios ● Overuse of Variables ● Examples of Behavior (Implementation, not Intention)
  • 23. @jessicamauerhan | http://bit.ly/double-loop Parts of a Behavior Test ● Feature: Gherkin ● Test Code ● BDD Framework / Test Runner
  • 24. @jessicamauerhan | http://bit.ly/double-loop BDD Frameworks / Test Runners ● Java - JBehave, Cucumber and more ● Ruby - Cucumber ● PHP - Behat ● JavaScript - cucumber.js, jasmine ● ...
  • 25. @jessicamauerhan | http://bit.ly/double-loop Scenario: Customer views Product Catalog Given I view the catalog When I select a state from the list of states Then I should see the list of products for sale Behat Code/** * @Given I view the catalog */ public function iViewTheCatalog() { $this->visit('catalog'); } /** * @When I select a state from the list of states */ public function iSelectAStateFromTheListOfStates() { $this->selectOption('states', rand(1, 52)); } /** * @Then I should see the list of products for sale */ public function iShouldSeeTheListOfProductsForSale() { $productsDiv = $this->getSession() ->getPage() ->find('css', '#products'); Assertion::notNull($productsDiv); }
  • 26. Add Behavior Test Run Behavior Test Pass* @jessicamauerhan | http://bit.ly/double-loop Double Loop: TDD & BDD Done Right! * A test that passes the first time before code has been written means the test is inaccurate or poorly written, not added to the test suite, or the code/feature already exists.
  • 27. @jessicamauerhan | http://bit.ly/double-loop Parts of a Behavior Test ● Feature: Gerkhin ● Test Code ● BDD Framework / Test Runner
  • 28. Add Behavior Test Add Unit Test Run Behavior Test Pass* Fail Double Loop: TDD & BDD Done Right! * A test that passes the first time before code has been written means the test is inaccurate or poorly written, not added to the test suite, or the code/feature already exists. @jessicamauerhan | http://bit.ly/double-loop
  • 29. @jessicamauerhan | http://bit.ly/double-loop Writing Unit Tests What is a unit? ● Unit: As small as possible ● Design and Describe behavior ○ Setup scenario for behavior ○ Cause behavior to occur ○ Assert result is as expected ● Verbose and Descriptive Names
  • 30. Add Behavior Test Add Unit Test Run Unit Test Run Behavior Test Pass* Fail Double Loop: TDD & BDD Done Right! * A test that passes the first time before code has been written means the test is inaccurate or poorly written, not added to the test suite, or the code/feature already exists. @jessicamauerhan | http://bit.ly/double-loop
  • 31. @jessicamauerhan | http://bit.ly/double-loop Executing Unit Tests ● Ensures test fails when code is broken ● Ensures test is added to suite ● Tells you exactly what to do next Always execute before writing production code
  • 32. Add Behavior Test Add Unit Test Run Unit Test Add/Edit Some Code Fail Run Behavior Test Pass* Fail Double Loop: TDD & BDD Done Right! * A test that passes the first time before code has been written means the test is inaccurate or poorly written, not added to the test suite, or the code/feature already exists. @jessicamauerhan | http://bit.ly/double-loop
  • 33. @jessicamauerhan | http://bit.ly/double-loop Writing Code Just Enough ● Add just enough code to pass the test ● Avoid over abstracting or adding untested logic
  • 34. @jessicamauerhan | http://bit.ly/double-loop Three "C" Types of Unit Tests Contract Unit adheres to the contract Correctness Unit works correctly Collaboration Unit talks to collaborators correctly "Integration Testing" Uses Assertions Test Doubles: None, or Dummies, Stubs and Fakes. Or Expects Exception Uses Expectations Test Doubles: Mocks & Spies
  • 35. New Class For User Registration Class: Registration Service Unit Tests Registration Service Correctness Third Party Service API (Mailer) Integrated Test MailChimp API Forgot Password Weekly Newsletter Direct Message Exciting Event Reminder! TDD: Integration Testing with Contract & Collaboration Tests @jessicamauerhan | http://bit.ly/double-loop
  • 36. New Class For User Registration Class: Registration Service Third Party Service API (Mailer) Collaborator: Mailer Mailer Contract (Interface / Abstract) Mailer Interface Test Double Persistence Layer Persistence Layer (Interface / Abstract) Persistence Layer Test Double Fully Unit Tested & Implemented Class: Registration Service Unit Tests Registration Service Correctness Collaboration Tests Collaboration Tests TDD: Integration Testing with Contract & Collaboration Tests @jessicamauerhan | http://bit.ly/double-loop
  • 37. Third Party Service API (Mailer) Mailer Implementation Class: Mailchimp Adapter New Class For User Registration Class: Registration Service Collaborator: Mailer Mailer Contract (Interface / Abstract) Mailer Interface Test Double Persistence Layer Persistence Layer (Interface / Abstract) Persistence Layer Test Double Fully Unit Tested & Implemented Class: Registration Service Unit Tests Registration Service Correctness Collaboration Tests Collaboration Tests Third Party Tool: MailChimp API (This is a Contract) Mailchimp API Double Fully Unit Tested & Implemented Class: Mailchimp Adapter Correctness Unit Tests Contract Tests Collaboration Tests TDD: Integration Testing with Contract & Collaboration Tests @jessicamauerhan | http://bit.ly/double-loop
  • 38. Mailer Implementation Class: SendBlue Adapter New Class For User Registration Class: Registration Service Third Party Service API (Mailer) Collaborator: Mailer Mailer Contract (Interface / Abstract) Mailer Interface Test Double Persistence Layer Persistence Layer (Interface / Abstract) Persistence Layer Test Double Fully Unit Tested & Implemented Class: Registration Service Unit Tests Registration Service Correctness Collaboration Tests Collaboration Tests Third Party Tool: SendBlue (This is a Contract) Third Party Tool: SendBlue (This is a Contract) SendBlue API Double Fully Unit Tested & Implemented Class: SendBlue Adapter Class: SendBlue Adapter Correctness Unit Tests Contract Tests Collaboration Tests TDD: Integration Testing with Contract & Collaboration Tests Forgot Password Weekly Newsletter Direct Message Exciting Event Reminder! @jessicamauerhan | http://bit.ly/double-loop
  • 39. @jessicamauerhan | http://bit.ly/double-loop Proof-Of-Concept (not tested) $dsn = 'pgsql:dbname=test;host=db'; $dbUser = 'postgres'; $dbPass = 'postgres'; $pdo = new PDO($dsn, $dbUser, $dbPass); $email = 'jane.doe@gmail.com'; $sql = "SELECT count(id) FROM users WHERE email = :email"; $statement = $pdo->prepare($sql); $statement->execute(['email' => $email]); $result = $statement->fetchColumn(); var_dump($result);
  • 40. @jessicamauerhan | http://bit.ly/double-loop PdoUserRepositoryTest.php //Collaboration public function testEmailExistsPreparesStatement() { $sql = "SELECT count(id) FROM users ". "WHERE email = :email"; $stmt = $this->createMock(PDOStatement::class); $pdo = this->createMock(PDO::class); $pdo->expects($this->once())->method('prepare') ->with($sql)->willReturn($stmt); $repo = new PdoUserRepository($pdo); $repo->emailExists('test@gmail.com'); } PdoUserRepository.php public function emailExists(string $email): bool { $sql = "SELECT count(id) FROM users ". "WHERE email = :email"; $statement = $this->pdo->prepare($sql); }
  • 41. @jessicamauerhan | http://bit.ly/double-loop PdoUserRepositoryTest.php //Collaboration public function testEmailExistsExecutesStatement() { $email = 'jdoe@gmail.com'; $stmt = $this->createMock(PDOStatement::class); $stmt>expects($this->once()) ->method('execute') ->with(['email'=>$email]); $pdo = this->createMock(PDO::class); $pdo->method('prepare')->willReturn($statement); $repo = new PdoUserRepository($pdo); $repo->emailExists($email); } PdoUserRepository.php public function emailExists(string $email): bool { $sql = "SELECT count(id) FROM users ". "WHERE email = :email"; $statement = $this->pdo->prepare($sql); } public function emailExists(string $email): bool { $sql = "SELECT count(id) FROM users ". "WHERE email = :email"; $statement = $this->pdo->prepare($sql); $statement->execute(['email' => $email]); }
  • 42. @jessicamauerhan | http://bit.ly/double-loop PdoUserRepositoryTest.php //Correctness public function testEmailExistsReturnsTrueWhenCountGreaterThanZero() { $stmt = $this->createMock(PDOStatement::class); $stmt->method('fetchColumn') ->willReturn(1); $pdo = this->createMock(PDO::class); $pdo->method('prepare') ->willReturn($statement); $repo = new PdoUserRepository($pdo); $this->assertTrue( $repo->emailExists('test@gmail.com') ); } PdoUserRepository.php public function emailExists(string $email): bool { $sql = "SELECT count(id) FROM users ". "WHERE email = :email"; $statement = $this->pdo->prepare($sql); $statement->execute(['email' => $email]); } public function emailExists(string $email): bool { $sql = "SELECT count(id) FROM users ". "WHERE email = :email"; $statement = $this->pdo->prepare($sql); $statement->execute(['email' => $email]); $result = $statement->fetchColumn(); return $result > 0; }
  • 43. @jessicamauerhan | http://bit.ly/double-loop PdoUserRepositoryTest.php //Correctness public function testEmailExistsReturnsFalseWhenCountZero() { $stmt = $this->createMock(PDOStatement::class); $stmt->method('fetchColumn') ->willReturn(0); $pdo = this->createMock(PDO::class); $pdo->method('prepare') ->willReturn($statement); $repo = new PdoUserRepository($pdo); $this->assertFalse( $repo->emailExists('test@gmail.com') ); } PdoUserRepository.php public function emailExists(string $email): bool { $sql = "SELECT count(id) FROM users ". "WHERE email = :email"; $statement = $this->pdo->prepare($sql); $statement->execute(['email' => $email]); $result = $statement->fetchColumn(); return $result > 0; }
  • 44. @jessicamauerhan | http://bit.ly/double-loop PdoUserRepositoryTest.php //Contract public function testEmailExistsThrowsUnableToCheckEmailWhenPDOExcept ion() { $this->expectException(UnableToCheckEmail::class); $pdoException = new PdoException(); $pdo = this->createMock(PDO::class); $pdo->method('prepare') ->willThrow($pdoException); $repo = new PdoUserRepository($pdo); $repo->emailExists('test@gmail.com'); } PdoUserRepository.php public function emailExists(string $email): bool { $sql = "SELECT count(id) FROM users ". "WHERE email = :email"; $statement = $this->pdo->prepare($sql); $statement->execute(['email' => $email]); $result = $statement->fetchColumn(); return $result > 0; } public function emailExists(string $email): bool { $sql = "SELECT count(id) FROM users ". "WHERE email = :email"; try { $statement = $this->pdo->prepare($sql); $statement->execute(['email' => $email]); $result = $statement->fetchColumn(); return $result > 0; } catch (PDOException $PDOException) { throw new UnableToCheckEmail(); } }
  • 45. Maintenance Coverage Fragility Duration Cost Number of Tests Isolated Unit Tests Correctness, Contract & Collaboration Integration Testing Multiple Components Integrated Tested for Correctness & Communication Behavior Tests Fully Integrated User Experience System Tests load balance, performance, security GUI Tests
  • 46. Add Behavior Test Add Unit Test Run Unit Test Add/Edit Some Code Fail Run Behavior Test Pass* Fail Double Loop: TDD & BDD Done Right! * A test that passes the first time before code has been written means the test is inaccurate or poorly written, not added to the test suite, or the code/feature already exists. @jessicamauerhan | http://bit.ly/double-loop
  • 47. @jessicamauerhan | http://bit.ly/double-loop Failing Test or Test Suite? Revert! ● If the test fails, revert your work ● Commit small changes, often!
  • 48. Add Behavior Test Add Unit Test Run Unit Test Add/Edit Some Code Refactor Run All Unit Tests Pass* Fail Fail Pass Run Behavior Test Pass* Fail Revert Changes Double Loop: TDD & BDD Done Right! Feature Done? NoYes * A test that passes the first time before code has been written means the test is inaccurate or poorly written, not added to the test suite, or the code/feature already exists. @jessicamauerhan | http://bit.ly/double-loop
  • 49. @jessicamauerhan | http://bit.ly/double-loop Refactoring The process of restructuring code without changing its behavior
  • 50. @jessicamauerhan | http://bit.ly/double-loop Refactoring ● Improving non-functional aspects ● Removing duplication ● Renaming ● Simplifying Unit Tests Always Passing! ● Changes that would break a unit test ● New functionality that is not tested New Unit Tests Fail, Then Pass Adding Functionality
  • 51. Add Behavior Test Add Unit Test Run Unit Test Add/Edit Some Code Refactor Run All Unit Tests Run All Behavior Tests Pass* Fail Fail Pass Run Behavior Test Pass* Fail Fail Pass Revert Changes Double Loop: TDD & BDD Done Right! Feature Done? NoYes * A test that passes the first time before code has been written means the test is inaccurate or poorly written, not added to the test suite, or the code/feature already exists. @jessicamauerhan | http://bit.ly/double-loop
  • 52. @jessicamauerhan | http://bit.ly/double-loop Thank You! Double Loop: TDD & BDD Done Right! Feedback & Questions? Welcome & Encouraged! @jessicamauerhan jessicamauerhan@gmail.com jmauerhan.wordpress.com