SlideShare a Scribd company logo
1 of 40
PHPUnit elevato alla Symfony2




                 Eugenio Pombi
                  Symfony Day 05 October 2012



@euxpom                                         nerd2business.net
Symfony2 Functional testing tools

●   SymfonyBundleFrameworkBundleClient
●   SymfonyBundleFrameworkBundleCrawler
●   SymfonyComponentHttpKernelProfilerProfile
●   SymfonyBundleDoctrineFixturesBundle
Profiler
config                               time
   ->getBundles()                       ->getTotalTime()
   ->getEnv()                        memory
request                                 ->getMemory()
   ->getRouteParams()                router
   ->getController()                    ->getRedirect()
exception                            security
   ->hasException()                     ->getUser()
events
                                        ->getRoles()
   ->GetCalledListeners()
                                        ->isAuthenticated()
   ->getNotCalledListeners()
                                     swiftmailer
logger
                                        ->getMessageCount()
   ->CountErrors()
                                        ->getMessages()
   ->getLogs()
Doctrine profiler
db
     ->getQueryCount()
     ->getTime()
     ->getQueries()

               query
                      ['sql']
                      ['params']
                      ['types']
                      ['executionMS']
Stubbing



An example with Paypal
namespace JMSPaymentPaypalBundleClient;

class Client {
    [...]
    public function request(Request $request) {
        [...]
        // perform the request
        if (false === $returnTransfer = curl_exec($curl)) {
            throw new CommunicationException(
                'cURL Error: '.curl_error($curl), curl_errno($curl)
            );
        }
        [...]
        $response = new RawResponse(
            substr($returnTransfer, $headerSize),
            curl_getinfo($curl, CURLINFO_HTTP_CODE),
            $headers
        );
        curl_close($curl);
        return $response;
    }
}
namespace JMSPaymentPaypalBundleClient;

class Client {
    [...]
    public function request(Request $request) {
        [...]
        // perform the request
        if (false === $returnTransfer = curl_exec($curl)) {
            throw new CommunicationException(
                'cURL Error: '.curl_error($curl), curl_errno($curl)
            );
        }
        [...]
        $response = new RawResponse(
            substr($returnTransfer, $headerSize),
            curl_getinfo($curl, CURLINFO_HTTP_CODE),
            $headers
        );
        curl_close($curl);
        return $response;
    }
}
namespace JMSPaymentPaypalBundleClient;

class Client {
    [...]
    public function request(Request $request) {
        [...]
        // perform the request
        if (false === $returnTransfer = curl_exec($curl)) {
            throw new CommunicationException(
                'cURL Error: '.curl_error($curl), curl_errno($curl)
            );
        }
        [...]
        $response = new RawResponse(
            substr($returnTransfer, $headerSize),
            curl_getinfo($curl, CURLINFO_HTTP_CODE),
            $headers
        );
        curl_close($curl);
        return $response;
    }
}
namespace ACMEPaymentBundleTestsStub;

use JMSPaymentPaypalBundleClientClient;

class PaypalClientStub extends Client {
    public function request(Request $request)
    {
        $response = new RawResponse(
                "TOKEN=BlaBlaBlaBla",
                200,
                array(
                  'Date' => "Fri, 07 Sep 2012 15:21:00 GMT",
                  'Server' => "Apache",
                )
        );
        return $response;
    }
}
namespace ACMEPaymentBundleTestsStub;

use JMSPaymentPaypalBundleClientClient;

class PaypalClientStub extends Client {
    public function request(Request $request)
    {
        $response = new RawResponse(
                "TOKEN=BlaBlaBlaBla",
                200,
                array(
                  'Date' => "Fri, 07 Sep 2012 15:21:00 GMT",
                  'Server' => "Apache",
                )
        );
        return $response;
    }
}
services.xml

<parameter key="payment.paypal.client.class">
    JMSPaymentPaypalBundleClientClient
</parameter>




config_test.yml

parameters:
    payment.paypal.client.class:
ACMEPaymentBundleTestsStubPaypalClientStub
namespace JMSPaymentPaypalBundleClient;


class Client {
    [...]
    public function getAuthenticateExpressCheckoutTokenUrl($token) {
        $host = $this->isDebug ? 'www.sandbox.paypal.com':'www.paypal.com';


        return $host;
    }
}
namespace ACMEPaymentBundleTestsStub;
use JMSPaymentPaypalBundleClientClient;


class PaypalClientStub extends Client {
    public function getAuthenticateExpressCheckoutTokenUrl($token)
    {
        return '/payment/paypalFakeController';
    }
}
namespace ACMEPaymentBundleTestsStub;
use JMSPaymentPaypalBundleClientClient;


class PaypalClientStub extends Client {
    public function request(Request $request)
    {
        if ($request->request->get('METHOD') == 'SetExpressCheckout') {
            $response = new RawResponse(
             "TOKEN=BlaBlaBla",
           );
        } elseif ($request->request->get('METHOD') == 'GetExpressCheckoutDetails')
{
           $response = new RawResponse(
             "CHECKOUTSTATUS=PaymentCompleted&ACK=Success",
           );
        } elseif ($request->request->get('METHOD') == 'DoExpressCheckoutPayment'){
            $response = new RawResponse(
             "PAYMENTINFO_0_PAYMENTSTATUS=Completed",
           );
        }
        return $response;
    }
}
namespace ACMEPaymentBundleTestsStub;
use JMSPaymentPaypalBundleClientClient;


class PaypalClientStub extends Client {
    public function request(Request $request)
    {
        if ($request->request->get('METHOD') == 'SetExpressCheckout') {
            $response = new RawResponse(
             "TOKEN=BlaBlaBla",
           );
        } elseif ($request->request->get('METHOD') == 'GetExpressCheckoutDetails')
{
           $response = new RawResponse(
             "CHECKOUTSTATUS=PaymentCompleted&ACK=Success",
           );
        } elseif ($request->request->get('METHOD') == 'DoExpressCheckoutPayment'){
            $response = new RawResponse(
             "PAYMENTINFO_0_PAYMENTSTATUS=Completed",
           );
        }
        return $response;
    }
}
namespace ACMEPaymentBundleTestsStub;
use JMSPaymentPaypalBundleClientClient;


class PaypalClientStub extends Client {
    public function request(Request $request)
    {
        if ($request->request->get('METHOD') == 'SetExpressCheckout') {
            $response = new RawResponse(
             "TOKEN=BlaBlaBla",
           );
        } elseif ($request->request->get('METHOD') == 'GetExpressCheckoutDetails')
{
           $response = new RawResponse(
             "CHECKOUTSTATUS=PaymentCompleted&ACK=Success",
           );
        } elseif ($request->request->get('METHOD') == 'DoExpressCheckoutPayment'){
            $response = new RawResponse(
             "PAYMENTINFO_0_PAYMENTSTATUS=Completed",
           );
        }
        return $response;
    }
}
Something is missing
Control on the request
namespace ACMEPaymentBundleTestsStub;
use JMSPaymentPaypalBundleClientClient;

class PaypalClientStub extends Client {
    public function request(Request $request)
    {
        if ($request != "OK STUFF") {
          throw new Exception ("Wrong Request for Paypal
call");
        }
        [...]

        return $response;
    }
}
What is “outside”?

●   External API
What is “outside”?

●   External API
●   OS services (time)
What is “outside”?

●   External API
●   OS services (time)
●   Systems that don't exist yet
What is “outside”?

●   External API
●   OS services (time)
●   Systems that don't exist yet
●   Systems that other people is working on
What is “outside”?

●   External API
●   OS services (time)
●   Systems that don't exist yet
●   Systems that other people is working on
●   Monsters from the inside(legacy code)
The date/time case
●   A user can see the next three appointments
The date/time case
●   A user can see the next three appointments

●   A user is shown an alert in home page if she
    has an appointment in the next 6 hours
The date/time case
●   A user can see the next three appointments

●   A user is shown an alert in home page if she
    has an appointment in the next 6 hours
●   A user can take an appointment for the next
    day, but if it is Friday the next eligible day will
    be Monday
namespace ACMECoreBundleService;

class Time
{
    public static function getNow()
    {
        return new DateTime();
    }
}
namespace AcmeCoreBundleTestService;

class Time
{
    public static $referenceTime = '2012-05-01 12:00:00';
    public static $time = null;

    public static function getNow()
    {
        if (is_null(self::$time)) {
            return new DateTime(self::$referenceTime);
        } else {
            return new DateTime(self::$time);
        }
    }
}
namespace AcmeCoreBundleTestService;

class Time
{
    public static $referenceTime = '2012-05-01 12:00:00';
    public static $time = null;

    public static function getNow()
    {
        if (is_null(self::$time)) {
            return new DateTime(self::$referenceTime);
        } else {
            return new DateTime(self::$time);
        }
    }
}
Inside the fixtures

Use AcmeCoreBundleTestServiceTime;


public function load(ObjectManager $manager)
{
    $appointmentToday = new Appointment();
    $appointmentToday->setDateTime(new DateTime(Time::$referenceTime));
    [...]
}
Inside the test
Use AcmeCoreBundleTestServiceTime;

public function test_customerHome()
{
  AcmeCoreBundleTestServiceTime::$time = "2012-06-01";

    [...]
}
Different config states


$client =
   self::createClient(array('environment' => 'test_alternative'));
Thank You


            @euxpom
            nerd2business.net

More Related Content

What's hot

Doctrine fixtures
Doctrine fixturesDoctrine fixtures
Doctrine fixtures
Bill Chang
 
international PHP2011_Bastian Feder_jQuery's Secrets
international PHP2011_Bastian Feder_jQuery's Secretsinternational PHP2011_Bastian Feder_jQuery's Secrets
international PHP2011_Bastian Feder_jQuery's Secrets
smueller_sandsmedia
 

What's hot (20)

Design Patterns avec PHP 5.3, Symfony et Pimple
Design Patterns avec PHP 5.3, Symfony et PimpleDesign Patterns avec PHP 5.3, Symfony et Pimple
Design Patterns avec PHP 5.3, Symfony et Pimple
 
Silex meets SOAP & REST
Silex meets SOAP & RESTSilex meets SOAP & REST
Silex meets SOAP & REST
 
Min-Maxing Software Costs
Min-Maxing Software CostsMin-Maxing Software Costs
Min-Maxing Software Costs
 
Doctrine fixtures
Doctrine fixturesDoctrine fixtures
Doctrine fixtures
 
Symfony2, creare bundle e valore per il cliente
Symfony2, creare bundle e valore per il clienteSymfony2, creare bundle e valore per il cliente
Symfony2, creare bundle e valore per il cliente
 
Rich domain model with symfony 2.5 and doctrine 2.5
Rich domain model with symfony 2.5 and doctrine 2.5Rich domain model with symfony 2.5 and doctrine 2.5
Rich domain model with symfony 2.5 and doctrine 2.5
 
Things I Believe Now That I'm Old
Things I Believe Now That I'm OldThings I Believe Now That I'm Old
Things I Believe Now That I'm Old
 
Min-Maxing Software Costs - Laracon EU 2015
Min-Maxing Software Costs - Laracon EU 2015Min-Maxing Software Costs - Laracon EU 2015
Min-Maxing Software Costs - Laracon EU 2015
 
The IoC Hydra
The IoC HydraThe IoC Hydra
The IoC Hydra
 
Object Calisthenics Adapted for PHP
Object Calisthenics Adapted for PHPObject Calisthenics Adapted for PHP
Object Calisthenics Adapted for PHP
 
international PHP2011_Bastian Feder_jQuery's Secrets
international PHP2011_Bastian Feder_jQuery's Secretsinternational PHP2011_Bastian Feder_jQuery's Secrets
international PHP2011_Bastian Feder_jQuery's Secrets
 
Decoupling the Ulabox.com monolith. From CRUD to DDD
Decoupling the Ulabox.com monolith. From CRUD to DDDDecoupling the Ulabox.com monolith. From CRUD to DDD
Decoupling the Ulabox.com monolith. From CRUD to DDD
 
Rich Model And Layered Architecture in SF2 Application
Rich Model And Layered Architecture in SF2 ApplicationRich Model And Layered Architecture in SF2 Application
Rich Model And Layered Architecture in SF2 Application
 
PHPCon 2016: PHP7 by Witek Adamus / XSolve
PHPCon 2016: PHP7 by Witek Adamus / XSolvePHPCon 2016: PHP7 by Witek Adamus / XSolve
PHPCon 2016: PHP7 by Witek Adamus / XSolve
 
Introduction to Zend Framework web services
Introduction to Zend Framework web servicesIntroduction to Zend Framework web services
Introduction to Zend Framework web services
 
The IoC Hydra - Dutch PHP Conference 2016
The IoC Hydra - Dutch PHP Conference 2016The IoC Hydra - Dutch PHP Conference 2016
The IoC Hydra - Dutch PHP Conference 2016
 
Advanced php testing in action
Advanced php testing in actionAdvanced php testing in action
Advanced php testing in action
 
Crafting beautiful software
Crafting beautiful softwareCrafting beautiful software
Crafting beautiful software
 
Object Calisthenics Applied to PHP
Object Calisthenics Applied to PHPObject Calisthenics Applied to PHP
Object Calisthenics Applied to PHP
 
SOLID: the core principles of success of the Symfony web framework and of you...
SOLID: the core principles of success of the Symfony web framework and of you...SOLID: the core principles of success of the Symfony web framework and of you...
SOLID: the core principles of success of the Symfony web framework and of you...
 

Similar to PHPUnit elevato alla Symfony2

Phpne august-2012-symfony-components-friends
Phpne august-2012-symfony-components-friendsPhpne august-2012-symfony-components-friends
Phpne august-2012-symfony-components-friends
Michael Peacock
 
Mocking Dependencies in PHPUnit
Mocking Dependencies in PHPUnitMocking Dependencies in PHPUnit
Mocking Dependencies in PHPUnit
mfrost503
 

Similar to PHPUnit elevato alla Symfony2 (20)

Doctrine For Beginners
Doctrine For BeginnersDoctrine For Beginners
Doctrine For Beginners
 
Forget about Index.php and build you applications around HTTP - PHPers Cracow
Forget about Index.php and build you applications around HTTP - PHPers CracowForget about Index.php and build you applications around HTTP - PHPers Cracow
Forget about Index.php and build you applications around HTTP - PHPers Cracow
 
Phpne august-2012-symfony-components-friends
Phpne august-2012-symfony-components-friendsPhpne august-2012-symfony-components-friends
Phpne august-2012-symfony-components-friends
 
Forget about index.php and build you applications around HTTP!
Forget about index.php and build you applications around HTTP!Forget about index.php and build you applications around HTTP!
Forget about index.php and build you applications around HTTP!
 
WordPress REST API hacking
WordPress REST API hackingWordPress REST API hacking
WordPress REST API hacking
 
Symfony components in the wild, PHPNW12
Symfony components in the wild, PHPNW12Symfony components in the wild, PHPNW12
Symfony components in the wild, PHPNW12
 
laravel tricks in 50minutes
laravel tricks in 50minuteslaravel tricks in 50minutes
laravel tricks in 50minutes
 
50 Laravel Tricks in 50 Minutes
50 Laravel Tricks in 50 Minutes50 Laravel Tricks in 50 Minutes
50 Laravel Tricks in 50 Minutes
 
Unit testing with zend framework tek11
Unit testing with zend framework tek11Unit testing with zend framework tek11
Unit testing with zend framework tek11
 
Mocking Dependencies in PHPUnit
Mocking Dependencies in PHPUnitMocking Dependencies in PHPUnit
Mocking Dependencies in PHPUnit
 
Your code sucks, let's fix it - DPC UnCon
Your code sucks, let's fix it - DPC UnConYour code sucks, let's fix it - DPC UnCon
Your code sucks, let's fix it - DPC UnCon
 
Symfony2 Building on Alpha / Beta technology
Symfony2 Building on Alpha / Beta technologySymfony2 Building on Alpha / Beta technology
Symfony2 Building on Alpha / Beta technology
 
Easy rest service using PHP reflection api
Easy rest service using PHP reflection apiEasy rest service using PHP reflection api
Easy rest service using PHP reflection api
 
Bag Of Tricks From Iusethis
Bag Of Tricks From IusethisBag Of Tricks From Iusethis
Bag Of Tricks From Iusethis
 
Unit testing zend framework apps
Unit testing zend framework appsUnit testing zend framework apps
Unit testing zend framework apps
 
The Zen of Lithium
The Zen of LithiumThe Zen of Lithium
The Zen of Lithium
 
Bacbkone js
Bacbkone jsBacbkone js
Bacbkone js
 
Unit testing with zend framework PHPBenelux
Unit testing with zend framework PHPBeneluxUnit testing with zend framework PHPBenelux
Unit testing with zend framework PHPBenelux
 
(PHPers Wrocław #5) How to write valuable unit test?
(PHPers Wrocław #5) How to write valuable unit test?(PHPers Wrocław #5) How to write valuable unit test?
(PHPers Wrocław #5) How to write valuable unit test?
 
How Kris Writes Symfony Apps
How Kris Writes Symfony AppsHow Kris Writes Symfony Apps
How Kris Writes Symfony Apps
 

More from eugenio pombi

More from eugenio pombi (7)

Parlo al mio codice
Parlo al mio codiceParlo al mio codice
Parlo al mio codice
 
Processing one year of leading for Pug roma
Processing one year of leading for Pug romaProcessing one year of leading for Pug roma
Processing one year of leading for Pug roma
 
Datagrids with Symfony 2, Backbone and Backgrid
Datagrids with Symfony 2, Backbone and BackgridDatagrids with Symfony 2, Backbone and Backgrid
Datagrids with Symfony 2, Backbone and Backgrid
 
Codemotion workshop
Codemotion workshopCodemotion workshop
Codemotion workshop
 
Arduino - il mio primo sketch
Arduino - il mio primo sketchArduino - il mio primo sketch
Arduino - il mio primo sketch
 
Appetite comes with testing
Appetite comes with testingAppetite comes with testing
Appetite comes with testing
 
breve introduzione a node.js
breve introduzione a node.jsbreve introduzione a node.js
breve introduzione a node.js
 

Recently uploaded

Recently uploaded (20)

Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...
Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...
Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...
 
Corporate and higher education May webinar.pptx
Corporate and higher education May webinar.pptxCorporate and higher education May webinar.pptx
Corporate and higher education May webinar.pptx
 
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data DiscoveryTrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
 
Emergent Methods: Multi-lingual narrative tracking in the news - real-time ex...
Emergent Methods: Multi-lingual narrative tracking in the news - real-time ex...Emergent Methods: Multi-lingual narrative tracking in the news - real-time ex...
Emergent Methods: Multi-lingual narrative tracking in the news - real-time ex...
 
Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...
 
DEV meet-up UiPath Document Understanding May 7 2024 Amsterdam
DEV meet-up UiPath Document Understanding May 7 2024 AmsterdamDEV meet-up UiPath Document Understanding May 7 2024 Amsterdam
DEV meet-up UiPath Document Understanding May 7 2024 Amsterdam
 
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
 
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
 
Biography Of Angeliki Cooney | Senior Vice President Life Sciences | Albany, ...
Biography Of Angeliki Cooney | Senior Vice President Life Sciences | Albany, ...Biography Of Angeliki Cooney | Senior Vice President Life Sciences | Albany, ...
Biography Of Angeliki Cooney | Senior Vice President Life Sciences | Albany, ...
 
AWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of TerraformAWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of Terraform
 
Mcleodganj Call Girls 🥰 8617370543 Service Offer VIP Hot Model
Mcleodganj Call Girls 🥰 8617370543 Service Offer VIP Hot ModelMcleodganj Call Girls 🥰 8617370543 Service Offer VIP Hot Model
Mcleodganj Call Girls 🥰 8617370543 Service Offer VIP Hot Model
 
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
 
Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...
Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...
Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...
 
Platformless Horizons for Digital Adaptability
Platformless Horizons for Digital AdaptabilityPlatformless Horizons for Digital Adaptability
Platformless Horizons for Digital Adaptability
 
MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024
 
ICT role in 21st century education and its challenges
ICT role in 21st century education and its challengesICT role in 21st century education and its challenges
ICT role in 21st century education and its challenges
 
Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...
Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...
Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...
 
Rising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdf
Rising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdfRising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdf
Rising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdf
 
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot TakeoffStrategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
 
Understanding the FAA Part 107 License ..
Understanding the FAA Part 107 License ..Understanding the FAA Part 107 License ..
Understanding the FAA Part 107 License ..
 

PHPUnit elevato alla Symfony2

  • 1. PHPUnit elevato alla Symfony2 Eugenio Pombi Symfony Day 05 October 2012 @euxpom nerd2business.net
  • 2. Symfony2 Functional testing tools ● SymfonyBundleFrameworkBundleClient ● SymfonyBundleFrameworkBundleCrawler ● SymfonyComponentHttpKernelProfilerProfile ● SymfonyBundleDoctrineFixturesBundle
  • 3. Profiler config time ->getBundles() ->getTotalTime() ->getEnv() memory request ->getMemory() ->getRouteParams() router ->getController() ->getRedirect() exception security ->hasException() ->getUser() events ->getRoles() ->GetCalledListeners() ->isAuthenticated() ->getNotCalledListeners() swiftmailer logger ->getMessageCount() ->CountErrors() ->getMessages() ->getLogs()
  • 4. Doctrine profiler db ->getQueryCount() ->getTime() ->getQueries() query ['sql'] ['params'] ['types'] ['executionMS']
  • 6.
  • 7.
  • 8.
  • 9.
  • 10. namespace JMSPaymentPaypalBundleClient; class Client { [...] public function request(Request $request) { [...] // perform the request if (false === $returnTransfer = curl_exec($curl)) { throw new CommunicationException( 'cURL Error: '.curl_error($curl), curl_errno($curl) ); } [...] $response = new RawResponse( substr($returnTransfer, $headerSize), curl_getinfo($curl, CURLINFO_HTTP_CODE), $headers ); curl_close($curl); return $response; } }
  • 11. namespace JMSPaymentPaypalBundleClient; class Client { [...] public function request(Request $request) { [...] // perform the request if (false === $returnTransfer = curl_exec($curl)) { throw new CommunicationException( 'cURL Error: '.curl_error($curl), curl_errno($curl) ); } [...] $response = new RawResponse( substr($returnTransfer, $headerSize), curl_getinfo($curl, CURLINFO_HTTP_CODE), $headers ); curl_close($curl); return $response; } }
  • 12. namespace JMSPaymentPaypalBundleClient; class Client { [...] public function request(Request $request) { [...] // perform the request if (false === $returnTransfer = curl_exec($curl)) { throw new CommunicationException( 'cURL Error: '.curl_error($curl), curl_errno($curl) ); } [...] $response = new RawResponse( substr($returnTransfer, $headerSize), curl_getinfo($curl, CURLINFO_HTTP_CODE), $headers ); curl_close($curl); return $response; } }
  • 13. namespace ACMEPaymentBundleTestsStub; use JMSPaymentPaypalBundleClientClient; class PaypalClientStub extends Client { public function request(Request $request) { $response = new RawResponse( "TOKEN=BlaBlaBlaBla", 200, array( 'Date' => "Fri, 07 Sep 2012 15:21:00 GMT", 'Server' => "Apache", ) ); return $response; } }
  • 14. namespace ACMEPaymentBundleTestsStub; use JMSPaymentPaypalBundleClientClient; class PaypalClientStub extends Client { public function request(Request $request) { $response = new RawResponse( "TOKEN=BlaBlaBlaBla", 200, array( 'Date' => "Fri, 07 Sep 2012 15:21:00 GMT", 'Server' => "Apache", ) ); return $response; } }
  • 15. services.xml <parameter key="payment.paypal.client.class"> JMSPaymentPaypalBundleClientClient </parameter> config_test.yml parameters: payment.paypal.client.class: ACMEPaymentBundleTestsStubPaypalClientStub
  • 16.
  • 17.
  • 18. namespace JMSPaymentPaypalBundleClient; class Client { [...] public function getAuthenticateExpressCheckoutTokenUrl($token) { $host = $this->isDebug ? 'www.sandbox.paypal.com':'www.paypal.com'; return $host; } }
  • 19. namespace ACMEPaymentBundleTestsStub; use JMSPaymentPaypalBundleClientClient; class PaypalClientStub extends Client { public function getAuthenticateExpressCheckoutTokenUrl($token) { return '/payment/paypalFakeController'; } }
  • 20.
  • 21. namespace ACMEPaymentBundleTestsStub; use JMSPaymentPaypalBundleClientClient; class PaypalClientStub extends Client { public function request(Request $request) { if ($request->request->get('METHOD') == 'SetExpressCheckout') { $response = new RawResponse( "TOKEN=BlaBlaBla", ); } elseif ($request->request->get('METHOD') == 'GetExpressCheckoutDetails') { $response = new RawResponse( "CHECKOUTSTATUS=PaymentCompleted&ACK=Success", ); } elseif ($request->request->get('METHOD') == 'DoExpressCheckoutPayment'){ $response = new RawResponse( "PAYMENTINFO_0_PAYMENTSTATUS=Completed", ); } return $response; } }
  • 22. namespace ACMEPaymentBundleTestsStub; use JMSPaymentPaypalBundleClientClient; class PaypalClientStub extends Client { public function request(Request $request) { if ($request->request->get('METHOD') == 'SetExpressCheckout') { $response = new RawResponse( "TOKEN=BlaBlaBla", ); } elseif ($request->request->get('METHOD') == 'GetExpressCheckoutDetails') { $response = new RawResponse( "CHECKOUTSTATUS=PaymentCompleted&ACK=Success", ); } elseif ($request->request->get('METHOD') == 'DoExpressCheckoutPayment'){ $response = new RawResponse( "PAYMENTINFO_0_PAYMENTSTATUS=Completed", ); } return $response; } }
  • 23. namespace ACMEPaymentBundleTestsStub; use JMSPaymentPaypalBundleClientClient; class PaypalClientStub extends Client { public function request(Request $request) { if ($request->request->get('METHOD') == 'SetExpressCheckout') { $response = new RawResponse( "TOKEN=BlaBlaBla", ); } elseif ($request->request->get('METHOD') == 'GetExpressCheckoutDetails') { $response = new RawResponse( "CHECKOUTSTATUS=PaymentCompleted&ACK=Success", ); } elseif ($request->request->get('METHOD') == 'DoExpressCheckoutPayment'){ $response = new RawResponse( "PAYMENTINFO_0_PAYMENTSTATUS=Completed", ); } return $response; } }
  • 25. Control on the request namespace ACMEPaymentBundleTestsStub; use JMSPaymentPaypalBundleClientClient; class PaypalClientStub extends Client { public function request(Request $request) { if ($request != "OK STUFF") { throw new Exception ("Wrong Request for Paypal call"); } [...] return $response; } }
  • 27. What is “outside”? ● External API ● OS services (time)
  • 28. What is “outside”? ● External API ● OS services (time) ● Systems that don't exist yet
  • 29. What is “outside”? ● External API ● OS services (time) ● Systems that don't exist yet ● Systems that other people is working on
  • 30. What is “outside”? ● External API ● OS services (time) ● Systems that don't exist yet ● Systems that other people is working on ● Monsters from the inside(legacy code)
  • 31. The date/time case ● A user can see the next three appointments
  • 32. The date/time case ● A user can see the next three appointments ● A user is shown an alert in home page if she has an appointment in the next 6 hours
  • 33. The date/time case ● A user can see the next three appointments ● A user is shown an alert in home page if she has an appointment in the next 6 hours ● A user can take an appointment for the next day, but if it is Friday the next eligible day will be Monday
  • 34. namespace ACMECoreBundleService; class Time { public static function getNow() { return new DateTime(); } }
  • 35. namespace AcmeCoreBundleTestService; class Time { public static $referenceTime = '2012-05-01 12:00:00'; public static $time = null; public static function getNow() { if (is_null(self::$time)) { return new DateTime(self::$referenceTime); } else { return new DateTime(self::$time); } } }
  • 36. namespace AcmeCoreBundleTestService; class Time { public static $referenceTime = '2012-05-01 12:00:00'; public static $time = null; public static function getNow() { if (is_null(self::$time)) { return new DateTime(self::$referenceTime); } else { return new DateTime(self::$time); } } }
  • 37. Inside the fixtures Use AcmeCoreBundleTestServiceTime; public function load(ObjectManager $manager) { $appointmentToday = new Appointment(); $appointmentToday->setDateTime(new DateTime(Time::$referenceTime)); [...] }
  • 38. Inside the test Use AcmeCoreBundleTestServiceTime; public function test_customerHome() { AcmeCoreBundleTestServiceTime::$time = "2012-06-01"; [...] }
  • 39. Different config states $client = self::createClient(array('environment' => 'test_alternative'));
  • 40. Thank You @euxpom nerd2business.net