SlideShare a Scribd company logo
Driving Development with 
PhpSpec 
with Ciaran McNulty 
PHPLondon November 2014
My experiences 
4 Unit testing since 2004 
4 Test Driven Development since 2005(ish) 
4 Behaviour Driven Development since 2012
TDD vs BDD 
(or are they the same?)
BDD is a second-generation, 
outside-in, 
pull-based, multiple-stakeholder… 
1 
Dan North
…multiple-scale, high-automation, 
agile 
methodology. 
1 
Dan North
BDD is the art of using 
examples in conversation to 
illustrate behaviour 
1 
Liz Keogh
Test Driven 
Development 
4 Before you write your code, 
write a test that validates how 
it should behave 
4 After you have written the 
code, see if it passes the test
Behaviour Driven 
Development 
4 Before you write your code, 
describe how it should behave 
using examples 
4 Then, Implement the behaviour 
you you described
Driving Design with PhpSpec
Driving Design with PhpSpec
Driving Design with PhpSpec
Driving Design with PhpSpec
SpecBDD with PhpSpec 
Describing individual classes
History 
1.0 - Inspired by RSpec 
4 Pádraic Brady and Travis 
Swicegood
History 
2.0beta - Inspired by 1.0 
4 Marcello Duarte and Konstantin Kudryashov 
(Everzet) 
4 Ground-up rewrite 
4 No BC in specs
History 
2.0 stable - The boring bits 
4 Me 
4 Christophe Coevoet 
4 Jakub Zalas 
4 Richard Miller 
4 Gildas Quéméner
Installation via Composer 
{ 
"require-dev": { 
"phpspec/phpspec": "~2.1-RC1" 
}, 
"config": { 
"bin-dir": "bin" 
}, 
"autoload": {"psr-0": {"": "src"}} 
}
Driving Design with PhpSpec
A requirement: 
We need something that 
says hello to people
Describing object behaviour 
4 We describe an object using a Specification 
4 A specification is made up of Examples illustrating 
different scenarios 
Usage: 
phpspec describe [Class]
Driving Design with PhpSpec
/spec/PhpLondon/HelloWorld/GreeterSpec.php 
namespace specPhpLondonHelloWorld; 
use PhpSpecObjectBehavior; 
use ProphecyArgument; 
class GreeterSpec extends ObjectBehavior 
{ 
function it_is_initializable() 
{ 
$this->shouldHaveType('PhpLondonHelloWorldGreeter'); 
} 
}
Verifying object behaviour 
4 Compare the real objects' behaviours with the 
examples 
Usage: 
phpspec run
Driving Design with PhpSpec
Driving Design with PhpSpec
/src/PhpLondon/HelloWorld/Greeter.php 
namespace PhpLondonHelloWorld; 
class Greeter 
{ 
}
An example for Greeter: 
When this greets, it should 
return "Hello"
/spec/PhpLondon/HelloWorld/GreeterSpec.php 
class GreeterSpec extends ObjectBehavior 
{ 
function it_greets_by_saying_hello() 
{ 
$this->greet()->shouldReturn('Hello'); 
} 
}
Driving Design with PhpSpec
Driving Design with PhpSpec
/src/PhpLondon/HelloWorld/Greeter.php 
class Greeter 
{ 
public function greet() 
{ 
// TODO: write logic here 
} 
}
So now I write some code?
Fake it till you make it 
4 Do the simplest thing that works 
4 Only add complexity later when more examples drive 
it 
phpspec run --fake
Driving Design with PhpSpec
Driving Design with PhpSpec
/src/PhpLondon/HelloWorld/Greeter.php 
class Greeter 
{ 
public function greet() 
{ 
return 'Hello'; 
} 
}
Describing values 
Matchers
Describing values - Equality 
$this->greet()->shouldReturn('Hello'); 
$this->sum(3,3)->shouldEqual(6); 
$user = $this->findById(1234); 
$user->shouldBe($expectedUser); 
$this->numberList() 
->shouldBeLike(new ArrayObject([1,2,3]));
Describing values - Type 
$this->address()->shouldHaveType('EmailAddress'); 
$this->getTime()->shouldReturnAnInstanceOf('DateTime'); 
$user = $this->findById(1234); 
$user->shouldBeAnInstanceOf('User'); 
$this->shouldImplement('Countable');
Describing values - Strings 
$this->getStory()->shouldStartWith('A long time ago'); 
$this->getStory()->shouldEndWith('happily ever after'); 
$this->getSlug()->shouldMatch('/^[0-9a-z]+$/');
Describing values - Arrays 
$this->getNames()->shouldContain('Tom'); 
$this->getNames()->shouldHaveKey(0); 
$this->getNames()->shouldHaveCount(1);
Describing values - object state 
// calls isAdmin() 
$this->getUser()->shouldBeAdmin(); 
// calls hasLoggedInUser() 
$this->shouldHaveLoggedInUser();
Describing custom values 
function it_gets_json_with_user_details() 
{ 
$this->getResponseData()->shouldHaveJsonKey('username'); 
} 
public function getMatchers() 
{ 
return [ 
'haveJsonKey' => function ($subject, $key) { 
return array_key_exists($key, json_decode($subject)); 
} 
]; 
}
Another example for Greeter: 
When this greets Bob, it 
should return "Hello, Bob"
Wait, what is Bob? 
Bob is a Person 
What is a Person?
Driving Design with PhpSpec
An example for a Person: 
When you ask a person 
named "Alice" for their 
name, they return "Alice"
/spec/PhpLondon/HelloWorld/PersonSpec.php 
class PersonSpec extends ObjectBehavior 
{ 
function it_returns_the_name_it_is_created_with() 
{ 
$this->beConstructedWith('Alice'); 
$this->getName()->shouldReturn('Alice'); 
} 
}
Driving Design with PhpSpec
Driving Design with PhpSpec
Driving Design with PhpSpec
Driving Design with PhpSpec
/src/PhpLondon/HelloWorld/Person.php 
class Person 
{ 
public function __construct($argument1) 
{ 
// TODO: write logic here 
} 
public function getName() 
{ 
// TODO: write logic here 
} 
}
So now I write some code!
/src/PhpLondon/HelloWorld/Person.php 
class Person 
{ 
private $name; 
public function __construct($name) 
{ 
$this->name = $name; 
} 
public function getName() 
{ 
return $this->name; 
} 
}
Driving Design with PhpSpec
Another example for a Person: 
When a person named 
"Alice" changes their name 
to "Bob", when you ask 
their name they return 
"Bob"
/spec/PhpLondon/HelloWorld/PersonSpec.php 
class PersonSpec extends ObjectBehavior 
{ 
function it_returns_the_name_it_is_created_with() 
{ 
$this->beConstructedWith('Alice'); 
$this->getName()->shouldReturn('Alice'); 
} 
}
/spec/PhpLondon/HelloWorld/PersonSpec.php 
class PersonSpec extends ObjectBehavior 
{ 
function let() 
{ 
$this->beConstructedWith('Alice'); 
} 
function it_returns_the_name_it_is_created_with() 
{ 
$this->getName()->shouldReturn('Alice'); 
} 
}
/spec/PhpLondon/HelloWorld/PersonSpec.php 
class PersonSpec extends ObjectBehavior 
{ 
function let() 
{ 
$this->beConstructedWith('Alice'); 
} 
// … 
function it_returns_its_new_name_when_the_name_has_been_changed() 
{ 
$this->changeNameTo('Bob'); 
$this->getName()->shouldReturn('Bob'); 
} 
}
Driving Design with PhpSpec
Driving Design with PhpSpec
/src/PhpLondon/HelloWorld/Person.php 
class Person 
{ 
private $name; 
// … 
public function changeNameTo($argument1) 
{ 
// TODO: write logic here 
} 
}
/src/PhpLondon/HelloWorld/Person.php 
class Person 
{ 
private $name; 
// … 
public function changeNameTo($name) 
{ 
$this->name = $name; 
} 
}
Driving Design with PhpSpec
Another example for Greeter: 
When this greets Bob, it 
should return "Hello, Bob"
Describing collaboration - Stubs 
Stubs are used to describe how we interact with objects 
we query 
4 Maybe it is hard to get the real collaborator to 
return the value we want 
4 Maybe using the real collaborator is expensive
/spec/PhpLondon/HelloWorld/GreeterSpec.php 
class GreeterSpec extends ObjectBehavior 
{ 
//… 
function it_greets_people_by_name(Person $bob) 
{ 
$bob->getName()->willReturn('Bob'); 
$this->greet($bob)->shouldReturn('Hello, Bob'); 
} 
}
Driving Design with PhpSpec
/src/PhpLondon/HelloWorld/Greeter.php 
class Greeter 
{ 
public function greet() 
{ 
return 'Hello'; 
} 
}
/src/PhpLondon/HelloWorld/Greeter.php 
class Greeter 
{ 
public function greet() 
{ 
$greeting = 'Hello'; 
return $greeting; 
} 
}
/src/PhpLondon/HelloWorld/Greeter.php 
class Greeter 
{ 
public function greet(Person $person = null) 
{ 
$greeting = 'Hello'; 
if ($person) { 
$greeting .= ', ' . $person->getName(); 
} 
return $greeting; 
} 
}
Driving Design with PhpSpec
Final example for Greeter: 
When it greets Bob, the 
message "Hello Bob" should 
be logged
What's a log? 
Let's not worry yet
/src/PhpLondon/HelloWorld/Logger.php 
interface Logger 
{ 
public function log($message); 
}
Describing collaboration - Mocks and 
Spies 
Mocks or Spies are used to describe how we interact 
with objects we command 
4 Maybe the real command is has side effects 
4 Maybe using the real collaborator is expensive
/spec/PhpLondon/HelloWorld/GreeterSpec.php 
class GreeterSpec extends ObjectBehavior 
{ 
//… 
function it_greets_people_by_name(Person $bob) 
{ 
$bob->getName()->willReturn('Bob'); 
$this->greet($bob)->shouldReturn('Hello, Bob'); 
} 
}
/spec/PhpLondon/HelloWorld/GreeterSpec.php 
class GreeterSpec extends ObjectBehavior 
{ 
function let(Person $bob) 
{ 
$bob->getName()->willReturn('Bob'); 
} 
//… 
function it_greets_people_by_name(Person $bob) 
{ 
$this->greet($bob)->shouldReturn('Hello, Bob'); 
} 
}
/spec/PhpLondon/HelloWorld/GreeterSpec.php 
class GreeterSpec extends ObjectBehavior 
{ 
function let(Person $bob, Logger $logger) 
{ 
$this->beConstructedWith($logger); 
$bob->getName()->willReturn('Bob'); 
} 
//… 
function it_logs_the_greetings(Person $bob, Logger $logger) 
{ 
$this->greet($bob); 
$logger->log('Hello, Bob')->shouldHaveBeenCalled(); 
} 
}
Driving Design with PhpSpec
Driving Design with PhpSpec
/src/PhpLondon/HelloWorld/Greeter.php 
class Greeter 
{ 
public function __construct($argument1) 
{ 
// TODO: write logic here 
} 
public function greet(Person $person = null) 
{ 
$greeting = 'Hello'; 
if ($person) { $greeting .= ', ' . $person->getName(); } 
return $greeting; 
} 
}
/src/PhpLondon/HelloWorld/Greeter.php 
class Greeter 
{ 
private $logger; 
public function __construct(Logger $logger) 
{ 
$this->logger = $logger; 
} 
public function greet(Person $person = null) 
{ 
$greeting = 'Hello'; 
if ($person) { $greeting .= ', ' . $person->getName(); } 
$this->logger->log($greeting); 
return $greeting; 
} 
}
Driving Design with PhpSpec
What have we built?
The domain model
Specs as documentation
PhpSpec 
4 Focuses on being descriptive 
4 Makes common dev activities easier or automated 
4 Drives your design
2.1 release - soon! 
4 Rerun after failure 
4 --fake option 
4 Named constructors: User::named('Bob') 
4 PSR-4 support (+ other autoloaders) 
4 + lots of small improvements
Me 
4 Senior Trainer at Inviqa / Sensio Labs UK / Session 
Digital 
4 Contributor to PhpSpec 
4 @ciaranmcnulty 
4 https://github.com/ciaranmcnulty/phplondon-phpspec- 
talk
Questions?

More Related Content

PDF
TDD with PhpSpec - Lone Star PHP 2016
PDF
TDD with PhpSpec
PDF
Conscious Decoupling - Lone Star PHP
PDF
TDD with phpspec2
PDF
Moving away from legacy code with BDD
PPTX
Clean Code Principles
PDF
Ruby 程式語言綜覽簡介
PDF
Ruby 入門 第一次就上手
TDD with PhpSpec - Lone Star PHP 2016
TDD with PhpSpec
Conscious Decoupling - Lone Star PHP
TDD with phpspec2
Moving away from legacy code with BDD
Clean Code Principles
Ruby 程式語言綜覽簡介
Ruby 入門 第一次就上手

What's hot (20)

PDF
C# conventions & good practices
PDF
Kicking off with Zend Expressive and Doctrine ORM (ConFoo YVR 2017)
PDF
PHP 5.4 New Features
PDF
Exception Handling: Designing Robust Software in Ruby (with presentation note)
PDF
Kicking off with Zend Expressive and Doctrine ORM (Sunshine PHP 2017)
PDF
Kicking off with Zend Expressive and Doctrine ORM (PHPNW2016)
PDF
Intermediate OOP in PHP
PPS
Coding Best Practices
PDF
Introduction to web programming with JavaScript
PDF
Clean Code
KEY
Ruby: Beyond the Basics
ZIP
Fundamental JavaScript [In Control 2009]
PDF
Crafting Quality PHP Applications (ConFoo YVR 2017)
PDF
Kicking off with Zend Expressive and Doctrine ORM (PHP Srbija 2017)
PPTX
Java script
PDF
Best practices for crafting high quality PHP apps (Bulgaria 2019)
PPT
Beginning Object-Oriented JavaScript
PPT
Create a web-app with Cgi Appplication
PDF
Intermediate OOP in PHP
PDF
Let's Play Dart
C# conventions & good practices
Kicking off with Zend Expressive and Doctrine ORM (ConFoo YVR 2017)
PHP 5.4 New Features
Exception Handling: Designing Robust Software in Ruby (with presentation note)
Kicking off with Zend Expressive and Doctrine ORM (Sunshine PHP 2017)
Kicking off with Zend Expressive and Doctrine ORM (PHPNW2016)
Intermediate OOP in PHP
Coding Best Practices
Introduction to web programming with JavaScript
Clean Code
Ruby: Beyond the Basics
Fundamental JavaScript [In Control 2009]
Crafting Quality PHP Applications (ConFoo YVR 2017)
Kicking off with Zend Expressive and Doctrine ORM (PHP Srbija 2017)
Java script
Best practices for crafting high quality PHP apps (Bulgaria 2019)
Beginning Object-Oriented JavaScript
Create a web-app with Cgi Appplication
Intermediate OOP in PHP
Let's Play Dart
Ad

Viewers also liked (10)

PDF
PHP's FIG and PSRs
PDF
PHP: 4 Design Patterns to Make Better Code
PDF
Software Testing & PHPSpec
PDF
Action-Domain-Responder: A Web-Specific Refinement of Model-View-Controller
PDF
Emergent design with phpspec
PDF
JWT - To authentication and beyond!
KEY
PHPSpec BDD for PHP
PDF
PHPSpec - the only Design Tool you need - 4Developers
PPTX
Minimal Containers for PHP
PDF
PhpSpec 2.0 ilustrated by examples
PHP's FIG and PSRs
PHP: 4 Design Patterns to Make Better Code
Software Testing & PHPSpec
Action-Domain-Responder: A Web-Specific Refinement of Model-View-Controller
Emergent design with phpspec
JWT - To authentication and beyond!
PHPSpec BDD for PHP
PHPSpec - the only Design Tool you need - 4Developers
Minimal Containers for PHP
PhpSpec 2.0 ilustrated by examples
Ad

Similar to Driving Design with PhpSpec (20)

PDF
SPL: The Missing Link in Development
ZIP
Object Oriented PHP5
PPTX
Introducing PHP Latest Updates
DOC
Jsphp 110312161301-phpapp02
PDF
DDD on example of Symfony (Webcamp Odessa 2014)
PDF
Dependency injection in Drupal 8
PPTX
PDF
JavaScript for PHP developers
PPT
PDF
php AND MYSQL _ppt.pdf
PDF
Php Tutorials for Beginners
PDF
Objects, Testing, and Responsibility
PPTX
PHPneweeeeeeeeeeeeeeeeeeeeeeeeeeeeee.pptx
PDF
PHP 5.3 Overview
PDF
ElePHPant7 - Introduction to PHP7
PDF
関西PHP勉強会 php5.4つまみぐい
KEY
PDF
Introducing ruby on rails
PDF
Introduction to PHP
PDF
Phpspec tips&tricks
SPL: The Missing Link in Development
Object Oriented PHP5
Introducing PHP Latest Updates
Jsphp 110312161301-phpapp02
DDD on example of Symfony (Webcamp Odessa 2014)
Dependency injection in Drupal 8
JavaScript for PHP developers
php AND MYSQL _ppt.pdf
Php Tutorials for Beginners
Objects, Testing, and Responsibility
PHPneweeeeeeeeeeeeeeeeeeeeeeeeeeeeee.pptx
PHP 5.3 Overview
ElePHPant7 - Introduction to PHP7
関西PHP勉強会 php5.4つまみぐい
Introducing ruby on rails
Introduction to PHP
Phpspec tips&tricks

More from CiaranMcNulty (17)

PDF
Greener web development at PHP London
PDF
Doodle Driven Development
PDF
Behat Best Practices with Symfony
PDF
Behat Best Practices
PDF
Behat Best Practices with Symfony
PDF
Driving Design through Examples
PDF
Modelling by Example Workshop - PHPNW 2016
PDF
Conscious Coupling
PDF
Driving Design through Examples
PDF
Finding the Right Testing Tool for the Job
PDF
Fly In Style (without splashing out)
PDF
Why Your Test Suite Sucks - PHPCon PL 2015
PDF
Driving Design through Examples - PhpCon PL 2015
PDF
Building a Pyramid: Symfony Testing Strategies
PDF
Driving Design through Examples
PDF
Why Your Test Suite Sucks
PDF
Using HttpKernelInterface for Painless Integration
Greener web development at PHP London
Doodle Driven Development
Behat Best Practices with Symfony
Behat Best Practices
Behat Best Practices with Symfony
Driving Design through Examples
Modelling by Example Workshop - PHPNW 2016
Conscious Coupling
Driving Design through Examples
Finding the Right Testing Tool for the Job
Fly In Style (without splashing out)
Why Your Test Suite Sucks - PHPCon PL 2015
Driving Design through Examples - PhpCon PL 2015
Building a Pyramid: Symfony Testing Strategies
Driving Design through Examples
Why Your Test Suite Sucks
Using HttpKernelInterface for Painless Integration

Recently uploaded (20)

PDF
Chapter 3 Spatial Domain Image Processing.pdf
PPTX
MYSQL Presentation for SQL database connectivity
PDF
Spectral efficient network and resource selection model in 5G networks
PDF
Empathic Computing: Creating Shared Understanding
PDF
Network Security Unit 5.pdf for BCA BBA.
PDF
GamePlan Trading System Review: Professional Trader's Honest Take
PDF
Peak of Data & AI Encore- AI for Metadata and Smarter Workflows
PDF
cuic standard and advanced reporting.pdf
PDF
Mobile App Security Testing_ A Comprehensive Guide.pdf
PPTX
Cloud computing and distributed systems.
PDF
7 ChatGPT Prompts to Help You Define Your Ideal Customer Profile.pdf
DOCX
The AUB Centre for AI in Media Proposal.docx
PDF
Dropbox Q2 2025 Financial Results & Investor Presentation
PDF
NewMind AI Weekly Chronicles - August'25 Week I
PPTX
Understanding_Digital_Forensics_Presentation.pptx
PDF
Electronic commerce courselecture one. Pdf
PDF
Advanced IT Governance
PDF
GDG Cloud Iasi [PUBLIC] Florian Blaga - Unveiling the Evolution of Cybersecur...
PDF
Approach and Philosophy of On baking technology
PDF
CIFDAQ's Market Insight: SEC Turns Pro Crypto
Chapter 3 Spatial Domain Image Processing.pdf
MYSQL Presentation for SQL database connectivity
Spectral efficient network and resource selection model in 5G networks
Empathic Computing: Creating Shared Understanding
Network Security Unit 5.pdf for BCA BBA.
GamePlan Trading System Review: Professional Trader's Honest Take
Peak of Data & AI Encore- AI for Metadata and Smarter Workflows
cuic standard and advanced reporting.pdf
Mobile App Security Testing_ A Comprehensive Guide.pdf
Cloud computing and distributed systems.
7 ChatGPT Prompts to Help You Define Your Ideal Customer Profile.pdf
The AUB Centre for AI in Media Proposal.docx
Dropbox Q2 2025 Financial Results & Investor Presentation
NewMind AI Weekly Chronicles - August'25 Week I
Understanding_Digital_Forensics_Presentation.pptx
Electronic commerce courselecture one. Pdf
Advanced IT Governance
GDG Cloud Iasi [PUBLIC] Florian Blaga - Unveiling the Evolution of Cybersecur...
Approach and Philosophy of On baking technology
CIFDAQ's Market Insight: SEC Turns Pro Crypto

Driving Design with PhpSpec