SlideShare a Scribd company logo
SOFTWARE TESTING &
PHPSPEC
DARREN CRAIG
@minusdarren
“Always code as if the guy who ends up maintaining
your code will be a violent psychopath
and knows where you live.”
- John F. Woods
THE OBLIGATORY QUOTE
TESTING. TESTING. 123.
LEARNING HOW TO TEST
Started looking at unit testing about 2010
Very confusing
So many new concepts, language & ideas
Difficult to implement
Documentation, help and examples were scarce
Since then, there are many new tools available
Behat
PHPSpec
Codeception
Documentation has improved, as have help & examples
Frameworks are introducing better standards/practices
BIGGER, BETTER TOOLS
GETTING MY HEAD AROUND IT
Started reading about Domain Driven Design
Started using CQRS
Experimented with Datamapper tools, like Doctrine
Started playing with other testing tools, like PHPSpec, Behat & Codeception
And I discovered:
The architecture of my code was a massive issue
I was thinking in terms of the frameworks I was using
“Fat Controllers, Thin Models” - No. (Anaemic Domain Model)
Public attributes on models ($user->name = $blah) weren’t helping
THINGS THAT HELPED
I started restructuring my code based on DDD, CQRS and SOLID principles
Made loads of mistakes
… and even more mistakes
Started removing the database structure from my thinking (tough!!!)
Discovered that some mistakes aren’t mistakes
Spoke to a bunch of people on IRC
A QUICK OVERVIEW OF TESTING &
TERMINOLOGY
SOFTWARE TESTING
Been around since the late 70s
Checks if a component of a system satisfies the requirements
Usually separated into:
Unit Testing
Integration Testing
Acceptance Testing
UNIT TESTING
Tests individual parts - or a unit - of your code
Eg. Does the add() method work properly?
One function/method may have multiple tests
PHPUnit, PHPSpec
INTEGRATION TESTING
Tests several parts of your system are working
correctly together
Eg. When a user registers, are their details
saved to the Database?
Behat
ACCEPTANCE TESTING
Tests the system is working correctly from a
user’s perspective
E.g. if I go to /register - is the correct form
displayed?
E.g. If I input an invalid email address, do I get
an error?
Behat, Codeception, Selenium
TEST DRIVEN DEVELOPMENT (TDD)
Write tests first, then the code that’s being tested
Red-Green-Refactor
Red: Write a test - make it fail
Green: Make the test pass
Refactor: Tidy it up. It should still pass.
PHPSPEC
WHAT IS PHPSPEC?
A PHP Library
Similar to PHPUnit (but with a nicer API!)
Available through Composer (phpspec/phpspec)
Helps design your PHP Classes through
specifications
Describes the behaviour of the class before you
write it
No real difference between SpecBDD and TDD
INSTALLING
"require-dev": {

"phpspec/phpspec": "~2.4"

},
DID IT WORK?
vendor/bin/phpspec run
0 specs
0 examples
0ms
CONFIGURATION
# phpspec.yml
suites:
main:
namespace: Acme
# composer.json
"autoload": {
"psr-4": {
"Acme": "src/Acme"
}
}
DOING AS YOU’RE TOLD…
“Users should be able to Register on the system.
They need a name, email and password to do so.”
- The Client
LET’S CODE THAT…
$input = Input::all();
$user = new User();
$user->name = $input['name'];
$user->email = $input['email'];
$user->password = Hash::make($input['password']);
$userRepository->save($user);
What’s going on here?
Is this testable?
Is it maintainable?
LET’S USE PHPSPEC TO HELP
vendor/bin/phpspec describe Acme/User
Specification for AcmeUser created in [dir]/spec/UserSpec.php.
namespace specAcme;
use PhpSpecObjectBehavior;
use ProphecyArgument;
class UserSpec extends ObjectBehavior
{
function it_is_initializable()
{
$this->shouldHaveType('AcmeUser');
}
}
RUN THE TEST!
$ vendor/bin/phpspec run
Acme/User
10 - it is initializable
class AcmeUser does not exist.
100%
1
1 specs
1 example (1 broken)
6ms
Do you want me to create `AcmeUser` for you?
[Y/n]
YES!
Class AcmeUser created in phpspec/src/Acme/User.php.
100% 1
1 specs
1 example (1 passed)
13ms
- The Client
WHAT THE CLIENT SAID
“Users should be able to Register on the system.
They need a name, email and password to do so.”
USE A CONSTRUCTOR
class UserSpec extends ObjectBehavior
{
function let()
{
$this->beConstructedWith('Darren Craig', 'darren@minus40.co', 'abc123');
}
function it_tests_a_users_can_be_registered()
{
$this->shouldHaveType('AcmeUser');
}
}
RUN THE TEST
$ vendor/bin/phpspec run
Acme/User
15 - it tests a users can be registered
method AcmeUser::__construct not found.
100% 1
1 specs
1 example (1 broken)
9ms
Do you want me to create `AcmeUser::__construct()` for you?
[Y/n]
Y
Method AcmeUser::__construct() has been created.
100% 1
1 specs
1 example (1 passed)
8ms
THE USER CLASS
class User
{
public function __construct($name, $email, $password)
{
// TODO: write logic here
}
}
RETURNING USER DETAILS
class UserSpec extends ObjectBehavior
{
// other tests…
function it_tests_that_it_can_return_a_name()
{
$this->getName()->shouldReturn('Darren Craig');
}
}
RUN THE TEST
$ vendor/bin/phpspec run
Acme/User
21 - it tests that it can return a name
method AcmeUser::getName not found.
50% 50% 2
1 specs
2 examples (1 passed, 1 broken)
11ms
Do you want me to create `AcmeUser::getName()` for you?
[Y/n]
Y
Method AcmeUser::getName() has been created.
Acme/User
21 - it tests that it can return a name
expected "Darren Craig", but got null.
50% 50% 2
1 specs
2 examples (1 passed, 1 failed)
12ms
MAKING IT PASS
class User
{
private $name;
public function __construct($name, $email, $password)
{
$this->name = $name;
}
public function getName()
{
return $this->name;
}
}
RUN THE TEST
$ vendor/bin/phpspec run
100% 2
1 specs
2 examples (2 passed)
7ms
THE OTHER USER DETAILS…
function it_tests_that_it_can_return_a_name()
{
$this->getName()->shouldReturn('Darren Craig');
}
function it_tests_that_it_can_return_the_email_address()
{
$this->getEmail()->shouldReturn('darren@minus40.co');
}
function it_tests_that_it_can_return_the_password()
{
$this->getPassword()->shouldReturn('abc123');
}
REGISTERING A USER
$input = Input::all();
$user = new User($input['name'], $input['email'], $input['password']);
$userRepository->save($user);
But, our code should represent the behaviour
it’s carrying out…
Are we creating a new User? What are we doing?
- The Client
WHAT THE CLIENT SAID
“Users should be able to Register on the system.
They need a name, email and password to do so.”
REGISTERING USERS
$input = Input::all();
$user = User::register($input['name'], $input['email'], $input['password']);
$userRepository->save($user);
private function __construct($name, $email, $password) {}
public static function register($name, $email, $password)
{
return new static($name, $email, $password);
}
function let()
{
$this->beConstructedThrough(‘register',
['Darren Craig', 'darren@minus40.co', 'abc123']);
}
NEXT…
“Users should be able to add up to 3
Qualifications”
- The Client
THE QUALIFICATION CLASS
$ vendor/bin/phpspec describe Acme/Qualification
Specification for AcmeQualification created in [dir]/spec/Acme/QualificationSpec.php.
$ vendor/bin/phpspec run
Acme/Qualification
10 - it is initializable
class AcmeQualification does not exist.
80% 20% 5
2 specs
5 examples (4 passed, 1 broken)
24ms
Do you want me to create `AcmeQualification` for you?
[Y/n]
Y
Class AcmeQualification created in [dir]/src/Acme/Qualification.php.
100% 5
2 specs
5 examples (5 passed)
9ms
MORE USER TESTS…
use AcmeQualification;
class UserSpec extends ObjectBehavior
{
function it_adds_a_qualification(Qualification $qualification)
{
$this->addQualification($qualification);
$this->getQualifications()->shouldHaveCount(1);
}
}
RUN AND CREATE THE METHODS
$ vendor/bin/phpspec run
Acme/User
36 - it adds a qualification
method AcmeUser::addQualification not found.
80% 20% 5
2 specs
5 examples (4 passed, 1 broken)
24ms
Do you want me to create `AcmeUser::addQualification()` for you?
[Y/n]
Y
Method AcmeUser::addQualification() has been created.
Acme/User
31 - it adds a qualification
method AcmeUser::getQualifications not found.
80% 20% 5
2 specs
5 examples (4 passed, 1 broken)
15ms
Do you want me to create `AcmeUser::getQualifications()` for you?
[Y/n]
Y
Method AcmeUser::getQualifications() has been created.
Acme/User
31 - it adds a qualification
no haveCount([array:1]) matcher found for null.
80% 20% 5
2 specs
5 examples (4 passed, 1 broken)
20ms
AND MAKE IT PASS…
class User
{
private $qualifications = [];
public function addQualification(Qualification $qualification)
{
$this->qualifications[] = $qualification;
}
public function getQualifications()
{
return $this->qualifications;
}
}
CHECK IF IT PASSED
$ vendor/bin/phpspec run
100% 5
2 specs
5 examples (5 passed)
14ms
GREAT, BUT…
“Users should be able to add up to 3
Qualifications”
- The Client
NO PROBLEM - ANOTHER TEST
function it_prevents_more_than_3_qualifications_being_added(Qualification
$qualification)
{
$this->addQualification($qualification);
$this->addQualification($qualification);
$this->addQualification($qualification);
$this->shouldThrow(Exception::class)->duringAddQualification($qualification);
}
RUN IT
$ vendor/bin/phpspec run
Acme/User
37 - it prevents more than 3 qualifications being added
expected to get exception, none got.
83% 16% 6
2 specs
6 examples (5 passed, 1 failed)
21ms
AND MAKE IT PASS…
class User
{
private $qualifications = [];
public function addQualification(Qualification $qualification)
{
if(count($this->qualifications) === 3) {
throw new Exception("You can't add more than 3 qualifications");
}
$this->qualifications[] = $qualification;
}
}
RUN IT
$ vendor/bin/phpspec run
100% 6
2 specs
6 examples (6 passed)
17ms
COMMON MATCHERS
http://phpspec.readthedocs.org/en/latest/cookbook/matchers.html
IDENTITY MATCHERS
$this->getName()->shouldBe("Darren Craig");
$this->getName()->shouldBeEqualTo("Darren Craig");
$this->getName()->shouldReturn("Darren Craig");
$this->getName()->shouldEqual("Darren Craig");
COMPARISON MATCHER
$this->getAge()->shouldBeLike('21');
THROW MATCHERS
$this->shouldThrow(Exception::class)->duringAddQualification($qualification);
$this->shouldThrow(Exception::class)->during('addQualification', [$qualification]);
TYPE MATCHERS
$this->shouldHaveType('AcmeUser');
$this->shouldReturnAnInstanceOf('AcmeUser');
$this->shouldBeAnInstanceOf('AcmeUser');
$this->shouldImplement('AcmeUserInterface');
OBJECT STATE MATCHERS
// calls $user->isOver18();
$this->shouldBeOver18();
// call $user->hasDOB();
$this->shouldHaveDOB();
A nice way of calling is* or has* methods on your object
COUNT MATCHER
$this->getQualifications()->shouldHaveCount(3);
SCALAR TYPE MATCHER
$this->getName()->shouldBeString();
$this->getQualifications()->shouldBeArray();
MORE WORK… LESS TEARS
TDD encourages you to think first
Smaller, single-responsibility classes
More maintainable code
More robust systems
As your skill improves, so will your speed
Less likely to spend hours debugging
QUESTIONS?
THANKS FOR LISTENING!
DARREN CRAIG
@minusdarren

More Related Content

What's hot

Ant User Guide
Ant User GuideAnt User Guide
Ant User Guide
Muthuselvam RS
 
The Dark Art of Rails Plugins (2008)
The Dark Art of Rails Plugins (2008)The Dark Art of Rails Plugins (2008)
The Dark Art of Rails Plugins (2008)
lazyatom
 
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
 
Apache Ant
Apache AntApache Ant
Apache Ant
hussulinux
 
No-script PowerShell v2
No-script PowerShell v2No-script PowerShell v2
No-script PowerShell v2
Concentrated Technology
 
Intro To JavaScript Unit Testing - Ran Mizrahi
Intro To JavaScript Unit Testing - Ran MizrahiIntro To JavaScript Unit Testing - Ran Mizrahi
Intro To JavaScript Unit Testing - Ran Mizrahi
Ran Mizrahi
 
Don't RTFM, WTFM - Open Source Documentation - German Perl Workshop 2010
Don't RTFM, WTFM - Open Source Documentation - German Perl Workshop 2010Don't RTFM, WTFM - Open Source Documentation - German Perl Workshop 2010
Don't RTFM, WTFM - Open Source Documentation - German Perl Workshop 2010
singingfish
 
Ran Mizrahi - Symfony2 meets Drupal8
Ran Mizrahi - Symfony2 meets Drupal8Ran Mizrahi - Symfony2 meets Drupal8
Ran Mizrahi - Symfony2 meets Drupal8
Ran Mizrahi
 
Selenium training
Selenium trainingSelenium training
Selenium training
Robin0590
 
Apache Ant
Apache AntApache Ant
Apache Ant
Rajesh Kumar
 
Overlays, Accordions & Tabs, Oh My
Overlays, Accordions & Tabs, Oh MyOverlays, Accordions & Tabs, Oh My
Overlays, Accordions & Tabs, Oh My
Steve McMahon
 
SPCA2013 - Test-driven Development with SharePoint 2013 and Visual Studio
SPCA2013 - Test-driven Development with SharePoint 2013 and Visual StudioSPCA2013 - Test-driven Development with SharePoint 2013 and Visual Studio
SPCA2013 - Test-driven Development with SharePoint 2013 and Visual Studio
NCCOMMS
 
Codeception
CodeceptionCodeception
Codeception
Jonathan Lau
 
Build restful ap is with python and flask
Build restful ap is with python and flaskBuild restful ap is with python and flask
Build restful ap is with python and flask
Jeetendra singh
 
WordPress Plugin development
WordPress Plugin developmentWordPress Plugin development
WordPress Plugin development
Mostafa Soufi
 
Code Quality Practice and Tools
Code Quality Practice and ToolsCode Quality Practice and Tools
Code Quality Practice and Tools
Bob Paulin
 
Introduction to Apache Ant
Introduction to Apache AntIntroduction to Apache Ant
Introduction to Apache Ant
Shih-Hsiang Lin
 
Ant - Another Neat Tool
Ant - Another Neat ToolAnt - Another Neat Tool
Ant - Another Neat Tool
Kanika2885
 

What's hot (18)

Ant User Guide
Ant User GuideAnt User Guide
Ant User Guide
 
The Dark Art of Rails Plugins (2008)
The Dark Art of Rails Plugins (2008)The Dark Art of Rails Plugins (2008)
The Dark Art of Rails Plugins (2008)
 
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)
 
Apache Ant
Apache AntApache Ant
Apache Ant
 
No-script PowerShell v2
No-script PowerShell v2No-script PowerShell v2
No-script PowerShell v2
 
Intro To JavaScript Unit Testing - Ran Mizrahi
Intro To JavaScript Unit Testing - Ran MizrahiIntro To JavaScript Unit Testing - Ran Mizrahi
Intro To JavaScript Unit Testing - Ran Mizrahi
 
Don't RTFM, WTFM - Open Source Documentation - German Perl Workshop 2010
Don't RTFM, WTFM - Open Source Documentation - German Perl Workshop 2010Don't RTFM, WTFM - Open Source Documentation - German Perl Workshop 2010
Don't RTFM, WTFM - Open Source Documentation - German Perl Workshop 2010
 
Ran Mizrahi - Symfony2 meets Drupal8
Ran Mizrahi - Symfony2 meets Drupal8Ran Mizrahi - Symfony2 meets Drupal8
Ran Mizrahi - Symfony2 meets Drupal8
 
Selenium training
Selenium trainingSelenium training
Selenium training
 
Apache Ant
Apache AntApache Ant
Apache Ant
 
Overlays, Accordions & Tabs, Oh My
Overlays, Accordions & Tabs, Oh MyOverlays, Accordions & Tabs, Oh My
Overlays, Accordions & Tabs, Oh My
 
SPCA2013 - Test-driven Development with SharePoint 2013 and Visual Studio
SPCA2013 - Test-driven Development with SharePoint 2013 and Visual StudioSPCA2013 - Test-driven Development with SharePoint 2013 and Visual Studio
SPCA2013 - Test-driven Development with SharePoint 2013 and Visual Studio
 
Codeception
CodeceptionCodeception
Codeception
 
Build restful ap is with python and flask
Build restful ap is with python and flaskBuild restful ap is with python and flask
Build restful ap is with python and flask
 
WordPress Plugin development
WordPress Plugin developmentWordPress Plugin development
WordPress Plugin development
 
Code Quality Practice and Tools
Code Quality Practice and ToolsCode Quality Practice and Tools
Code Quality Practice and Tools
 
Introduction to Apache Ant
Introduction to Apache AntIntroduction to Apache Ant
Introduction to Apache Ant
 
Ant - Another Neat Tool
Ant - Another Neat ToolAnt - Another Neat Tool
Ant - Another Neat Tool
 

Viewers also liked

Driving Design with PhpSpec
Driving Design with PhpSpecDriving Design with PhpSpec
Driving Design with PhpSpec
CiaranMcNulty
 
Emergent design with phpspec
Emergent design with phpspecEmergent design with phpspec
Emergent design with phpspec
Marcello Duarte
 
PHPSpec BDD for PHP
PHPSpec BDD for PHPPHPSpec BDD for PHP
PHPSpec BDD for PHP
Marcello Duarte
 
TDD with PhpSpec - Lone Star PHP 2016
TDD with PhpSpec - Lone Star PHP 2016TDD with PhpSpec - Lone Star PHP 2016
TDD with PhpSpec - Lone Star PHP 2016
CiaranMcNulty
 
PHPSpec - the only Design Tool you need - 4Developers
PHPSpec - the only Design Tool you need - 4DevelopersPHPSpec - the only Design Tool you need - 4Developers
PHPSpec - the only Design Tool you need - 4Developers
Kacper Gunia
 
PhpSpec 2.0 ilustrated by examples
PhpSpec 2.0 ilustrated by examplesPhpSpec 2.0 ilustrated by examples
PhpSpec 2.0 ilustrated by examples
Marcello Duarte
 

Viewers also liked (6)

Driving Design with PhpSpec
Driving Design with PhpSpecDriving Design with PhpSpec
Driving Design with PhpSpec
 
Emergent design with phpspec
Emergent design with phpspecEmergent design with phpspec
Emergent design with phpspec
 
PHPSpec BDD for PHP
PHPSpec BDD for PHPPHPSpec BDD for PHP
PHPSpec BDD for PHP
 
TDD with PhpSpec - Lone Star PHP 2016
TDD with PhpSpec - Lone Star PHP 2016TDD with PhpSpec - Lone Star PHP 2016
TDD with PhpSpec - Lone Star PHP 2016
 
PHPSpec - the only Design Tool you need - 4Developers
PHPSpec - the only Design Tool you need - 4DevelopersPHPSpec - the only Design Tool you need - 4Developers
PHPSpec - the only Design Tool you need - 4Developers
 
PhpSpec 2.0 ilustrated by examples
PhpSpec 2.0 ilustrated by examplesPhpSpec 2.0 ilustrated by examples
PhpSpec 2.0 ilustrated by examples
 

Similar to Software Testing & PHPSpec

How To Test Everything
How To Test EverythingHow To Test Everything
How To Test Everything
noelrap
 
Comparison of different access controls
Comparison of different access controlsComparison of different access controls
Comparison of different access controls
Rashmi Nair
 
EPHPC Webinar Slides: Unit Testing by Arthur Purnama
EPHPC Webinar Slides: Unit Testing by Arthur PurnamaEPHPC Webinar Slides: Unit Testing by Arthur Purnama
EPHPC Webinar Slides: Unit Testing by Arthur Purnama
Enterprise PHP Center
 
Building Testable PHP Applications
Building Testable PHP ApplicationsBuilding Testable PHP Applications
Building Testable PHP Applications
chartjes
 
Quality Assurance for PHP projects - ZendCon 2012
Quality Assurance for PHP projects - ZendCon 2012Quality Assurance for PHP projects - ZendCon 2012
Quality Assurance for PHP projects - ZendCon 2012
Michelangelo van Dam
 
Workshop quality assurance for php projects tek12
Workshop quality assurance for php projects tek12Workshop quality assurance for php projects tek12
Workshop quality assurance for php projects tek12
Michelangelo van Dam
 
2011-02-03 LA RubyConf Rails3 TDD Workshop
2011-02-03 LA RubyConf Rails3 TDD Workshop2011-02-03 LA RubyConf Rails3 TDD Workshop
2011-02-03 LA RubyConf Rails3 TDD Workshop
Wolfram Arnold
 
Ruby/Rails
Ruby/RailsRuby/Rails
Ruby/Rails
rstankov
 
Test-driven Development with Drupal and Codeception (DrupalCamp Brighton)
Test-driven Development with Drupal and Codeception (DrupalCamp Brighton)Test-driven Development with Drupal and Codeception (DrupalCamp Brighton)
Test-driven Development with Drupal and Codeception (DrupalCamp Brighton)
Cogapp
 
Demystifying Object-Oriented Programming - PHP[tek] 2017
Demystifying Object-Oriented Programming - PHP[tek] 2017Demystifying Object-Oriented Programming - PHP[tek] 2017
Demystifying Object-Oriented Programming - PHP[tek] 2017
Alena Holligan
 
2014 11 20 Drupal 7 -> 8 test migratie
2014 11 20 Drupal 7 -> 8 test migratie2014 11 20 Drupal 7 -> 8 test migratie
2014 11 20 Drupal 7 -> 8 test migratie
hcderaad
 
PHPUnit best practices presentation
PHPUnit best practices presentationPHPUnit best practices presentation
PHPUnit best practices presentation
Thanh Robi
 
Rspec
RspecRspec
Workshop quality assurance for php projects - ZendCon 2013
Workshop quality assurance for php projects - ZendCon 2013Workshop quality assurance for php projects - ZendCon 2013
Workshop quality assurance for php projects - ZendCon 2013
Michelangelo van Dam
 
Save time by applying clean code principles
Save time by applying clean code principlesSave time by applying clean code principles
Save time by applying clean code principles
Edorian
 
modern module development - Ken Barber 2012 Edinburgh Puppet Camp
modern module development - Ken Barber 2012 Edinburgh Puppet Campmodern module development - Ken Barber 2012 Edinburgh Puppet Camp
modern module development - Ken Barber 2012 Edinburgh Puppet Camp
Puppet
 
Oops concepts in php
Oops concepts in phpOops concepts in php
Oops concepts in php
CPD INDIA
 
How to? Drupal developer toolkit. Dennis Povshedny.
How to? Drupal developer toolkit. Dennis Povshedny.How to? Drupal developer toolkit. Dennis Povshedny.
How to? Drupal developer toolkit. Dennis Povshedny.
DrupalCampDN
 
Pragmatic Parallels: Java and JavaScript
Pragmatic Parallels: Java and JavaScriptPragmatic Parallels: Java and JavaScript
Pragmatic Parallels: Java and JavaScript
davejohnson
 
Efficient Rails Test Driven Development (class 4) by Wolfram Arnold
Efficient Rails Test Driven Development (class 4) by Wolfram ArnoldEfficient Rails Test Driven Development (class 4) by Wolfram Arnold
Efficient Rails Test Driven Development (class 4) by Wolfram Arnold
Marakana Inc.
 

Similar to Software Testing & PHPSpec (20)

How To Test Everything
How To Test EverythingHow To Test Everything
How To Test Everything
 
Comparison of different access controls
Comparison of different access controlsComparison of different access controls
Comparison of different access controls
 
EPHPC Webinar Slides: Unit Testing by Arthur Purnama
EPHPC Webinar Slides: Unit Testing by Arthur PurnamaEPHPC Webinar Slides: Unit Testing by Arthur Purnama
EPHPC Webinar Slides: Unit Testing by Arthur Purnama
 
Building Testable PHP Applications
Building Testable PHP ApplicationsBuilding Testable PHP Applications
Building Testable PHP Applications
 
Quality Assurance for PHP projects - ZendCon 2012
Quality Assurance for PHP projects - ZendCon 2012Quality Assurance for PHP projects - ZendCon 2012
Quality Assurance for PHP projects - ZendCon 2012
 
Workshop quality assurance for php projects tek12
Workshop quality assurance for php projects tek12Workshop quality assurance for php projects tek12
Workshop quality assurance for php projects tek12
 
2011-02-03 LA RubyConf Rails3 TDD Workshop
2011-02-03 LA RubyConf Rails3 TDD Workshop2011-02-03 LA RubyConf Rails3 TDD Workshop
2011-02-03 LA RubyConf Rails3 TDD Workshop
 
Ruby/Rails
Ruby/RailsRuby/Rails
Ruby/Rails
 
Test-driven Development with Drupal and Codeception (DrupalCamp Brighton)
Test-driven Development with Drupal and Codeception (DrupalCamp Brighton)Test-driven Development with Drupal and Codeception (DrupalCamp Brighton)
Test-driven Development with Drupal and Codeception (DrupalCamp Brighton)
 
Demystifying Object-Oriented Programming - PHP[tek] 2017
Demystifying Object-Oriented Programming - PHP[tek] 2017Demystifying Object-Oriented Programming - PHP[tek] 2017
Demystifying Object-Oriented Programming - PHP[tek] 2017
 
2014 11 20 Drupal 7 -> 8 test migratie
2014 11 20 Drupal 7 -> 8 test migratie2014 11 20 Drupal 7 -> 8 test migratie
2014 11 20 Drupal 7 -> 8 test migratie
 
PHPUnit best practices presentation
PHPUnit best practices presentationPHPUnit best practices presentation
PHPUnit best practices presentation
 
Rspec
RspecRspec
Rspec
 
Workshop quality assurance for php projects - ZendCon 2013
Workshop quality assurance for php projects - ZendCon 2013Workshop quality assurance for php projects - ZendCon 2013
Workshop quality assurance for php projects - ZendCon 2013
 
Save time by applying clean code principles
Save time by applying clean code principlesSave time by applying clean code principles
Save time by applying clean code principles
 
modern module development - Ken Barber 2012 Edinburgh Puppet Camp
modern module development - Ken Barber 2012 Edinburgh Puppet Campmodern module development - Ken Barber 2012 Edinburgh Puppet Camp
modern module development - Ken Barber 2012 Edinburgh Puppet Camp
 
Oops concepts in php
Oops concepts in phpOops concepts in php
Oops concepts in php
 
How to? Drupal developer toolkit. Dennis Povshedny.
How to? Drupal developer toolkit. Dennis Povshedny.How to? Drupal developer toolkit. Dennis Povshedny.
How to? Drupal developer toolkit. Dennis Povshedny.
 
Pragmatic Parallels: Java and JavaScript
Pragmatic Parallels: Java and JavaScriptPragmatic Parallels: Java and JavaScript
Pragmatic Parallels: Java and JavaScript
 
Efficient Rails Test Driven Development (class 4) by Wolfram Arnold
Efficient Rails Test Driven Development (class 4) by Wolfram ArnoldEfficient Rails Test Driven Development (class 4) by Wolfram Arnold
Efficient Rails Test Driven Development (class 4) by Wolfram Arnold
 

Recently uploaded

Preparing Non - Technical Founders for Engaging a Tech Agency
Preparing Non - Technical Founders for Engaging  a  Tech AgencyPreparing Non - Technical Founders for Engaging  a  Tech Agency
Preparing Non - Technical Founders for Engaging a Tech Agency
ISH Technologies
 
Top Benefits of Using Salesforce Healthcare CRM for Patient Management.pdf
Top Benefits of Using Salesforce Healthcare CRM for Patient Management.pdfTop Benefits of Using Salesforce Healthcare CRM for Patient Management.pdf
Top Benefits of Using Salesforce Healthcare CRM for Patient Management.pdf
VALiNTRY360
 
Unveiling the Advantages of Agile Software Development.pdf
Unveiling the Advantages of Agile Software Development.pdfUnveiling the Advantages of Agile Software Development.pdf
Unveiling the Advantages of Agile Software Development.pdf
brainerhub1
 
INTRODUCTION TO AI CLASSICAL THEORY TARGETED EXAMPLES
INTRODUCTION TO AI CLASSICAL THEORY TARGETED EXAMPLESINTRODUCTION TO AI CLASSICAL THEORY TARGETED EXAMPLES
INTRODUCTION TO AI CLASSICAL THEORY TARGETED EXAMPLES
anfaltahir1010
 
Kubernetes at Scale: Going Multi-Cluster with Istio
Kubernetes at Scale:  Going Multi-Cluster  with IstioKubernetes at Scale:  Going Multi-Cluster  with Istio
Kubernetes at Scale: Going Multi-Cluster with Istio
Severalnines
 
DECODING JAVA THREAD DUMPS: MASTER THE ART OF ANALYSIS
DECODING JAVA THREAD DUMPS: MASTER THE ART OF ANALYSISDECODING JAVA THREAD DUMPS: MASTER THE ART OF ANALYSIS
DECODING JAVA THREAD DUMPS: MASTER THE ART OF ANALYSIS
Tier1 app
 
J-Spring 2024 - Going serverless with Quarkus, GraalVM native images and AWS ...
J-Spring 2024 - Going serverless with Quarkus, GraalVM native images and AWS ...J-Spring 2024 - Going serverless with Quarkus, GraalVM native images and AWS ...
J-Spring 2024 - Going serverless with Quarkus, GraalVM native images and AWS ...
Bert Jan Schrijver
 
E-Invoicing Implementation: A Step-by-Step Guide for Saudi Arabian Companies
E-Invoicing Implementation: A Step-by-Step Guide for Saudi Arabian CompaniesE-Invoicing Implementation: A Step-by-Step Guide for Saudi Arabian Companies
E-Invoicing Implementation: A Step-by-Step Guide for Saudi Arabian Companies
Quickdice ERP
 
Everything You Need to Know About X-Sign: The eSign Functionality of XfilesPr...
Everything You Need to Know About X-Sign: The eSign Functionality of XfilesPr...Everything You Need to Know About X-Sign: The eSign Functionality of XfilesPr...
Everything You Need to Know About X-Sign: The eSign Functionality of XfilesPr...
XfilesPro
 
Using Query Store in Azure PostgreSQL to Understand Query Performance
Using Query Store in Azure PostgreSQL to Understand Query PerformanceUsing Query Store in Azure PostgreSQL to Understand Query Performance
Using Query Store in Azure PostgreSQL to Understand Query Performance
Grant Fritchey
 
Oracle Database 19c New Features for DBAs and Developers.pptx
Oracle Database 19c New Features for DBAs and Developers.pptxOracle Database 19c New Features for DBAs and Developers.pptx
Oracle Database 19c New Features for DBAs and Developers.pptx
Remote DBA Services
 
Measures in SQL (SIGMOD 2024, Santiago, Chile)
Measures in SQL (SIGMOD 2024, Santiago, Chile)Measures in SQL (SIGMOD 2024, Santiago, Chile)
Measures in SQL (SIGMOD 2024, Santiago, Chile)
Julian Hyde
 
UI5con 2024 - Keynote: Latest News about UI5 and it’s Ecosystem
UI5con 2024 - Keynote: Latest News about UI5 and it’s EcosystemUI5con 2024 - Keynote: Latest News about UI5 and it’s Ecosystem
UI5con 2024 - Keynote: Latest News about UI5 and it’s Ecosystem
Peter Muessig
 
Mobile App Development Company In Noida | Drona Infotech
Mobile App Development Company In Noida | Drona InfotechMobile App Development Company In Noida | Drona Infotech
Mobile App Development Company In Noida | Drona Infotech
Drona Infotech
 
E-commerce Development Services- Hornet Dynamics
E-commerce Development Services- Hornet DynamicsE-commerce Development Services- Hornet Dynamics
E-commerce Development Services- Hornet Dynamics
Hornet Dynamics
 
UI5con 2024 - Bring Your Own Design System
UI5con 2024 - Bring Your Own Design SystemUI5con 2024 - Bring Your Own Design System
UI5con 2024 - Bring Your Own Design System
Peter Muessig
 
一比一原版(UMN毕业证)明尼苏达大学毕业证如何办理
一比一原版(UMN毕业证)明尼苏达大学毕业证如何办理一比一原版(UMN毕业证)明尼苏达大学毕业证如何办理
一比一原版(UMN毕业证)明尼苏达大学毕业证如何办理
dakas1
 
Energy consumption of Database Management - Florina Jonuzi
Energy consumption of Database Management - Florina JonuziEnergy consumption of Database Management - Florina Jonuzi
Energy consumption of Database Management - Florina Jonuzi
Green Software Development
 
What’s New in Odoo 17 – A Complete Roadmap
What’s New in Odoo 17 – A Complete RoadmapWhat’s New in Odoo 17 – A Complete Roadmap
What’s New in Odoo 17 – A Complete Roadmap
Envertis Software Solutions
 
All you need to know about Spring Boot and GraalVM
All you need to know about Spring Boot and GraalVMAll you need to know about Spring Boot and GraalVM
All you need to know about Spring Boot and GraalVM
Alina Yurenko
 

Recently uploaded (20)

Preparing Non - Technical Founders for Engaging a Tech Agency
Preparing Non - Technical Founders for Engaging  a  Tech AgencyPreparing Non - Technical Founders for Engaging  a  Tech Agency
Preparing Non - Technical Founders for Engaging a Tech Agency
 
Top Benefits of Using Salesforce Healthcare CRM for Patient Management.pdf
Top Benefits of Using Salesforce Healthcare CRM for Patient Management.pdfTop Benefits of Using Salesforce Healthcare CRM for Patient Management.pdf
Top Benefits of Using Salesforce Healthcare CRM for Patient Management.pdf
 
Unveiling the Advantages of Agile Software Development.pdf
Unveiling the Advantages of Agile Software Development.pdfUnveiling the Advantages of Agile Software Development.pdf
Unveiling the Advantages of Agile Software Development.pdf
 
INTRODUCTION TO AI CLASSICAL THEORY TARGETED EXAMPLES
INTRODUCTION TO AI CLASSICAL THEORY TARGETED EXAMPLESINTRODUCTION TO AI CLASSICAL THEORY TARGETED EXAMPLES
INTRODUCTION TO AI CLASSICAL THEORY TARGETED EXAMPLES
 
Kubernetes at Scale: Going Multi-Cluster with Istio
Kubernetes at Scale:  Going Multi-Cluster  with IstioKubernetes at Scale:  Going Multi-Cluster  with Istio
Kubernetes at Scale: Going Multi-Cluster with Istio
 
DECODING JAVA THREAD DUMPS: MASTER THE ART OF ANALYSIS
DECODING JAVA THREAD DUMPS: MASTER THE ART OF ANALYSISDECODING JAVA THREAD DUMPS: MASTER THE ART OF ANALYSIS
DECODING JAVA THREAD DUMPS: MASTER THE ART OF ANALYSIS
 
J-Spring 2024 - Going serverless with Quarkus, GraalVM native images and AWS ...
J-Spring 2024 - Going serverless with Quarkus, GraalVM native images and AWS ...J-Spring 2024 - Going serverless with Quarkus, GraalVM native images and AWS ...
J-Spring 2024 - Going serverless with Quarkus, GraalVM native images and AWS ...
 
E-Invoicing Implementation: A Step-by-Step Guide for Saudi Arabian Companies
E-Invoicing Implementation: A Step-by-Step Guide for Saudi Arabian CompaniesE-Invoicing Implementation: A Step-by-Step Guide for Saudi Arabian Companies
E-Invoicing Implementation: A Step-by-Step Guide for Saudi Arabian Companies
 
Everything You Need to Know About X-Sign: The eSign Functionality of XfilesPr...
Everything You Need to Know About X-Sign: The eSign Functionality of XfilesPr...Everything You Need to Know About X-Sign: The eSign Functionality of XfilesPr...
Everything You Need to Know About X-Sign: The eSign Functionality of XfilesPr...
 
Using Query Store in Azure PostgreSQL to Understand Query Performance
Using Query Store in Azure PostgreSQL to Understand Query PerformanceUsing Query Store in Azure PostgreSQL to Understand Query Performance
Using Query Store in Azure PostgreSQL to Understand Query Performance
 
Oracle Database 19c New Features for DBAs and Developers.pptx
Oracle Database 19c New Features for DBAs and Developers.pptxOracle Database 19c New Features for DBAs and Developers.pptx
Oracle Database 19c New Features for DBAs and Developers.pptx
 
Measures in SQL (SIGMOD 2024, Santiago, Chile)
Measures in SQL (SIGMOD 2024, Santiago, Chile)Measures in SQL (SIGMOD 2024, Santiago, Chile)
Measures in SQL (SIGMOD 2024, Santiago, Chile)
 
UI5con 2024 - Keynote: Latest News about UI5 and it’s Ecosystem
UI5con 2024 - Keynote: Latest News about UI5 and it’s EcosystemUI5con 2024 - Keynote: Latest News about UI5 and it’s Ecosystem
UI5con 2024 - Keynote: Latest News about UI5 and it’s Ecosystem
 
Mobile App Development Company In Noida | Drona Infotech
Mobile App Development Company In Noida | Drona InfotechMobile App Development Company In Noida | Drona Infotech
Mobile App Development Company In Noida | Drona Infotech
 
E-commerce Development Services- Hornet Dynamics
E-commerce Development Services- Hornet DynamicsE-commerce Development Services- Hornet Dynamics
E-commerce Development Services- Hornet Dynamics
 
UI5con 2024 - Bring Your Own Design System
UI5con 2024 - Bring Your Own Design SystemUI5con 2024 - Bring Your Own Design System
UI5con 2024 - Bring Your Own Design System
 
一比一原版(UMN毕业证)明尼苏达大学毕业证如何办理
一比一原版(UMN毕业证)明尼苏达大学毕业证如何办理一比一原版(UMN毕业证)明尼苏达大学毕业证如何办理
一比一原版(UMN毕业证)明尼苏达大学毕业证如何办理
 
Energy consumption of Database Management - Florina Jonuzi
Energy consumption of Database Management - Florina JonuziEnergy consumption of Database Management - Florina Jonuzi
Energy consumption of Database Management - Florina Jonuzi
 
What’s New in Odoo 17 – A Complete Roadmap
What’s New in Odoo 17 – A Complete RoadmapWhat’s New in Odoo 17 – A Complete Roadmap
What’s New in Odoo 17 – A Complete Roadmap
 
All you need to know about Spring Boot and GraalVM
All you need to know about Spring Boot and GraalVMAll you need to know about Spring Boot and GraalVM
All you need to know about Spring Boot and GraalVM
 

Software Testing & PHPSpec

  • 2. “Always code as if the guy who ends up maintaining your code will be a violent psychopath and knows where you live.” - John F. Woods THE OBLIGATORY QUOTE
  • 4. LEARNING HOW TO TEST Started looking at unit testing about 2010 Very confusing So many new concepts, language & ideas Difficult to implement Documentation, help and examples were scarce
  • 5.
  • 6. Since then, there are many new tools available Behat PHPSpec Codeception Documentation has improved, as have help & examples Frameworks are introducing better standards/practices BIGGER, BETTER TOOLS
  • 7. GETTING MY HEAD AROUND IT Started reading about Domain Driven Design Started using CQRS Experimented with Datamapper tools, like Doctrine Started playing with other testing tools, like PHPSpec, Behat & Codeception And I discovered: The architecture of my code was a massive issue I was thinking in terms of the frameworks I was using “Fat Controllers, Thin Models” - No. (Anaemic Domain Model) Public attributes on models ($user->name = $blah) weren’t helping
  • 8. THINGS THAT HELPED I started restructuring my code based on DDD, CQRS and SOLID principles Made loads of mistakes … and even more mistakes Started removing the database structure from my thinking (tough!!!) Discovered that some mistakes aren’t mistakes Spoke to a bunch of people on IRC
  • 9. A QUICK OVERVIEW OF TESTING & TERMINOLOGY
  • 10. SOFTWARE TESTING Been around since the late 70s Checks if a component of a system satisfies the requirements Usually separated into: Unit Testing Integration Testing Acceptance Testing
  • 11. UNIT TESTING Tests individual parts - or a unit - of your code Eg. Does the add() method work properly? One function/method may have multiple tests PHPUnit, PHPSpec
  • 12. INTEGRATION TESTING Tests several parts of your system are working correctly together Eg. When a user registers, are their details saved to the Database? Behat
  • 13. ACCEPTANCE TESTING Tests the system is working correctly from a user’s perspective E.g. if I go to /register - is the correct form displayed? E.g. If I input an invalid email address, do I get an error? Behat, Codeception, Selenium
  • 14. TEST DRIVEN DEVELOPMENT (TDD) Write tests first, then the code that’s being tested Red-Green-Refactor Red: Write a test - make it fail Green: Make the test pass Refactor: Tidy it up. It should still pass.
  • 16. WHAT IS PHPSPEC? A PHP Library Similar to PHPUnit (but with a nicer API!) Available through Composer (phpspec/phpspec) Helps design your PHP Classes through specifications Describes the behaviour of the class before you write it No real difference between SpecBDD and TDD
  • 18. DID IT WORK? vendor/bin/phpspec run 0 specs 0 examples 0ms
  • 19. CONFIGURATION # phpspec.yml suites: main: namespace: Acme # composer.json "autoload": { "psr-4": { "Acme": "src/Acme" } }
  • 20. DOING AS YOU’RE TOLD…
  • 21. “Users should be able to Register on the system. They need a name, email and password to do so.” - The Client
  • 22. LET’S CODE THAT… $input = Input::all(); $user = new User(); $user->name = $input['name']; $user->email = $input['email']; $user->password = Hash::make($input['password']); $userRepository->save($user); What’s going on here? Is this testable? Is it maintainable?
  • 23. LET’S USE PHPSPEC TO HELP vendor/bin/phpspec describe Acme/User Specification for AcmeUser created in [dir]/spec/UserSpec.php. namespace specAcme; use PhpSpecObjectBehavior; use ProphecyArgument; class UserSpec extends ObjectBehavior { function it_is_initializable() { $this->shouldHaveType('AcmeUser'); } }
  • 24. RUN THE TEST! $ vendor/bin/phpspec run Acme/User 10 - it is initializable class AcmeUser does not exist. 100% 1 1 specs 1 example (1 broken) 6ms Do you want me to create `AcmeUser` for you? [Y/n]
  • 25. YES! Class AcmeUser created in phpspec/src/Acme/User.php. 100% 1 1 specs 1 example (1 passed) 13ms
  • 26. - The Client WHAT THE CLIENT SAID “Users should be able to Register on the system. They need a name, email and password to do so.”
  • 27. USE A CONSTRUCTOR class UserSpec extends ObjectBehavior { function let() { $this->beConstructedWith('Darren Craig', 'darren@minus40.co', 'abc123'); } function it_tests_a_users_can_be_registered() { $this->shouldHaveType('AcmeUser'); } }
  • 28. RUN THE TEST $ vendor/bin/phpspec run Acme/User 15 - it tests a users can be registered method AcmeUser::__construct not found. 100% 1 1 specs 1 example (1 broken) 9ms Do you want me to create `AcmeUser::__construct()` for you? [Y/n] Y Method AcmeUser::__construct() has been created. 100% 1 1 specs 1 example (1 passed) 8ms
  • 29. THE USER CLASS class User { public function __construct($name, $email, $password) { // TODO: write logic here } }
  • 30. RETURNING USER DETAILS class UserSpec extends ObjectBehavior { // other tests… function it_tests_that_it_can_return_a_name() { $this->getName()->shouldReturn('Darren Craig'); } }
  • 31. RUN THE TEST $ vendor/bin/phpspec run Acme/User 21 - it tests that it can return a name method AcmeUser::getName not found. 50% 50% 2 1 specs 2 examples (1 passed, 1 broken) 11ms Do you want me to create `AcmeUser::getName()` for you? [Y/n] Y Method AcmeUser::getName() has been created. Acme/User 21 - it tests that it can return a name expected "Darren Craig", but got null. 50% 50% 2 1 specs 2 examples (1 passed, 1 failed) 12ms
  • 32. MAKING IT PASS class User { private $name; public function __construct($name, $email, $password) { $this->name = $name; } public function getName() { return $this->name; } }
  • 33. RUN THE TEST $ vendor/bin/phpspec run 100% 2 1 specs 2 examples (2 passed) 7ms
  • 34.
  • 35. THE OTHER USER DETAILS… function it_tests_that_it_can_return_a_name() { $this->getName()->shouldReturn('Darren Craig'); } function it_tests_that_it_can_return_the_email_address() { $this->getEmail()->shouldReturn('darren@minus40.co'); } function it_tests_that_it_can_return_the_password() { $this->getPassword()->shouldReturn('abc123'); }
  • 36. REGISTERING A USER $input = Input::all(); $user = new User($input['name'], $input['email'], $input['password']); $userRepository->save($user); But, our code should represent the behaviour it’s carrying out… Are we creating a new User? What are we doing?
  • 37. - The Client WHAT THE CLIENT SAID “Users should be able to Register on the system. They need a name, email and password to do so.”
  • 38. REGISTERING USERS $input = Input::all(); $user = User::register($input['name'], $input['email'], $input['password']); $userRepository->save($user); private function __construct($name, $email, $password) {} public static function register($name, $email, $password) { return new static($name, $email, $password); } function let() { $this->beConstructedThrough(‘register', ['Darren Craig', 'darren@minus40.co', 'abc123']); }
  • 39.
  • 40. NEXT… “Users should be able to add up to 3 Qualifications” - The Client
  • 41. THE QUALIFICATION CLASS $ vendor/bin/phpspec describe Acme/Qualification Specification for AcmeQualification created in [dir]/spec/Acme/QualificationSpec.php. $ vendor/bin/phpspec run Acme/Qualification 10 - it is initializable class AcmeQualification does not exist. 80% 20% 5 2 specs 5 examples (4 passed, 1 broken) 24ms Do you want me to create `AcmeQualification` for you? [Y/n] Y Class AcmeQualification created in [dir]/src/Acme/Qualification.php. 100% 5 2 specs 5 examples (5 passed) 9ms
  • 42. MORE USER TESTS… use AcmeQualification; class UserSpec extends ObjectBehavior { function it_adds_a_qualification(Qualification $qualification) { $this->addQualification($qualification); $this->getQualifications()->shouldHaveCount(1); } }
  • 43. RUN AND CREATE THE METHODS $ vendor/bin/phpspec run Acme/User 36 - it adds a qualification method AcmeUser::addQualification not found. 80% 20% 5 2 specs 5 examples (4 passed, 1 broken) 24ms Do you want me to create `AcmeUser::addQualification()` for you? [Y/n] Y Method AcmeUser::addQualification() has been created. Acme/User 31 - it adds a qualification method AcmeUser::getQualifications not found. 80% 20% 5 2 specs 5 examples (4 passed, 1 broken) 15ms Do you want me to create `AcmeUser::getQualifications()` for you? [Y/n] Y Method AcmeUser::getQualifications() has been created. Acme/User 31 - it adds a qualification no haveCount([array:1]) matcher found for null. 80% 20% 5 2 specs 5 examples (4 passed, 1 broken) 20ms
  • 44. AND MAKE IT PASS… class User { private $qualifications = []; public function addQualification(Qualification $qualification) { $this->qualifications[] = $qualification; } public function getQualifications() { return $this->qualifications; } }
  • 45. CHECK IF IT PASSED $ vendor/bin/phpspec run 100% 5 2 specs 5 examples (5 passed) 14ms
  • 46. GREAT, BUT… “Users should be able to add up to 3 Qualifications” - The Client
  • 47. NO PROBLEM - ANOTHER TEST function it_prevents_more_than_3_qualifications_being_added(Qualification $qualification) { $this->addQualification($qualification); $this->addQualification($qualification); $this->addQualification($qualification); $this->shouldThrow(Exception::class)->duringAddQualification($qualification); }
  • 48. RUN IT $ vendor/bin/phpspec run Acme/User 37 - it prevents more than 3 qualifications being added expected to get exception, none got. 83% 16% 6 2 specs 6 examples (5 passed, 1 failed) 21ms
  • 49. AND MAKE IT PASS… class User { private $qualifications = []; public function addQualification(Qualification $qualification) { if(count($this->qualifications) === 3) { throw new Exception("You can't add more than 3 qualifications"); } $this->qualifications[] = $qualification; } }
  • 50. RUN IT $ vendor/bin/phpspec run 100% 6 2 specs 6 examples (6 passed) 17ms
  • 52. IDENTITY MATCHERS $this->getName()->shouldBe("Darren Craig"); $this->getName()->shouldBeEqualTo("Darren Craig"); $this->getName()->shouldReturn("Darren Craig"); $this->getName()->shouldEqual("Darren Craig");
  • 56. OBJECT STATE MATCHERS // calls $user->isOver18(); $this->shouldBeOver18(); // call $user->hasDOB(); $this->shouldHaveDOB(); A nice way of calling is* or has* methods on your object
  • 59.
  • 60. MORE WORK… LESS TEARS TDD encourages you to think first Smaller, single-responsibility classes More maintainable code More robust systems As your skill improves, so will your speed Less likely to spend hours debugging
  • 62. THANKS FOR LISTENING! DARREN CRAIG @minusdarren