SlideShare ist ein Scribd-Unternehmen logo
1 von 114
Downloaden Sie, um offline zu lesen
TDD with PhpSpec
with Ciaran McNulty
Lone Star PHP 2016
Before we start...
Install composer from getcomposer.org
Create composer.json in a new empty folder:
{
"require-dev" : {
"phpspec/phpspec" : "~2.0"
},
"config" : { "bin-dir" : "bin" },
"autoload": { "psr-0" : {"" : "src"} }
}
Run composer install
TDD with PhpSpec
with Ciaran McNulty
Lone Star PHP 2016
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 have described
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
Design principles
4 Optimise for descriptiveness
4 Encourage good design
4 Encourage TDD cycle
4 Do it the PHP way
History
2.0.0 to 2.5.0 - Steady improvement
4 Me
4 Christophe Coevoet
4 Jakub Zalas
4 Richard Miller
4 Gildas Quéméner
4 Luis Cordova + MANY MORE
Future
3.0.0 - This summer
4 Architecture cleanup
4 Dropping old dependencies (supports PHP5.6+)
4 Better suite config?
4 Cleaner extension mechanism?
4 Easier to add custom matchers?
Installation via Composer
{
"require-dev": {
"phpspec/phpspec": "~2.0"
},
"config": {
"bin-dir": "bin"
},
"autoload": {"psr-0": {"": "src"}}
}
A requirement:
We need a component that
greets 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]
# spec/HelloWorld/GreeterSpec.php
namespace specHelloWorld;
use PhpSpecObjectBehavior;
use ProphecyArgument;
class GreeterSpec extends ObjectBehavior
{
function it_is_initializable()
{
$this->shouldHaveType('HelloWorldGreeter');
}
}
Verifying object behaviour
4 Compare the real objects' behaviours with the
examples
Usage:
phpspec run
# src/HelloWorld/Greeter.php
namespace HelloWorld;
class Greeter
{
}
An example for Greeter:
When this greets, it should
return "Hello"
# spec/HelloWorld/GreeterSpec.php
class GreeterSpec extends ObjectBehavior
{
// ...
function it_greets_by_saying_hello()
{
$this->greet()->shouldReturn('Hello');
}
}
# src/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
# src/PhpDay/HelloWorld/Greeter.php
class Greeter
{
public function greet()
{
return 'Hello';
}
}
Describing values
Matchers
Matchers
# Equality
$this->greet()->shouldReturn('Hello');
$this->sum(3,3)->shouldEqual(6);
# Type
$this->getEmail()->shouldHaveType('Email');
$this->getTime()->shouldReturnAnInstanceOf('DateTime');
# Fuzzy value matching
$this->getSlug()->shouldMatch('/^[0-9a-z]+$/');
$this->getNames()->shouldContain('Tom');
Object state
// isAdmin() should return true
$this->getUser()->shouldBeAdmin();
// hasLoggedInUser() should return true
$this->shouldHaveLoggedInUser();
Custom matchers
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));
}
];
}
Wildcarding
4 In most cases you should know what arguments a
method will be invoked with
4 If not, you can use wildcards
$obj->doSomething(Argument::any())->will...;
$obj->save(Argument::type(User::class))->will...;
Describing Exceptions
The shouldThrow matcher
$this->shouldThrow(InvalidArgumentException::class)
->duringSave($user);
or
$this->shouldThrow(InvalidArgumentException::class)
->during(‘save’, [$user]);
Construction
// new User(‘Ciaran’)
$this->beConstructedWith('Ciaran');
// User::named(‘Ciaran’)
$this->beConstructedThrough('named', ['Ciaran']);
$this->beConstructedNamed('Ciaran');
// Testing constructor exceptions
$this->shouldThrow(InvalidArgumentException::class)
->duringInstantiation();
Exercise
4 Install PhpSpec using composer
4 Describe a Calculator that takes two numbers and
adds them together, by writing a few examples
(using phpspec describe)
4 Test the specificaiton and see it fail (using phpspec
run)
4 Implement the code so that the tests pass
The TDD Workflow
Coder's design process:
4 How should it behave?
4 How can I make it do that?
4 How can I make it do that well?
Coder's design process:
4 How should it behave?
Write a test
4 How can I make it do that?
Write some code
4 How can I make it do that well?
Improve what you wrote
The Rules of TDD
by Robert C Martin
1. Don’t write any code unless it is
to make a failing test pass.
2. Don’t write any more of a test
than is sufficient to fail.
3. Don’t write any more code than
is sufficient to pass the one
failing test.
Test - Describe the
next behaviour
4 Think about a behaviour the
object has that it doesn’t yet
4 Describe that behaviour in the
form of a test
4 Find the simple or degenerate
cases first
4 Don’t “Go for Gold”
Code - Make it pass
4 Code the most obvious or
simplest working solution
4 Don’t overthink design - do
that later
4 The test is failing! Get back to
green ASAP
Refactor - Improve
the design
4 Is there duplication?
4 What can be taken out?
4 Is the code clear and
expressive?
4 The tests are passing so we can
stop and think
Getting used to TDD
Pairing
4 Driver + Navigator roles
4 Driver controls the keyboard
4 Driver solves the immediate problems
4 Navigator checks the TDD rules are being enforced
4 Navigator thinks about what to test next, what
future problems might come up
Kata
4 Short exercises to practise TDD
4 Solve an achievable problem in a fixed time
4 Throw away the code and do it again differently
4 Focus on the process not the problem
You will probably not solve the problem on first attempt
Kata
4 String Calculator
4 Roman Numbers
4 Bowling
4 Tic-Tac-Toe
4 The Command Line Argument Parser
4 Prime Factors
4 Factorial
4 String Tokeniser
Kata - string calculator
Design an object that takes a string expression and calculates an integer.
4 No arguments evaluate to zero
4 Empty string should evaluate to zero
4 Zero as a string should evaluate to zero
4 Numeric string should evaluate to that number
4 Space separated numbers should be added together
4 Whitespace separated numbers should be added together
4 Custom separator can be specified (e.g. ’[+]1+2+3’ -> 6)
Describing Collaboration
Another example for Greeter:
When this greets a person
called "Bob", it should
return "Hello, Bob"
# spec/HelloWorld/GreeterSpec.php
use HelloWorldPerson;
class GreeterSpec extends ObjectBehavior
{
// ...
function it_greets_a_person_by_name(Person $person)
{
$person->getName()->willReturn('Bob');
$this->greet($person)->shouldReturn('Hello, Bob');
}
}
The Interface Segregation
Principle:
No client should be forced to
depend on methods it does not
use
1
Robert C Martin
# spec/HelloWorld/GreeterSpec.php
use HelloWorldNamed;
class GreeterSpec extends ObjectBehavior
{
// ...
function it_greets_named_things_by_name(Named $named)
{
$named->getName()->willReturn('Bob');
$this->greet($named)->shouldReturn('Hello, Bob');
}
}
# src/HelloWorld/Named.php
namespace HelloWorld;
interface Named
{
public function getName();
}
# src/HelloWorld/Greeter.php
class Greeter
{
public function greet()
{
return 'Hello';
}
}
Finally now we write some code!
# src/HelloWorld/Greeter.php
class Greeter
{
public function greet(Named $named = null)
{
return 'Hello';
}
}
# src/HelloWorld/Greeter.php
class Greeter
{
public function greet(Named $named = null)
{
$greeting = 'Hello';
if ($named) {
$greeting .= ', ' . $named->getName();
}
return $greeting;
}
}
An example for a Person:
When you ask a person
named "Bob" for their
name, they return "Bob"
# spec/HelloWorld/PersonSpec.php
class PersonSpec extends ObjectBehavior
{
function it_returns_the_name_it_is_created_with()
{
$this->beConstructedWith('Bob');
$this->getName()->shouldReturn('Bob');
}
}
# src/HelloWorld/Person.php
class Person
{
public function __construct($argument1)
{
// TODO: write logic here
}
public function getName()
{
// TODO: write logic here
}
}
# src/HelloWorld/Person.php
class Person implements Named
{
private $name;
public function __construct($name)
{
$this->name = $name;
}
public function getName()
{
return $this->name;
}
}
Another example for a Person:
When a person named
"Bob" changes their name
to "Alice", when you ask
their name they return
"Alice"
# spec/HelloWorld/PersonSpec.php
class PersonSpec extends ObjectBehavior
{
function it_returns_the_name_it_is_created_with()
{
$this->beConstructedWith('Bob');
$this->getName()->shouldReturn('Bob');
}
function it_returns_its_new_name_when_it_has_been_renamed()
{
$this->beConstructedWith('Bob');
$this->changeNameTo('Alice');
$this->getName()->shouldReturn('Alice');
}
}
# spec/HelloWorld/PersonSpec.php
class PersonSpec extends ObjectBehavior
{
function let()
{
$this->beConstructedWith('Bob');
}
function it_returns_the_name_it_is_created_with()
{
$this->getName()->shouldReturn('Bob');
}
function it_returns_its_new_name_when_it_has_been_renamed()
{
$this->changeNameTo('Alice');
$this->getName()->shouldReturn('Alice');
}
}
# src/HelloWorld/Person.php
class Person
{
private $name;
// …
public function changeNameTo($argument1)
{
// TODO: write logic here
}
}
# src/HelloWorld/Person.php
class Person
{
private $name;
// …
public function changeNameTo($name)
{
$this->name = $name;
}
}
Describing collaboration - Stubs
Stubs are when we describe how we interact with
objects we query
4 willReturn()
4 Doesn't care when or how many times the method is
called
Describing collaboration - Mocking and
Spying
Mocks or Spies are when we describe how we interact
with objects we command
4 shouldBeCalled() or shouldHaveBeenCalled()
4 Verifies that the method is called
Final example for Greeter:
When it greets Bob, the
message "Hello Bob" should
be logged
# spec/HelloWorld/GreeterSpec.php
class GreeterSpec extends ObjectBehavior
{
// ...
function it_greets_named_things_by_name(Named $named)
{
$named->getName()->willReturn('Bob');
$this->greet($named)->shouldReturn('Hello, Bob');
}
}
# spec/HelloWorld/GreeterSpec.php
class GreeterSpec extends ObjectBehavior
{
function let(Named $named)
{
$named->getName()->willReturn('Bob');
}
// ...
function it_greets_named_things_by_name(Named $named)
{
$this->greet($named)->shouldReturn('Hello, Bob');
}
}
# spec/HelloWorld/GreeterSpec.php
class GreeterSpec extends ObjectBehavior
{
function let(Named $named, Logger $logger)
{
$this->beConstructedWith($logger);
$named->getName()->willReturn('Bob');
}
// ...
function it_logs_the_greetings(Named $named, Logger $logger)
{
$this->greet($named);
$logger->log('Hello, Bob')->shouldHaveBeenCalled();
}
}
# src/HelloWorld/Greeter.php
class Greeter
{
public function __construct($argument1)
{
// TODO: write logic here
}
public function greet(Named $named = null)
{
$greeting = 'Hello';
if ($named) { $greeting .= ', ' . $named->getName(); }
return $greeting;
}
}
# src/HelloWorld/Greeter.php
class Greeter
{
private $logger;
public function __construct(Logger $logger)
{
$this->logger = $logger;
}
public function greet(Named $named = null)
{
$greeting = 'Hello';
if ($named) { $greeting .= ', ' . $named->getName(); }
$this->logger->log($greeting);
return $greeting;
}
}
What have we built?
The domain model
Kata - String Calculator
4 The String Calculator has more than one
responsibility:
1. Splitting the string into components
2. Combining them together again by summing
4 Do the exercise again, but this time use more than
one object to achieve the task
An high level test
echo $result = (new Calculator(new Splitter(), new Parser()))->evaluate('[x]1x2x3');
4 When your application becomes composed of small
self-contained objects, you need some higher level of
testing (e.g. PHPUnit or Behat)
Kata - string calculator
4 Empty string should evaluate to zero
4 Zero as a string should evaluate to zero
4 Numeric string should evaluate to that number
4 Space separated numbers should be added together
4 Whitespace separated numbers should be added
together
4 Custom separator can be specified (e.g. ’[+]1+2+3’ -> 6)
Thank you!
4 @ciaranmcnulty
4 Lead Maintainer of PhpSpec
4 SeniorTrainer at Inviqa
4 https://joind.in/talk/6a1ed
Questions?

Weitere ähnliche Inhalte

Was ist angesagt?

Ruby 程式語言綜覽簡介
Ruby 程式語言綜覽簡介Ruby 程式語言綜覽簡介
Ruby 程式語言綜覽簡介
Wen-Tien Chang
 
Zend Studio Tips and Tricks
Zend Studio Tips and TricksZend Studio Tips and Tricks
Zend Studio Tips and Tricks
Roy Ganor
 
Ruby 入門 第一次就上手
Ruby 入門 第一次就上手Ruby 入門 第一次就上手
Ruby 入門 第一次就上手
Wen-Tien Chang
 

Was ist angesagt? (20)

Kicking off with Zend Expressive and Doctrine ORM (PHPNW2016)
Kicking off with Zend Expressive and Doctrine ORM (PHPNW2016)Kicking off with Zend Expressive and Doctrine ORM (PHPNW2016)
Kicking off with Zend Expressive and Doctrine ORM (PHPNW2016)
 
Kicking off with Zend Expressive and Doctrine ORM (Sunshine PHP 2017)
Kicking off with Zend Expressive and Doctrine ORM (Sunshine PHP 2017)Kicking off with Zend Expressive and Doctrine ORM (Sunshine PHP 2017)
Kicking off with Zend Expressive and Doctrine ORM (Sunshine PHP 2017)
 
TDD, BDD, RSpec
TDD, BDD, RSpecTDD, BDD, RSpec
TDD, BDD, RSpec
 
PHP 5.4 New Features
PHP 5.4 New FeaturesPHP 5.4 New Features
PHP 5.4 New Features
 
Kicking off with Zend Expressive and Doctrine ORM (PHP Srbija 2017)
Kicking off with Zend Expressive and Doctrine ORM (PHP Srbija 2017)Kicking off with Zend Expressive and Doctrine ORM (PHP Srbija 2017)
Kicking off with Zend Expressive and Doctrine ORM (PHP Srbija 2017)
 
Crafting Quality PHP Applications (ConFoo YVR 2017)
Crafting Quality PHP Applications (ConFoo YVR 2017)Crafting Quality PHP Applications (ConFoo YVR 2017)
Crafting Quality PHP Applications (ConFoo YVR 2017)
 
Create a web-app with Cgi Appplication
Create a web-app with Cgi AppplicationCreate a web-app with Cgi Appplication
Create a web-app with Cgi Appplication
 
BDD with Behat and Symfony2
BDD with Behat and Symfony2BDD with Behat and Symfony2
BDD with Behat and Symfony2
 
Clean Code
Clean CodeClean Code
Clean Code
 
Modern Web Development with Perl
Modern Web Development with PerlModern Web Development with Perl
Modern Web Development with Perl
 
Ruby 程式語言綜覽簡介
Ruby 程式語言綜覽簡介Ruby 程式語言綜覽簡介
Ruby 程式語言綜覽簡介
 
Bringing modern PHP development to IBM i (ZendCon 2016)
Bringing modern PHP development to IBM i (ZendCon 2016)Bringing modern PHP development to IBM i (ZendCon 2016)
Bringing modern PHP development to IBM i (ZendCon 2016)
 
Dip Your Toes in the Sea of Security (ConFoo YVR 2017)
Dip Your Toes in the Sea of Security (ConFoo YVR 2017)Dip Your Toes in the Sea of Security (ConFoo YVR 2017)
Dip Your Toes in the Sea of Security (ConFoo YVR 2017)
 
Crafting Quality PHP Applications (PHP Benelux 2018)
Crafting Quality PHP Applications (PHP Benelux 2018)Crafting Quality PHP Applications (PHP Benelux 2018)
Crafting Quality PHP Applications (PHP Benelux 2018)
 
Object Oriented Design Patterns for PHP
Object Oriented Design Patterns for PHPObject Oriented Design Patterns for PHP
Object Oriented Design Patterns for PHP
 
Ant
Ant Ant
Ant
 
Zend Studio Tips and Tricks
Zend Studio Tips and TricksZend Studio Tips and Tricks
Zend Studio Tips and Tricks
 
Ruby 入門 第一次就上手
Ruby 入門 第一次就上手Ruby 入門 第一次就上手
Ruby 入門 第一次就上手
 
Testing Ruby with Rspec (a beginner's guide)
Testing Ruby with Rspec (a beginner's guide)Testing Ruby with Rspec (a beginner's guide)
Testing Ruby with Rspec (a beginner's guide)
 
RSpec 3: The new, the old, the good
RSpec 3: The new, the old, the goodRSpec 3: The new, the old, the good
RSpec 3: The new, the old, the good
 

Andere mochten auch

Get Soaked - An In Depth Look At PHP Streams
Get Soaked - An In Depth Look At PHP StreamsGet Soaked - An In Depth Look At PHP Streams
Get Soaked - An In Depth Look At PHP Streams
Davey Shafik
 
Why elasticsearch rocks!
Why elasticsearch rocks!Why elasticsearch rocks!
Why elasticsearch rocks!
tlrx
 
L'ABC du BDD (Behavior Driven Development)
L'ABC du BDD (Behavior Driven Development)L'ABC du BDD (Behavior Driven Development)
L'ABC du BDD (Behavior Driven Development)
Arnauld Loyer
 

Andere mochten auch (20)

PhpSpec 2.0 ilustrated by examples
PhpSpec 2.0 ilustrated by examplesPhpSpec 2.0 ilustrated by examples
PhpSpec 2.0 ilustrated by examples
 
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
 
Tactical DDD (just better OOP?) - PHPBenelux 2017
Tactical DDD (just better OOP?) - PHPBenelux 2017Tactical DDD (just better OOP?) - PHPBenelux 2017
Tactical DDD (just better OOP?) - PHPBenelux 2017
 
Techniques d'accélération des pages web
Techniques d'accélération des pages webTechniques d'accélération des pages web
Techniques d'accélération des pages web
 
Get Soaked - An In Depth Look At PHP Streams
Get Soaked - An In Depth Look At PHP StreamsGet Soaked - An In Depth Look At PHP Streams
Get Soaked - An In Depth Look At PHP Streams
 
Diving deep into twig
Diving deep into twigDiving deep into twig
Diving deep into twig
 
Elastic Searching With PHP
Elastic Searching With PHPElastic Searching With PHP
Elastic Searching With PHP
 
Automation using-phing
Automation using-phingAutomation using-phing
Automation using-phing
 
PHP5.5 is Here
PHP5.5 is HerePHP5.5 is Here
PHP5.5 is Here
 
Electrify your code with PHP Generators
Electrify your code with PHP GeneratorsElectrify your code with PHP Generators
Electrify your code with PHP Generators
 
The quest for global design principles (SymfonyLive Berlin 2015)
The quest for global design principles (SymfonyLive Berlin 2015)The quest for global design principles (SymfonyLive Berlin 2015)
The quest for global design principles (SymfonyLive Berlin 2015)
 
Mocking Demystified
Mocking DemystifiedMocking Demystified
Mocking Demystified
 
Top tips my_sql_performance
Top tips my_sql_performanceTop tips my_sql_performance
Top tips my_sql_performance
 
Understanding Craftsmanship SwanseaCon2015
Understanding Craftsmanship SwanseaCon2015Understanding Craftsmanship SwanseaCon2015
Understanding Craftsmanship SwanseaCon2015
 
Why elasticsearch rocks!
Why elasticsearch rocks!Why elasticsearch rocks!
Why elasticsearch rocks!
 
Writing infinite scalability web applications with PHP and PostgreSQL
Writing infinite scalability web applications with PHP and PostgreSQLWriting infinite scalability web applications with PHP and PostgreSQL
Writing infinite scalability web applications with PHP and PostgreSQL
 
Si le tdd est mort alors pratiquons une autopsie mix-it 2015
Si le tdd est mort alors pratiquons une autopsie mix-it 2015Si le tdd est mort alors pratiquons une autopsie mix-it 2015
Si le tdd est mort alors pratiquons une autopsie mix-it 2015
 
L'ABC du BDD (Behavior Driven Development)
L'ABC du BDD (Behavior Driven Development)L'ABC du BDD (Behavior Driven Development)
L'ABC du BDD (Behavior Driven Development)
 
Caching on the Edge
Caching on the EdgeCaching on the Edge
Caching on the Edge
 
Behat 3.0 meetup (March)
Behat 3.0 meetup (March)Behat 3.0 meetup (March)
Behat 3.0 meetup (March)
 

Ähnlich wie TDD with PhpSpec - Lone Star PHP 2016

BDD style Unit Testing
BDD style Unit TestingBDD style Unit Testing
BDD style Unit Testing
Wen-Tien Chang
 
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
 

Ähnlich wie TDD with PhpSpec - Lone Star PHP 2016 (20)

Good Coding Practices with JavaScript
Good Coding Practices with JavaScriptGood Coding Practices with JavaScript
Good Coding Practices with JavaScript
 
Rspec and Capybara Intro Tutorial at RailsConf 2013
Rspec and Capybara Intro Tutorial at RailsConf 2013Rspec and Capybara Intro Tutorial at RailsConf 2013
Rspec and Capybara Intro Tutorial at RailsConf 2013
 
New Ideas for Old Code - Greach
New Ideas for Old Code - GreachNew Ideas for Old Code - Greach
New Ideas for Old Code - Greach
 
It's all about behaviour, also in php - phpspec
It's all about behaviour, also in php - phpspecIt's all about behaviour, also in php - phpspec
It's all about behaviour, also in php - phpspec
 
Random Ruby Tips - Ruby Meetup 27 Jun 2018
Random Ruby Tips - Ruby Meetup 27 Jun 2018Random Ruby Tips - Ruby Meetup 27 Jun 2018
Random Ruby Tips - Ruby Meetup 27 Jun 2018
 
Writing Readable Code
Writing Readable CodeWriting Readable Code
Writing Readable Code
 
In-Depth Guide On WordPress Coding Standards For PHP & HTML
In-Depth Guide On WordPress Coding Standards For PHP & HTMLIn-Depth Guide On WordPress Coding Standards For PHP & HTML
In-Depth Guide On WordPress Coding Standards For PHP & HTML
 
Start using PHP 7
Start using PHP 7Start using PHP 7
Start using PHP 7
 
Behavior Driven Development with Rails
Behavior Driven Development with RailsBehavior Driven Development with Rails
Behavior Driven Development with Rails
 
PhpSpec: practical introduction
PhpSpec: practical introductionPhpSpec: practical introduction
PhpSpec: practical introduction
 
resolvendo problemas de comunicação em equipes distribuídas com bdd
resolvendo problemas de comunicação em equipes distribuídas com bddresolvendo problemas de comunicação em equipes distribuídas com bdd
resolvendo problemas de comunicação em equipes distribuídas com bdd
 
BDD style Unit Testing
BDD style Unit TestingBDD style Unit Testing
BDD style Unit Testing
 
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
 
Clean code and code smells
Clean code and code smellsClean code and code smells
Clean code and code smells
 
Kicking off with Zend Expressive and Doctrine ORM (ZendCon 2016)
Kicking off with Zend Expressive and Doctrine ORM (ZendCon 2016)Kicking off with Zend Expressive and Doctrine ORM (ZendCon 2016)
Kicking off with Zend Expressive and Doctrine ORM (ZendCon 2016)
 
Php extensions
Php extensionsPhp extensions
Php extensions
 
Puppet Camp Paris 2014: Test Driven Development
Puppet Camp Paris 2014: Test Driven DevelopmentPuppet Camp Paris 2014: Test Driven Development
Puppet Camp Paris 2014: Test Driven Development
 
20140408 tdd puppetcamp-paris
20140408 tdd puppetcamp-paris20140408 tdd puppetcamp-paris
20140408 tdd puppetcamp-paris
 
Dutch PHP Conference 2013: Distilled
Dutch PHP Conference 2013: DistilledDutch PHP Conference 2013: Distilled
Dutch PHP Conference 2013: Distilled
 
Simplifying Code: Monster to Elegant in 5 Steps
Simplifying Code: Monster to Elegant in 5 StepsSimplifying Code: Monster to Elegant in 5 Steps
Simplifying Code: Monster to Elegant in 5 Steps
 

Mehr von CiaranMcNulty

Mehr von CiaranMcNulty (17)

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

Kürzlich hochgeladen

%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
masabamasaba
 
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
masabamasaba
 
Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024
Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024
Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024
VictoriaMetrics
 
Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...
Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...
Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...
Medical / Health Care (+971588192166) Mifepristone and Misoprostol tablets 200mg
 
%+27788225528 love spells in Huntington Beach Psychic Readings, Attraction sp...
%+27788225528 love spells in Huntington Beach Psychic Readings, Attraction sp...%+27788225528 love spells in Huntington Beach Psychic Readings, Attraction sp...
%+27788225528 love spells in Huntington Beach Psychic Readings, Attraction sp...
masabamasaba
 
%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...
masabamasaba
 

Kürzlich hochgeladen (20)

WSO2CON 2024 - API Management Usage at La Poste and Its Impact on Business an...
WSO2CON 2024 - API Management Usage at La Poste and Its Impact on Business an...WSO2CON 2024 - API Management Usage at La Poste and Its Impact on Business an...
WSO2CON 2024 - API Management Usage at La Poste and Its Impact on Business an...
 
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
 
VTU technical seminar 8Th Sem on Scikit-learn
VTU technical seminar 8Th Sem on Scikit-learnVTU technical seminar 8Th Sem on Scikit-learn
VTU technical seminar 8Th Sem on Scikit-learn
 
tonesoftg
tonesoftgtonesoftg
tonesoftg
 
%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain
%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain
%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain
 
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
 
Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024
Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024
Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024
 
WSO2Con204 - Hard Rock Presentation - Keynote
WSO2Con204 - Hard Rock Presentation - KeynoteWSO2Con204 - Hard Rock Presentation - Keynote
WSO2Con204 - Hard Rock Presentation - Keynote
 
WSO2CON 2024 - Does Open Source Still Matter?
WSO2CON 2024 - Does Open Source Still Matter?WSO2CON 2024 - Does Open Source Still Matter?
WSO2CON 2024 - Does Open Source Still Matter?
 
Architecture decision records - How not to get lost in the past
Architecture decision records - How not to get lost in the pastArchitecture decision records - How not to get lost in the past
Architecture decision records - How not to get lost in the past
 
Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...
Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...
Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...
 
%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisa%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisa
 
%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein
%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein
%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein
 
WSO2CON 2024 Slides - Open Source to SaaS
WSO2CON 2024 Slides - Open Source to SaaSWSO2CON 2024 Slides - Open Source to SaaS
WSO2CON 2024 Slides - Open Source to SaaS
 
%+27788225528 love spells in Huntington Beach Psychic Readings, Attraction sp...
%+27788225528 love spells in Huntington Beach Psychic Readings, Attraction sp...%+27788225528 love spells in Huntington Beach Psychic Readings, Attraction sp...
%+27788225528 love spells in Huntington Beach Psychic Readings, Attraction sp...
 
WSO2CON 2024 - Building the API First Enterprise – Running an API Program, fr...
WSO2CON 2024 - Building the API First Enterprise – Running an API Program, fr...WSO2CON 2024 - Building the API First Enterprise – Running an API Program, fr...
WSO2CON 2024 - Building the API First Enterprise – Running an API Program, fr...
 
%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...
 
Announcing Codolex 2.0 from GDK Software
Announcing Codolex 2.0 from GDK SoftwareAnnouncing Codolex 2.0 from GDK Software
Announcing Codolex 2.0 from GDK Software
 
%in kaalfontein+277-882-255-28 abortion pills for sale in kaalfontein
%in kaalfontein+277-882-255-28 abortion pills for sale in kaalfontein%in kaalfontein+277-882-255-28 abortion pills for sale in kaalfontein
%in kaalfontein+277-882-255-28 abortion pills for sale in kaalfontein
 
WSO2CON2024 - It's time to go Platformless
WSO2CON2024 - It's time to go PlatformlessWSO2CON2024 - It's time to go Platformless
WSO2CON2024 - It's time to go Platformless
 

TDD with PhpSpec - Lone Star PHP 2016