SlideShare a Scribd company logo
1 of 46
Download to read offline
Testing untestable Code
   Stephan Hochdörfer, bitExpert AG




 "Quality is a function of thought and reflection -
 precise thought and reflection. That’s the magic."
                 Michael Feathers
About me
 Founder of bitExpert AG, Mannheim

 Field of duty
         
           Department Manager of Research Labs
         
           Head of Development for bitFramework

 Focusing on
        
          PHP
        
          Generative Programming


    Contact me
          
            @shochdoerfer
          
            S.Hochdoerfer@bitExpert.de
Agenda
1.   Theory

2.   How to test untestable PHP Code

3.   Generate testable code

4.   Conclusion
Theory




         "There is no secret to writing tests, there
          are only secrets to write testable code!"
                         Miško Hevery
Theory



 What is „untestable code“?
Theory



 What is „untestable code“?

  Global variables
          
            Singleton
          
            Registry
          
            Globale state
  static method calls
  Control flow in a constructor
  Tight coupling
          
            Dependencies to concrete implementations
          
            to many dependencies to other classes
          
            Dependencies without control
Theory




          "...our test strategy requires us to have more control or
         visibility of the internal behavior of the system under test."
               Gerard Meszaros, xUnit Test Patterns: Refactoring Test Code
Theory




                               Required
                                class
                    Class to
         Unittest
                      Test
                               Required
                                class
Theory




                                          Database

                               Required
                                class
                                           External
                    Class to
         Unittest                          resource
                      test
                               Required
                                class




                    Required   Required
                                           Webservice
                     class      class
Theory




                                          Database

                               Required
                                class
                                           External
                    Class to
         Unittest                          resource
                      test
                               Required
                                class




                    Required   Required
                                           Webservice
                     class      class
Theory



 How to achieve „testable“ code?
Theory



 How to achieve „testable“ code?




                Refactoring
Theory




         "Before you start refactoring, check that you
                  have a solid suite of tests."
                     Martin Fowler, Refactoring
Agenda
1.   Theory

2.   Testing untestable PHP Code

3.   Generate testable code

4.   Conclusion
Agenda
1.   Theory

2.   Testing untestable PHP Code
     – Hardcoded Dependencies
     – Procedural code
     – Overwrite internal PHP functions

3.   Generate testable code

4.   Conclusion
Testing „untestable“ PHP Code



 Assumption




          Do not change existing code!
Testing „untestable“ PHP Code | __autoload




<?php
class Car {
    private $Engine;

     public function __construct($sEngine) {
         $this->Engine = Engine::getByType($sEngine);
     }

}
Testing „untestable“ PHP Code | __autoload




<?php
class Car {
    private $Engine;

     public function __construct($sEngine) {
         $this->Engine = Engine::getByType($sEngine);
     }

}




How to inject a dependency?
 Use __autoload
Testing „untestable“ PHP Code | __autoload




<?php
function run_autoload($psClass) {
    $sFileToInclude = strtolower($psClass).'.php';
    if(strtolower($psClass) == 'engine') {
         $sFileToInclude = '/custom/mocks/'.$sFileToInclude;
    }
    include($sFileToInclude);
}


// Testcase
spl_autoload_register('run_autoload');
$oCar = new Car('Diesel');
echo $oCar->run();
Testing „untestable“ PHP Code | include_path




<?php
include('Engine.php');

class Car {
    private $Engine;

     public function __construct($sEngine) {
         $this->Engine = Engine::getByType($sEngine);
     }
}
Testing „untestable“ PHP Code | include_path




<?php
include('Engine.php');

class Car {
    private $Engine;

     public function __construct($sEngine) {
         $this->Engine = Engine::getByType($sEngine);
     }
}




How to inject a dependency?
 Manipulate include_path setting
Testing „untestable“ PHP Code | include_path




<?php
ini_set('include_path',
    '/custom/mocks/'.PATH_SEPARATOR.
    ini_get('include_path'));

// Testcase
include('car.php');

$oCar = new Car('Diesel');
echo $oCar->run();
Testing „untestable“ PHP Code | include_path alternative

<?php
class CustomFileStreamWrapper {
  private $_handler;

    function stream_open($path, $mode, $options, &$opened_path) {
      stream_wrapper_restore('file');
       // @TODO: modify $path before fopen
      $this->_handler = fopen($path, $mode);
      stream_wrapper_unregister('file');
      stream_wrapper_register('file', 'CustomFileStreamWrapper');
      return true;
    }

    function stream_read($count) {}

    function stream_write($data) {}

    function stream_tell() {}

    function stream_eof() {}

    function stream_seek($offset, $whence) {}
}

stream_wrapper_unregister('file');
stream_wrapper_register('file', 'CustomFileStreamWrapper');



Source: Alex Netkachov, http://www.alexatnet.com/node/203
Testing „untestable“ PHP Code | Namespaces




<?php
class Car {
    private $Engine;

     public function __construct($sEngine) {
         $this->Engine = CarEngine::getByType($sEngine);
     }
}
Testing „untestable“ PHP Code | Namespaces




<?php
class Car {
    private $Engine;

     public function __construct($sEngine) {
         $this->Engine = CarEngine::getByType($sEngine);
     }
}




How to inject a dependency?
 Use __autoload or manipulate the include_path
Testing „untestable“ PHP Code | vfsStream




<?php
class Car {
    private $Engine;

     public function __construct($sEngine, $CacheDir) {
         $this->Engine = CarEngine::getByType($sEngine);
         mkdir($CacheDir.'/cache/', 0700, true);
     }
}
Testing „untestable“ PHP Code | vfsStream




<?php
class Car {
    private $Engine;

     public function __construct($sEngine, $CacheDir) {
         $this->Engine = CarEngine::getByType($sEngine);
         mkdir($CacheDir.'/cache/', 0700, true);
     }
}




How mock a filesystem?
 Use vfsStream - http://code.google.com/p/bovigo/
Testing „untestable“ PHP Code | vfsStream




<?php

// setup vfsStream
vfsStreamWrapper::register();
vfsStreamWrapper::setRoot(new vfsStreamDirectory('app'));

$oCar = new Car('Diesel', vfsStream::url('app'));

echo vfsStreamWrapper::getRoot()->hasChild('cache');
Agenda
1.   Theory

2.   Testing untestable PHP Code
     – Hardcoded Dependencies
     – Procedural code
     – Overwrite internal PHP functions

3.   Generate testable code

4.   Conclusion
Testing „untestable“ PHP Code




       „I have no idea how to unit-test procedural code. Unit-testing
          assumes that I can instantiate a piece of my application in
                                  isolation.“
                                 Miško Hevery
Testing „untestable“ PHP Code | Test functions




<?php
function startsWith($sString, $psPre) {
    return $psPre == substr($sString, 0, strlen($psPre));
}

function contains($sString, $sSearch) {
    return false !== strpos($sString, $sSearch);
}
Testing „untestable“ PHP Code | Test functions




<?php
function startsWith($sString, $psPre) {
    return $psPre == substr($sString, 0, strlen($psPre));
}

function contains($sString, $sSearch) {
    return false !== strpos($sString, $sSearch);
}




How to test
 PHPUnit can call methods
 PHPUnit can save/restore globale state
Agenda
1.   Theory

2.   Testing untestable PHP Code
     – Hardcoded Dependencies
     – Procedural code
     – Overwrite internal PHP functions

3.   Generate testable code

4.   Conclusion
Testing „untestable“ PHP Code | overwrite internal functions




<?php
function buyCar(Car $oCar) {
    global $oDB;

     mysql_query("INSERT INTO...", $oDB);

     mail('order@domain.org', 'New sale', '....');
}
Testing „untestable“ PHP Code | overwrite internal functions




<?php
function buyCar(Car $oCar) {
    global $oDB;

     mysql_query("INSERT INTO...", $oDB);

     mail('order@domain.org', 'New sale', '....');
}




How to test
 Do not load mysql extension. Provide own implementation
 Unfortunatly mail() is part of the PHP core
Testing „untestable“ PHP Code | overwrite internal functions




<?php
function buyCar(Car $oCar) {
    global $oDB;

     mysql_query("INSERT INTO...", $oDB);

     mail('order@domain.org', 'New sale', '....');
}




How to test
 Use classkit extension to mock internal functions
Testing „untestable“ PHP Code | overwrite internal functions




<?php

ini_set('runkit.internal_override', '1');

runkit_function_redefine('mail','','return true;');

?>
Agenda
1.   Theory

2.   Testing untestable PHP Code

3.   Generate testable code

4.   Conclusion
Generate testable code



 Generative Programming

                             Configuration




                                                         1 ... n
            Implementation
                                             Generator    Product
             components




                               Generator
                               application
Generate testable code



 Generative Programming

                             Configuration


                                                         Application



            Implementation
                                             Generator
             components



                                                         Testcases
                               Generator
                               application
Generate testable code



 Course of action
 Extraction
  „Mask“ parts of the code


 Customizing
  Change content of global vars
  Pre/Postfixes for own functions, methods, classes


 Recombine
  Re-order parts of the code
Generate testable code




FileFrm FILEIndex_php5 {
  private String Prefix   = "test_";
  private String MailSlot = "mail('order@domain.org', 'New sale', '....');";

   public FILEIndex_php5() {
     setFilename("index.php5");
     setRelativePath("/");
   }

  private void assign() {
BEGINCONTENT()
<?php
function buyCar(Car $oCar) {
global $oDB;

<!{Prefix}!>mysql_query(„INSERT INTO...“, $oDB);
<!{MailSlot}!>
}

?>
ENDCONTENT()
  }
}
Generate testable code




1. Example
Prefix: test_
<?php
function buyCar(Car $oCar) {
  global $oDB;

    test_mysql_query("INSERT INTO...", $oDB);
}
Generate testable code




1. Example
Prefix: test_
<?php
function buyCar(Car $oCar) {
  global $oDB;

     test_mysql_query("INSERT INTO...", $oDB);
}


2. Example
MailSlot: mail('order@domain.org', 'New sale', '....');
<?php
function buyCar(Car $oCar) {
  global $oDB;

     mysql_query("INSERT INTO...", $oDB);
     mail('order@domain.org', 'New sale', '....');
}

?>
Conclustion



 Conclusion

  Change mindset to write testable code
        
          Dependency Injection

  Look for other options to raise the bar
         
           Work around limitations of PHP
         
           PHP is flexible, use it that way
Testing untestable Code - PFCongres 2010

More Related Content

What's hot

Real World Dependency Injection - phpugffm13
Real World Dependency Injection - phpugffm13Real World Dependency Injection - phpugffm13
Real World Dependency Injection - phpugffm13Stephan Hochdörfer
 
Real World Dependency Injection - IPC11 Spring Edition
Real World Dependency Injection - IPC11 Spring EditionReal World Dependency Injection - IPC11 Spring Edition
Real World Dependency Injection - IPC11 Spring EditionStephan Hochdörfer
 
Offline Strategies for HTML5 Web Applications - ipc13
Offline Strategies for HTML5 Web Applications - ipc13Offline Strategies for HTML5 Web Applications - ipc13
Offline Strategies for HTML5 Web Applications - ipc13Stephan Hochdörfer
 
Your Business. Your Language. Your Code - dpc13
Your Business. Your Language. Your Code - dpc13Your Business. Your Language. Your Code - dpc13
Your Business. Your Language. Your Code - dpc13Stephan Hochdörfer
 
Testing untestable code - phpday
Testing untestable code - phpdayTesting untestable code - phpday
Testing untestable code - phpdayStephan Hochdörfer
 
Offline strategies for HTML5 web applications - IPC12
Offline strategies for HTML5 web applications - IPC12Offline strategies for HTML5 web applications - IPC12
Offline strategies for HTML5 web applications - IPC12Stephan Hochdörfer
 
GDG Addis - An Introduction to Django and App Engine
GDG Addis - An Introduction to Django and App EngineGDG Addis - An Introduction to Django and App Engine
GDG Addis - An Introduction to Django and App EngineYared Ayalew
 
Real World Dependency Injection - phpday
Real World Dependency Injection - phpdayReal World Dependency Injection - phpday
Real World Dependency Injection - phpdayStephan Hochdörfer
 
Invoke dynamite in Java EE with invoke dynamic
Invoke dynamite in Java EE with invoke dynamicInvoke dynamite in Java EE with invoke dynamic
Invoke dynamite in Java EE with invoke dynamicAntoine Sabot-Durand
 
Extracting Plugins And Gems From Rails Apps
Extracting Plugins And Gems From Rails AppsExtracting Plugins And Gems From Rails Apps
Extracting Plugins And Gems From Rails AppsJosh Nichols
 
Easy tests with Selenide and Easyb
Easy tests with Selenide and EasybEasy tests with Selenide and Easyb
Easy tests with Selenide and EasybIakiv Kramarenko
 
Real World Dependency Injection SE - phpugrhh
Real World Dependency Injection SE - phpugrhhReal World Dependency Injection SE - phpugrhh
Real World Dependency Injection SE - phpugrhhStephan Hochdörfer
 
Workshop quality assurance for php projects - phpdublin
Workshop quality assurance for php projects - phpdublinWorkshop quality assurance for php projects - phpdublin
Workshop quality assurance for php projects - phpdublinMichelangelo van Dam
 
Node.js vs Play Framework (with Japanese subtitles)
Node.js vs Play Framework (with Japanese subtitles)Node.js vs Play Framework (with Japanese subtitles)
Node.js vs Play Framework (with Japanese subtitles)Yevgeniy Brikman
 
JavaScript Library Overview
JavaScript Library OverviewJavaScript Library Overview
JavaScript Library Overviewjeresig
 
Metrics-Driven Engineering
Metrics-Driven EngineeringMetrics-Driven Engineering
Metrics-Driven EngineeringMike Brittain
 
vJUG - The JavaFX Ecosystem
vJUG - The JavaFX EcosystemvJUG - The JavaFX Ecosystem
vJUG - The JavaFX EcosystemAndres Almiray
 

What's hot (20)

Real World Dependency Injection - phpugffm13
Real World Dependency Injection - phpugffm13Real World Dependency Injection - phpugffm13
Real World Dependency Injection - phpugffm13
 
Real World Dependency Injection - IPC11 Spring Edition
Real World Dependency Injection - IPC11 Spring EditionReal World Dependency Injection - IPC11 Spring Edition
Real World Dependency Injection - IPC11 Spring Edition
 
Thinking Beyond ORM in JPA
Thinking Beyond ORM in JPAThinking Beyond ORM in JPA
Thinking Beyond ORM in JPA
 
Offline Strategies for HTML5 Web Applications - ipc13
Offline Strategies for HTML5 Web Applications - ipc13Offline Strategies for HTML5 Web Applications - ipc13
Offline Strategies for HTML5 Web Applications - ipc13
 
Your Business. Your Language. Your Code - dpc13
Your Business. Your Language. Your Code - dpc13Your Business. Your Language. Your Code - dpc13
Your Business. Your Language. Your Code - dpc13
 
Testing untestable code - phpday
Testing untestable code - phpdayTesting untestable code - phpday
Testing untestable code - phpday
 
Offline strategies for HTML5 web applications - IPC12
Offline strategies for HTML5 web applications - IPC12Offline strategies for HTML5 web applications - IPC12
Offline strategies for HTML5 web applications - IPC12
 
GDG Addis - An Introduction to Django and App Engine
GDG Addis - An Introduction to Django and App EngineGDG Addis - An Introduction to Django and App Engine
GDG Addis - An Introduction to Django and App Engine
 
Real World Dependency Injection - phpday
Real World Dependency Injection - phpdayReal World Dependency Injection - phpday
Real World Dependency Injection - phpday
 
Invoke dynamite in Java EE with invoke dynamic
Invoke dynamite in Java EE with invoke dynamicInvoke dynamite in Java EE with invoke dynamic
Invoke dynamite in Java EE with invoke dynamic
 
Extracting Plugins And Gems From Rails Apps
Extracting Plugins And Gems From Rails AppsExtracting Plugins And Gems From Rails Apps
Extracting Plugins And Gems From Rails Apps
 
Easy tests with Selenide and Easyb
Easy tests with Selenide and EasybEasy tests with Selenide and Easyb
Easy tests with Selenide and Easyb
 
Real World Dependency Injection SE - phpugrhh
Real World Dependency Injection SE - phpugrhhReal World Dependency Injection SE - phpugrhh
Real World Dependency Injection SE - phpugrhh
 
Javascript Best Practices
Javascript Best PracticesJavascript Best Practices
Javascript Best Practices
 
Workshop quality assurance for php projects - phpdublin
Workshop quality assurance for php projects - phpdublinWorkshop quality assurance for php projects - phpdublin
Workshop quality assurance for php projects - phpdublin
 
Node.js vs Play Framework (with Japanese subtitles)
Node.js vs Play Framework (with Japanese subtitles)Node.js vs Play Framework (with Japanese subtitles)
Node.js vs Play Framework (with Japanese subtitles)
 
Spring AOP
Spring AOPSpring AOP
Spring AOP
 
JavaScript Library Overview
JavaScript Library OverviewJavaScript Library Overview
JavaScript Library Overview
 
Metrics-Driven Engineering
Metrics-Driven EngineeringMetrics-Driven Engineering
Metrics-Driven Engineering
 
vJUG - The JavaFX Ecosystem
vJUG - The JavaFX EcosystemvJUG - The JavaFX Ecosystem
vJUG - The JavaFX Ecosystem
 

Similar to Testing untestable Code - PFCongres 2010

Testing untestable code - PHPBNL11
Testing untestable code - PHPBNL11Testing untestable code - PHPBNL11
Testing untestable code - PHPBNL11Stephan Hochdörfer
 
Testing untestable code - phpconpl11
Testing untestable code - phpconpl11Testing untestable code - phpconpl11
Testing untestable code - phpconpl11Stephan Hochdörfer
 
Testing untestable code - STPCon11
Testing untestable code - STPCon11Testing untestable code - STPCon11
Testing untestable code - STPCon11Stephan Hochdörfer
 
Leveling Up With Unit Testing - php[tek] 2023
Leveling Up With Unit Testing - php[tek] 2023Leveling Up With Unit Testing - php[tek] 2023
Leveling Up With Unit Testing - php[tek] 2023Mark Niebergall
 
Leveling Up With Unit Testing - LonghornPHP 2022
Leveling Up With Unit Testing - LonghornPHP 2022Leveling Up With Unit Testing - LonghornPHP 2022
Leveling Up With Unit Testing - LonghornPHP 2022Mark Niebergall
 
Developer testing 101: Become a Testing Fanatic
Developer testing 101: Become a Testing FanaticDeveloper testing 101: Become a Testing Fanatic
Developer testing 101: Become a Testing FanaticLB Denker
 
Testing untestable code - oscon 2012
Testing untestable code - oscon 2012Testing untestable code - oscon 2012
Testing untestable code - oscon 2012Stephan Hochdörfer
 
Testing untestable code - ConFoo13
Testing untestable code - ConFoo13Testing untestable code - ConFoo13
Testing untestable code - ConFoo13Stephan Hochdörfer
 
Unit Testing from Setup to Deployment
Unit Testing from Setup to DeploymentUnit Testing from Setup to Deployment
Unit Testing from Setup to DeploymentMark Niebergall
 
Test Driven Development with PHPUnit
Test Driven Development with PHPUnitTest Driven Development with PHPUnit
Test Driven Development with PHPUnitMindfire Solutions
 
Better Testing With PHP Unit
Better Testing With PHP UnitBetter Testing With PHP Unit
Better Testing With PHP Unitsitecrafting
 
Working Effectively With Legacy Perl Code
Working Effectively With Legacy Perl CodeWorking Effectively With Legacy Perl Code
Working Effectively With Legacy Perl Codeerikmsp
 
Test in action – week 1
Test in action – week 1Test in action – week 1
Test in action – week 1Yi-Huan Chan
 
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 tek12Michelangelo van Dam
 
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 2012Michelangelo van Dam
 
2010 07-28-testing-zf-apps
2010 07-28-testing-zf-apps2010 07-28-testing-zf-apps
2010 07-28-testing-zf-appsVenkata Ramana
 
New Ideas for Old Code - Greach
New Ideas for Old Code - GreachNew Ideas for Old Code - Greach
New Ideas for Old Code - GreachHamletDRC
 
Selenium-Webdriver With PHPUnit Automation test for Joomla CMS!
Selenium-Webdriver With PHPUnit Automation test for Joomla CMS!Selenium-Webdriver With PHPUnit Automation test for Joomla CMS!
Selenium-Webdriver With PHPUnit Automation test for Joomla CMS!Puneet Kala
 

Similar to Testing untestable Code - PFCongres 2010 (20)

Testing untestable code - PHPBNL11
Testing untestable code - PHPBNL11Testing untestable code - PHPBNL11
Testing untestable code - PHPBNL11
 
Testing untestable code - phpconpl11
Testing untestable code - phpconpl11Testing untestable code - phpconpl11
Testing untestable code - phpconpl11
 
Testing untestable code - STPCon11
Testing untestable code - STPCon11Testing untestable code - STPCon11
Testing untestable code - STPCon11
 
Leveling Up With Unit Testing - php[tek] 2023
Leveling Up With Unit Testing - php[tek] 2023Leveling Up With Unit Testing - php[tek] 2023
Leveling Up With Unit Testing - php[tek] 2023
 
Leveling Up With Unit Testing - LonghornPHP 2022
Leveling Up With Unit Testing - LonghornPHP 2022Leveling Up With Unit Testing - LonghornPHP 2022
Leveling Up With Unit Testing - LonghornPHP 2022
 
Developer testing 101: Become a Testing Fanatic
Developer testing 101: Become a Testing FanaticDeveloper testing 101: Become a Testing Fanatic
Developer testing 101: Become a Testing Fanatic
 
Testing untestable code - IPC12
Testing untestable code - IPC12Testing untestable code - IPC12
Testing untestable code - IPC12
 
Testing untestable code - oscon 2012
Testing untestable code - oscon 2012Testing untestable code - oscon 2012
Testing untestable code - oscon 2012
 
Testing untestable code - ConFoo13
Testing untestable code - ConFoo13Testing untestable code - ConFoo13
Testing untestable code - ConFoo13
 
Test
TestTest
Test
 
Unit Testing from Setup to Deployment
Unit Testing from Setup to DeploymentUnit Testing from Setup to Deployment
Unit Testing from Setup to Deployment
 
Test Driven Development with PHPUnit
Test Driven Development with PHPUnitTest Driven Development with PHPUnit
Test Driven Development with PHPUnit
 
Better Testing With PHP Unit
Better Testing With PHP UnitBetter Testing With PHP Unit
Better Testing With PHP Unit
 
Working Effectively With Legacy Perl Code
Working Effectively With Legacy Perl CodeWorking Effectively With Legacy Perl Code
Working Effectively With Legacy Perl Code
 
Test in action – week 1
Test in action – week 1Test in action – week 1
Test in action – week 1
 
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
 
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
 
2010 07-28-testing-zf-apps
2010 07-28-testing-zf-apps2010 07-28-testing-zf-apps
2010 07-28-testing-zf-apps
 
New Ideas for Old Code - Greach
New Ideas for Old Code - GreachNew Ideas for Old Code - Greach
New Ideas for Old Code - Greach
 
Selenium-Webdriver With PHPUnit Automation test for Joomla CMS!
Selenium-Webdriver With PHPUnit Automation test for Joomla CMS!Selenium-Webdriver With PHPUnit Automation test for Joomla CMS!
Selenium-Webdriver With PHPUnit Automation test for Joomla CMS!
 

More from Stephan Hochdörfer

Offline. Na und? Strategien für offlinefähige Applikationen in HTML5 - Herbst...
Offline. Na und? Strategien für offlinefähige Applikationen in HTML5 - Herbst...Offline. Na und? Strategien für offlinefähige Applikationen in HTML5 - Herbst...
Offline. Na und? Strategien für offlinefähige Applikationen in HTML5 - Herbst...Stephan Hochdörfer
 
Offline Strategien für HTML5 Web Applikationen - dwx13
Offline Strategien für HTML5 Web Applikationen - dwx13 Offline Strategien für HTML5 Web Applikationen - dwx13
Offline Strategien für HTML5 Web Applikationen - dwx13 Stephan Hochdörfer
 
Offline-Strategien für HTML5 Web Applikationen - wmka
Offline-Strategien für HTML5 Web Applikationen - wmkaOffline-Strategien für HTML5 Web Applikationen - wmka
Offline-Strategien für HTML5 Web Applikationen - wmkaStephan Hochdörfer
 
Offline-Strategien für HTML5 Web Applikationen - bedcon13
Offline-Strategien für HTML5 Web Applikationen - bedcon13Offline-Strategien für HTML5 Web Applikationen - bedcon13
Offline-Strategien für HTML5 Web Applikationen - bedcon13Stephan Hochdörfer
 
Offline strategies for HTML5 web applications - ConFoo13
Offline strategies for HTML5 web applications - ConFoo13Offline strategies for HTML5 web applications - ConFoo13
Offline strategies for HTML5 web applications - ConFoo13Stephan Hochdörfer
 
Offline-Strategien für HTML5Web Applikationen - WMMRN12
Offline-Strategien für HTML5Web Applikationen - WMMRN12Offline-Strategien für HTML5Web Applikationen - WMMRN12
Offline-Strategien für HTML5Web Applikationen - WMMRN12Stephan Hochdörfer
 
Große Systeme, lose Kopplung, Spaß bei der Arbeit! - WDC12
Große Systeme, lose Kopplung, Spaß bei der Arbeit! - WDC12Große Systeme, lose Kopplung, Spaß bei der Arbeit! - WDC12
Große Systeme, lose Kopplung, Spaß bei der Arbeit! - WDC12Stephan Hochdörfer
 
Offline strategies for HTML5 web applications - pfCongres2012
Offline strategies for HTML5 web applications - pfCongres2012Offline strategies for HTML5 web applications - pfCongres2012
Offline strategies for HTML5 web applications - pfCongres2012Stephan Hochdörfer
 
Wie Software-Generatoren die Welt verändern können - Herbstcampus12
Wie Software-Generatoren die Welt verändern können - Herbstcampus12Wie Software-Generatoren die Welt verändern können - Herbstcampus12
Wie Software-Generatoren die Welt verändern können - Herbstcampus12Stephan Hochdörfer
 
Testing untestable code - Herbstcampus12
Testing untestable code - Herbstcampus12Testing untestable code - Herbstcampus12
Testing untestable code - Herbstcampus12Stephan Hochdörfer
 
Introducing a Software Generator Framework - JAZOON12
Introducing a Software Generator Framework - JAZOON12Introducing a Software Generator Framework - JAZOON12
Introducing a Software Generator Framework - JAZOON12Stephan Hochdörfer
 
Managing variability in software applications - scandev12
Managing variability in software applications - scandev12Managing variability in software applications - scandev12
Managing variability in software applications - scandev12Stephan Hochdörfer
 
The state of DI in PHP - phpbnl12
The state of DI in PHP - phpbnl12The state of DI in PHP - phpbnl12
The state of DI in PHP - phpbnl12Stephan Hochdörfer
 

More from Stephan Hochdörfer (16)

Offline. Na und? Strategien für offlinefähige Applikationen in HTML5 - Herbst...
Offline. Na und? Strategien für offlinefähige Applikationen in HTML5 - Herbst...Offline. Na und? Strategien für offlinefähige Applikationen in HTML5 - Herbst...
Offline. Na und? Strategien für offlinefähige Applikationen in HTML5 - Herbst...
 
Offline Strategien für HTML5 Web Applikationen - dwx13
Offline Strategien für HTML5 Web Applikationen - dwx13 Offline Strategien für HTML5 Web Applikationen - dwx13
Offline Strategien für HTML5 Web Applikationen - dwx13
 
Offline-Strategien für HTML5 Web Applikationen - wmka
Offline-Strategien für HTML5 Web Applikationen - wmkaOffline-Strategien für HTML5 Web Applikationen - wmka
Offline-Strategien für HTML5 Web Applikationen - wmka
 
Offline-Strategien für HTML5 Web Applikationen - bedcon13
Offline-Strategien für HTML5 Web Applikationen - bedcon13Offline-Strategien für HTML5 Web Applikationen - bedcon13
Offline-Strategien für HTML5 Web Applikationen - bedcon13
 
A Phing fairy tale - ConFoo13
A Phing fairy tale - ConFoo13A Phing fairy tale - ConFoo13
A Phing fairy tale - ConFoo13
 
Offline strategies for HTML5 web applications - ConFoo13
Offline strategies for HTML5 web applications - ConFoo13Offline strategies for HTML5 web applications - ConFoo13
Offline strategies for HTML5 web applications - ConFoo13
 
Offline-Strategien für HTML5Web Applikationen - WMMRN12
Offline-Strategien für HTML5Web Applikationen - WMMRN12Offline-Strategien für HTML5Web Applikationen - WMMRN12
Offline-Strategien für HTML5Web Applikationen - WMMRN12
 
Große Systeme, lose Kopplung, Spaß bei der Arbeit! - WDC12
Große Systeme, lose Kopplung, Spaß bei der Arbeit! - WDC12Große Systeme, lose Kopplung, Spaß bei der Arbeit! - WDC12
Große Systeme, lose Kopplung, Spaß bei der Arbeit! - WDC12
 
Offline strategies for HTML5 web applications - pfCongres2012
Offline strategies for HTML5 web applications - pfCongres2012Offline strategies for HTML5 web applications - pfCongres2012
Offline strategies for HTML5 web applications - pfCongres2012
 
Wie Software-Generatoren die Welt verändern können - Herbstcampus12
Wie Software-Generatoren die Welt verändern können - Herbstcampus12Wie Software-Generatoren die Welt verändern können - Herbstcampus12
Wie Software-Generatoren die Welt verändern können - Herbstcampus12
 
Testing untestable code - Herbstcampus12
Testing untestable code - Herbstcampus12Testing untestable code - Herbstcampus12
Testing untestable code - Herbstcampus12
 
Introducing a Software Generator Framework - JAZOON12
Introducing a Software Generator Framework - JAZOON12Introducing a Software Generator Framework - JAZOON12
Introducing a Software Generator Framework - JAZOON12
 
The state of DI - DPC12
The state of DI - DPC12The state of DI - DPC12
The state of DI - DPC12
 
Separation of concerns - DPC12
Separation of concerns - DPC12Separation of concerns - DPC12
Separation of concerns - DPC12
 
Managing variability in software applications - scandev12
Managing variability in software applications - scandev12Managing variability in software applications - scandev12
Managing variability in software applications - scandev12
 
The state of DI in PHP - phpbnl12
The state of DI in PHP - phpbnl12The state of DI in PHP - phpbnl12
The state of DI in PHP - phpbnl12
 

Recently uploaded

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 DiscoveryTrustArc
 
Artificial Intelligence Chap.5 : Uncertainty
Artificial Intelligence Chap.5 : UncertaintyArtificial Intelligence Chap.5 : Uncertainty
Artificial Intelligence Chap.5 : UncertaintyKhushali Kathiriya
 
Cyberprint. Dark Pink Apt Group [EN].pdf
Cyberprint. Dark Pink Apt Group [EN].pdfCyberprint. Dark Pink Apt Group [EN].pdf
Cyberprint. Dark Pink Apt Group [EN].pdfOverkill Security
 
Ransomware_Q4_2023. The report. [EN].pdf
Ransomware_Q4_2023. The report. [EN].pdfRansomware_Q4_2023. The report. [EN].pdf
Ransomware_Q4_2023. The report. [EN].pdfOverkill Security
 
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...apidays
 
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FMESafe Software
 
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FMESafe Software
 
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...DianaGray10
 
EMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWER
EMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWEREMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWER
EMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWERMadyBayot
 
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...Zilliz
 
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, ...apidays
 
Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...
Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...
Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...apidays
 
Spring Boot vs Quarkus the ultimate battle - DevoxxUK
Spring Boot vs Quarkus the ultimate battle - DevoxxUKSpring Boot vs Quarkus the ultimate battle - DevoxxUK
Spring Boot vs Quarkus the ultimate battle - DevoxxUKJago de Vreede
 
Polkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin WoodPolkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin WoodJuan lago vázquez
 
Finding Java's Hidden Performance Traps @ DevoxxUK 2024
Finding Java's Hidden Performance Traps @ DevoxxUK 2024Finding Java's Hidden Performance Traps @ DevoxxUK 2024
Finding Java's Hidden Performance Traps @ DevoxxUK 2024Victor Rentea
 
Boost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfBoost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfsudhanshuwaghmare1
 
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, ...Angeliki Cooney
 
Exploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone ProcessorsExploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone Processorsdebabhi2
 
FWD Group - Insurer Innovation Award 2024
FWD Group - Insurer Innovation Award 2024FWD Group - Insurer Innovation Award 2024
FWD Group - Insurer Innovation Award 2024The Digital Insurer
 
DBX First Quarter 2024 Investor Presentation
DBX First Quarter 2024 Investor PresentationDBX First Quarter 2024 Investor Presentation
DBX First Quarter 2024 Investor PresentationDropbox
 

Recently uploaded (20)

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
 
Artificial Intelligence Chap.5 : Uncertainty
Artificial Intelligence Chap.5 : UncertaintyArtificial Intelligence Chap.5 : Uncertainty
Artificial Intelligence Chap.5 : Uncertainty
 
Cyberprint. Dark Pink Apt Group [EN].pdf
Cyberprint. Dark Pink Apt Group [EN].pdfCyberprint. Dark Pink Apt Group [EN].pdf
Cyberprint. Dark Pink Apt Group [EN].pdf
 
Ransomware_Q4_2023. The report. [EN].pdf
Ransomware_Q4_2023. The report. [EN].pdfRansomware_Q4_2023. The report. [EN].pdf
Ransomware_Q4_2023. The report. [EN].pdf
 
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...
 
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
 
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
 
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...
 
EMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWER
EMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWEREMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWER
EMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWER
 
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 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, ...
 
Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...
Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...
Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...
 
Spring Boot vs Quarkus the ultimate battle - DevoxxUK
Spring Boot vs Quarkus the ultimate battle - DevoxxUKSpring Boot vs Quarkus the ultimate battle - DevoxxUK
Spring Boot vs Quarkus the ultimate battle - DevoxxUK
 
Polkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin WoodPolkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin Wood
 
Finding Java's Hidden Performance Traps @ DevoxxUK 2024
Finding Java's Hidden Performance Traps @ DevoxxUK 2024Finding Java's Hidden Performance Traps @ DevoxxUK 2024
Finding Java's Hidden Performance Traps @ DevoxxUK 2024
 
Boost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfBoost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdf
 
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, ...
 
Exploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone ProcessorsExploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone Processors
 
FWD Group - Insurer Innovation Award 2024
FWD Group - Insurer Innovation Award 2024FWD Group - Insurer Innovation Award 2024
FWD Group - Insurer Innovation Award 2024
 
DBX First Quarter 2024 Investor Presentation
DBX First Quarter 2024 Investor PresentationDBX First Quarter 2024 Investor Presentation
DBX First Quarter 2024 Investor Presentation
 

Testing untestable Code - PFCongres 2010

  • 1. Testing untestable Code Stephan Hochdörfer, bitExpert AG "Quality is a function of thought and reflection - precise thought and reflection. That’s the magic." Michael Feathers
  • 2. About me  Founder of bitExpert AG, Mannheim  Field of duty  Department Manager of Research Labs  Head of Development for bitFramework  Focusing on  PHP  Generative Programming  Contact me  @shochdoerfer  S.Hochdoerfer@bitExpert.de
  • 3. Agenda 1. Theory 2. How to test untestable PHP Code 3. Generate testable code 4. Conclusion
  • 4. Theory "There is no secret to writing tests, there are only secrets to write testable code!" Miško Hevery
  • 5. Theory What is „untestable code“?
  • 6. Theory What is „untestable code“?  Global variables  Singleton  Registry  Globale state  static method calls  Control flow in a constructor  Tight coupling  Dependencies to concrete implementations  to many dependencies to other classes  Dependencies without control
  • 7. Theory "...our test strategy requires us to have more control or visibility of the internal behavior of the system under test." Gerard Meszaros, xUnit Test Patterns: Refactoring Test Code
  • 8. Theory Required class Class to Unittest Test Required class
  • 9. Theory Database Required class External Class to Unittest resource test Required class Required Required Webservice class class
  • 10. Theory Database Required class External Class to Unittest resource test Required class Required Required Webservice class class
  • 11. Theory How to achieve „testable“ code?
  • 12. Theory How to achieve „testable“ code? Refactoring
  • 13. Theory "Before you start refactoring, check that you have a solid suite of tests." Martin Fowler, Refactoring
  • 14. Agenda 1. Theory 2. Testing untestable PHP Code 3. Generate testable code 4. Conclusion
  • 15. Agenda 1. Theory 2. Testing untestable PHP Code – Hardcoded Dependencies – Procedural code – Overwrite internal PHP functions 3. Generate testable code 4. Conclusion
  • 16. Testing „untestable“ PHP Code Assumption Do not change existing code!
  • 17. Testing „untestable“ PHP Code | __autoload <?php class Car { private $Engine; public function __construct($sEngine) { $this->Engine = Engine::getByType($sEngine); } }
  • 18. Testing „untestable“ PHP Code | __autoload <?php class Car { private $Engine; public function __construct($sEngine) { $this->Engine = Engine::getByType($sEngine); } } How to inject a dependency?  Use __autoload
  • 19. Testing „untestable“ PHP Code | __autoload <?php function run_autoload($psClass) { $sFileToInclude = strtolower($psClass).'.php'; if(strtolower($psClass) == 'engine') { $sFileToInclude = '/custom/mocks/'.$sFileToInclude; } include($sFileToInclude); } // Testcase spl_autoload_register('run_autoload'); $oCar = new Car('Diesel'); echo $oCar->run();
  • 20. Testing „untestable“ PHP Code | include_path <?php include('Engine.php'); class Car { private $Engine; public function __construct($sEngine) { $this->Engine = Engine::getByType($sEngine); } }
  • 21. Testing „untestable“ PHP Code | include_path <?php include('Engine.php'); class Car { private $Engine; public function __construct($sEngine) { $this->Engine = Engine::getByType($sEngine); } } How to inject a dependency?  Manipulate include_path setting
  • 22. Testing „untestable“ PHP Code | include_path <?php ini_set('include_path', '/custom/mocks/'.PATH_SEPARATOR. ini_get('include_path')); // Testcase include('car.php'); $oCar = new Car('Diesel'); echo $oCar->run();
  • 23. Testing „untestable“ PHP Code | include_path alternative <?php class CustomFileStreamWrapper { private $_handler; function stream_open($path, $mode, $options, &$opened_path) { stream_wrapper_restore('file'); // @TODO: modify $path before fopen $this->_handler = fopen($path, $mode); stream_wrapper_unregister('file'); stream_wrapper_register('file', 'CustomFileStreamWrapper'); return true; } function stream_read($count) {} function stream_write($data) {} function stream_tell() {} function stream_eof() {} function stream_seek($offset, $whence) {} } stream_wrapper_unregister('file'); stream_wrapper_register('file', 'CustomFileStreamWrapper'); Source: Alex Netkachov, http://www.alexatnet.com/node/203
  • 24. Testing „untestable“ PHP Code | Namespaces <?php class Car { private $Engine; public function __construct($sEngine) { $this->Engine = CarEngine::getByType($sEngine); } }
  • 25. Testing „untestable“ PHP Code | Namespaces <?php class Car { private $Engine; public function __construct($sEngine) { $this->Engine = CarEngine::getByType($sEngine); } } How to inject a dependency?  Use __autoload or manipulate the include_path
  • 26. Testing „untestable“ PHP Code | vfsStream <?php class Car { private $Engine; public function __construct($sEngine, $CacheDir) { $this->Engine = CarEngine::getByType($sEngine); mkdir($CacheDir.'/cache/', 0700, true); } }
  • 27. Testing „untestable“ PHP Code | vfsStream <?php class Car { private $Engine; public function __construct($sEngine, $CacheDir) { $this->Engine = CarEngine::getByType($sEngine); mkdir($CacheDir.'/cache/', 0700, true); } } How mock a filesystem?  Use vfsStream - http://code.google.com/p/bovigo/
  • 28. Testing „untestable“ PHP Code | vfsStream <?php // setup vfsStream vfsStreamWrapper::register(); vfsStreamWrapper::setRoot(new vfsStreamDirectory('app')); $oCar = new Car('Diesel', vfsStream::url('app')); echo vfsStreamWrapper::getRoot()->hasChild('cache');
  • 29. Agenda 1. Theory 2. Testing untestable PHP Code – Hardcoded Dependencies – Procedural code – Overwrite internal PHP functions 3. Generate testable code 4. Conclusion
  • 30. Testing „untestable“ PHP Code „I have no idea how to unit-test procedural code. Unit-testing assumes that I can instantiate a piece of my application in isolation.“ Miško Hevery
  • 31. Testing „untestable“ PHP Code | Test functions <?php function startsWith($sString, $psPre) { return $psPre == substr($sString, 0, strlen($psPre)); } function contains($sString, $sSearch) { return false !== strpos($sString, $sSearch); }
  • 32. Testing „untestable“ PHP Code | Test functions <?php function startsWith($sString, $psPre) { return $psPre == substr($sString, 0, strlen($psPre)); } function contains($sString, $sSearch) { return false !== strpos($sString, $sSearch); } How to test  PHPUnit can call methods  PHPUnit can save/restore globale state
  • 33. Agenda 1. Theory 2. Testing untestable PHP Code – Hardcoded Dependencies – Procedural code – Overwrite internal PHP functions 3. Generate testable code 4. Conclusion
  • 34. Testing „untestable“ PHP Code | overwrite internal functions <?php function buyCar(Car $oCar) { global $oDB; mysql_query("INSERT INTO...", $oDB); mail('order@domain.org', 'New sale', '....'); }
  • 35. Testing „untestable“ PHP Code | overwrite internal functions <?php function buyCar(Car $oCar) { global $oDB; mysql_query("INSERT INTO...", $oDB); mail('order@domain.org', 'New sale', '....'); } How to test  Do not load mysql extension. Provide own implementation  Unfortunatly mail() is part of the PHP core
  • 36. Testing „untestable“ PHP Code | overwrite internal functions <?php function buyCar(Car $oCar) { global $oDB; mysql_query("INSERT INTO...", $oDB); mail('order@domain.org', 'New sale', '....'); } How to test  Use classkit extension to mock internal functions
  • 37. Testing „untestable“ PHP Code | overwrite internal functions <?php ini_set('runkit.internal_override', '1'); runkit_function_redefine('mail','','return true;'); ?>
  • 38. Agenda 1. Theory 2. Testing untestable PHP Code 3. Generate testable code 4. Conclusion
  • 39. Generate testable code Generative Programming Configuration 1 ... n Implementation Generator Product components Generator application
  • 40. Generate testable code Generative Programming Configuration Application Implementation Generator components Testcases Generator application
  • 41. Generate testable code Course of action Extraction  „Mask“ parts of the code Customizing  Change content of global vars  Pre/Postfixes for own functions, methods, classes Recombine  Re-order parts of the code
  • 42. Generate testable code FileFrm FILEIndex_php5 { private String Prefix = "test_"; private String MailSlot = "mail('order@domain.org', 'New sale', '....');"; public FILEIndex_php5() { setFilename("index.php5"); setRelativePath("/"); } private void assign() { BEGINCONTENT() <?php function buyCar(Car $oCar) { global $oDB; <!{Prefix}!>mysql_query(„INSERT INTO...“, $oDB); <!{MailSlot}!> } ?> ENDCONTENT() } }
  • 43. Generate testable code 1. Example Prefix: test_ <?php function buyCar(Car $oCar) { global $oDB; test_mysql_query("INSERT INTO...", $oDB); }
  • 44. Generate testable code 1. Example Prefix: test_ <?php function buyCar(Car $oCar) { global $oDB; test_mysql_query("INSERT INTO...", $oDB); } 2. Example MailSlot: mail('order@domain.org', 'New sale', '....'); <?php function buyCar(Car $oCar) { global $oDB; mysql_query("INSERT INTO...", $oDB); mail('order@domain.org', 'New sale', '....'); } ?>
  • 45. Conclustion Conclusion  Change mindset to write testable code  Dependency Injection  Look for other options to raise the bar  Work around limitations of PHP  PHP is flexible, use it that way