SlideShare une entreprise Scribd logo
1  sur  69
Télécharger pour lire hors ligne
Testing untestable code
 Stephan Hochdörfer, bitExpert AG
Testing untestable code

 About me

  Stephan Hochdörfer, bitExpert AG

  Department Manager Research Labs

  enjoying PHP since 1999

  S.Hochdoerfer@bitExpert.de

  @shochdoerfer
Testing untestable code

 No excuse for writing bad code!
Testing untestable code




 Not to freak out!
Testing untestable code




 Creativity matters!
Testing untestable code




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

 What is „untestable code“?
Testing untestable code




 Wrong object construction

         “new” is evil!
                          s
Testing untestable code




 Tight coupling
Testing untestable code




 Uncertainty
Testing untestable code




       "...our test strategy requires us to
       have more control [...] of the sut."
      Gerard Meszaros, xUnit Test Patterns: Refactoring Test
                              Code
Testing untestable code

 In a perfect world...




                  Unittest
                   Unittest   SUT
                               SUT
Testing untestable code

 Legacy code is not perfect...


                                 Dependency
                                  Dependency

       Unittest
        Unittest          SUT
                           SUT


                                 Dependency
                                  Dependency
Testing untestable code
                                 ...
 Legacy code is not perfect...


                                 Dependency
                                  Dependency

       Unittest
        Unittest          SUT
                           SUT


                                 Dependency
                                  Dependency




                                  ...
Testing untestable code
                                 ...
 Legacy code is not perfect...


                                 Dependency
                                  Dependency

       Unittest
        Unittest          SUT
                           SUT


                                 Dependency
                                  Dependency




                                  ...
Testing untestable code

 How to get „testable“ code?
Testing untestable code

 How to get „testable“ code?




                   Refactoring
Testing untestable code




     "Before you start refactoring, check
     that you have a solid suite of tests."
                    Martin Fowler, Refactoring
Testing untestable code




 Hope? - Nope...
Testing untestable code

 Which path to take?
Testing untestable code

 Which path to take?




       Do not change existing code!
Testing untestable code

 Examples




 Object construction      External resources   Language issues
Testing untestable code

 Object construction
 <?php
 class Car {
    private $Engine;

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

 }
Testing untestable code

 Object construction - 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');
Testing untestable code

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

 class Car {
    private $Engine;

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

 Object construction - 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 code

 Object construction – Stream Wrapper
 <?php
 class CustomWrapper {
   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', 'CustomWrapper');
         return true;
     }
 }
Testing untestable code

 Object construction – Stream Wrapper
 stream_wrapper_unregister('file');
 stream_wrapper_register('file', 'CustomWrapper');
Testing untestable code

 Object construction – Stream Wrapper
 <?php
 class CustomWrapper {
    private $_handler ;

     function stream_read( $count ) {
        $content = fread($this->_handler, $count );
        $content = str_replace ('Engine::getByType' ,
         ' Abstract Engine::get' , $content );
        return $content ;
     }
 }
Testing untestable code

 Object construction – Namespaces
 <?php
 class Car {
    private $Engine;

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

 External resources
Testing untestable code

 External resources



             Database     Webservice



            Filesystem    Mailserver
Testing untestable code

 External resources – Mock database
Testing untestable code

 External resources – Mock database




          Provide own implementation
Testing untestable code

 External resources – Mock database



                          ZF example:
          $db = new Custom_Db_Adapter(array());
          Zend_Db_Table::setDefaultAdapter($db);
Testing untestable code

 External resources – Mock database




 PHPUnit_Extensions_Database_TestCase
Testing untestable code

 External resources – Mock database




            Proxy for your SQL Server
Testing untestable code

 External resources – Mock webservice
Testing untestable code

 External resources – Mock webservice




          Provide own implementation
Testing untestable code

 External resources – Mock webservice




            Host redirect via /etc/hosts
Testing untestable code

 External resources – Mock filesystem
Testing untestable code

 External resources – Mock filesystem
 <?php

 // set up test environmemt
 vfsStream::setup('exampleDir');

 // create directory in test enviroment
 mkdir(vfsStream::url('exampleDir').'/sample/');

 // check if directory was created
 echo vfsStreamWrapper::getRoot()->hasChild('sample');
Testing untestable code

 External resources – Mock Mailserver
Testing untestable code

 External resources – Mock Mailserver




                Use fake mail server
Testing untestable code

 External resources – Mock Mailserver

 $ cat /etc/php5/php.ini | grep sendmail_path
 sendmail_path=/usr/local/bin/logmail

 $ cat /usr/local/bin/logmail
 cat >> /tmp/logmail.log
Testing untestable code

 Dealing with language issues
Testing untestable code

 Dealing with language issues




             Testing your privates?
Testing untestable code

 Dealing with language issues
 <?php
 class CustomWrapper {
    private $_handler;

     function stream_read($count) {
        $content = fread($this->_handler, $count);
        $content = str_replace(
           'private function',
           'public function',
           $content
        );
        return $content;
     }
Testing untestable code

 Dealing with language issues
 $myClass = new MyClass();

 $reflectionClass = new ReflectionClass('MyClass');
 $reflectionMethod = $reflectionClass->
                         getMethod('mydemo');
 $reflectionMethod->setAccessible(true);
 $reflectionMethod->invoke($myClass);
Testing untestable code

 Dealing with language issues




       Overwrite internal functions?
Testing untestable code

 Dealing with language issues




              pecl install runkit-0.9
Testing untestable code

 Dealing with language issues - Runkit
 <?php

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

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

 ?>
Testing untestable code




 What else?
Testing untestable code

 What else?




           Generative Programming
Testing untestable code

 Generative Programming

                 Configuration
                  Configuration


                                                1 ... n
       Implementation
        Implementation             Generator
                                    Generator   Product
         components
          components                             Product



                    Generator
                     Generator
                    application
                     application
Testing untestable code

 Generative Programming

                 Configuration
                  Configuration

                                                Application
                                                 Application

       Implementation
        Implementation             Generator
                                    Generator
         components
          components


                                                Testcases
                                                 Testcases
                    Generator
                     Generator
                    application
                     application
Testing untestable code

 Generative Programming




        A frame is a data structure
       for representing knowledge.
Testing untestable code

 A Frame instance
 <?php
 class Car {
    private $Engine;

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

 }
Testing untestable code

 The Frame controller

 public class MyFrameController extends
 SimpleFrameController {

    public void execute(Frame frame, FeatureConfig
 config) {
       if(config.hasFeature("unittest")) {
         frame.setSlot("Factory", "FactoryMock");
       }
       else {
         frame.setSlot("Factory", "EngineFactory");
       }
    }
 }
Testing untestable code

 Generated result - Testcase
 <?php
 class Car {
    private $Engine;

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

 }
Testing untestable code

 Generated result - Application
 <?php
 class Car {
    private $Engine;

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

 }
Testing untestable code

 What is possible?
Testing untestable code

 What is possible?




          Show / hide parts of the code
Testing untestable code

 What is possible?




         Change content of global vars!
Testing untestable code

 What is possible?




              Define pre- or postfixes!
Testing untestable code

 Is it worth it?
Testing untestable code

 Conclusions




         Change your mindset to write
                testable code!
Testing untestable code

 Conclusions




            PHP is a swiss-army knife.
                 Use it that way!
http://joind.in/3026

Contenu connexe

Tendances

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
 
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
 
Java 7: Fork/Join, Invokedynamic and the future
Java 7: Fork/Join, Invokedynamic and the futureJava 7: Fork/Join, Invokedynamic and the future
Java 7: Fork/Join, Invokedynamic and the futureSander Mak (@Sander_Mak)
 
Zend Framework 2 quick start
Zend Framework 2 quick startZend Framework 2 quick start
Zend Framework 2 quick startEnrico Zimuel
 
Testing untestable Code - PFCongres 2010
Testing untestable Code - PFCongres 2010Testing untestable Code - PFCongres 2010
Testing untestable Code - PFCongres 2010Stephan Hochdörfer
 
Java Code Generation for Productivity
Java Code Generation for ProductivityJava Code Generation for Productivity
Java Code Generation for ProductivityDavid Noble
 
PHP 7 Crash Course
PHP 7 Crash CoursePHP 7 Crash Course
PHP 7 Crash CourseColin O'Dell
 
JavaOne 2014 - CON2013 - Code Generation in the Java Compiler: Annotation Pro...
JavaOne 2014 - CON2013 - Code Generation in the Java Compiler: Annotation Pro...JavaOne 2014 - CON2013 - Code Generation in the Java Compiler: Annotation Pro...
JavaOne 2014 - CON2013 - Code Generation in the Java Compiler: Annotation Pro...Jorge Hidalgo
 
Working Effectively With Legacy Code
Working Effectively With Legacy CodeWorking Effectively With Legacy Code
Working Effectively With Legacy Codescidept
 
Working Effectively With Legacy Perl Code
Working Effectively With Legacy Perl CodeWorking Effectively With Legacy Perl Code
Working Effectively With Legacy Perl Codeerikmsp
 
Living With Legacy Code
Living With Legacy CodeLiving With Legacy Code
Living With Legacy CodeRowan Merewood
 
Java 7 Whats New(), Whats Next() from Oredev
Java 7 Whats New(), Whats Next() from OredevJava 7 Whats New(), Whats Next() from Oredev
Java 7 Whats New(), Whats Next() from OredevMattias Karlsson
 
Webinar: Zend framework Getting to grips (ZF1)
Webinar: Zend framework Getting to grips (ZF1)Webinar: Zend framework Getting to grips (ZF1)
Webinar: Zend framework Getting to grips (ZF1)Ryan Mauger
 
Zend framework: Getting to grips (ZF1)
Zend framework: Getting to grips (ZF1)Zend framework: Getting to grips (ZF1)
Zend framework: Getting to grips (ZF1)Ryan Mauger
 

Tendances (20)

Real World Dependency Injection SE - phpugrhh
Real World Dependency Injection SE - phpugrhhReal World Dependency Injection SE - phpugrhh
Real World Dependency Injection SE - phpugrhh
 
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
 
Java 7: Fork/Join, Invokedynamic and the future
Java 7: Fork/Join, Invokedynamic and the futureJava 7: Fork/Join, Invokedynamic and the future
Java 7: Fork/Join, Invokedynamic and the future
 
What's new in Java EE 6
What's new in Java EE 6What's new in Java EE 6
What's new in Java EE 6
 
Zend Framework 2 quick start
Zend Framework 2 quick startZend Framework 2 quick start
Zend Framework 2 quick start
 
Testing untestable Code - PFCongres 2010
Testing untestable Code - PFCongres 2010Testing untestable Code - PFCongres 2010
Testing untestable Code - PFCongres 2010
 
Java Code Generation for Productivity
Java Code Generation for ProductivityJava Code Generation for Productivity
Java Code Generation for Productivity
 
PHP 7 Crash Course
PHP 7 Crash CoursePHP 7 Crash Course
PHP 7 Crash Course
 
JavaOne 2014 - CON2013 - Code Generation in the Java Compiler: Annotation Pro...
JavaOne 2014 - CON2013 - Code Generation in the Java Compiler: Annotation Pro...JavaOne 2014 - CON2013 - Code Generation in the Java Compiler: Annotation Pro...
JavaOne 2014 - CON2013 - Code Generation in the Java Compiler: Annotation Pro...
 
Working Effectively With Legacy Code
Working Effectively With Legacy CodeWorking Effectively With Legacy Code
Working Effectively With Legacy Code
 
Working Effectively With Legacy Perl Code
Working Effectively With Legacy Perl CodeWorking Effectively With Legacy Perl Code
Working Effectively With Legacy Perl Code
 
Spring frame work
Spring frame workSpring frame work
Spring frame work
 
UI testing in Xcode 7
UI testing in Xcode 7UI testing in Xcode 7
UI testing in Xcode 7
 
Java Enterprise Edition
Java Enterprise EditionJava Enterprise Edition
Java Enterprise Edition
 
Living With Legacy Code
Living With Legacy CodeLiving With Legacy Code
Living With Legacy Code
 
Java Tutorial
Java TutorialJava Tutorial
Java Tutorial
 
Java 7 Whats New(), Whats Next() from Oredev
Java 7 Whats New(), Whats Next() from OredevJava 7 Whats New(), Whats Next() from Oredev
Java 7 Whats New(), Whats Next() from Oredev
 
Webinar: Zend framework Getting to grips (ZF1)
Webinar: Zend framework Getting to grips (ZF1)Webinar: Zend framework Getting to grips (ZF1)
Webinar: Zend framework Getting to grips (ZF1)
 
Zend framework: Getting to grips (ZF1)
Zend framework: Getting to grips (ZF1)Zend framework: Getting to grips (ZF1)
Zend framework: Getting to grips (ZF1)
 
Javascript Best Practices
Javascript Best PracticesJavascript Best Practices
Javascript Best Practices
 

Similaire à Testing untestable code - phpday

Automated infrastructure testing - by Ranjib Dey
Automated infrastructure testing - by Ranjib DeyAutomated infrastructure testing - by Ranjib Dey
Automated infrastructure testing - by Ranjib Deybhumika2108
 
Automated Infrastructure Testing
Automated Infrastructure TestingAutomated Infrastructure Testing
Automated Infrastructure TestingRanjib Dey
 
Unit tests & TDD
Unit tests & TDDUnit tests & TDD
Unit tests & TDDDror Helper
 
Unit Testing Android Applications
Unit Testing Android ApplicationsUnit Testing Android Applications
Unit Testing Android ApplicationsRody Middelkoop
 
GlobalLogic Test Automation Online TechTalk “Test Driven Development as a Per...
GlobalLogic Test Automation Online TechTalk “Test Driven Development as a Per...GlobalLogic Test Automation Online TechTalk “Test Driven Development as a Per...
GlobalLogic Test Automation Online TechTalk “Test Driven Development as a Per...GlobalLogic Ukraine
 
Extreme
ExtremeExtreme
ExtremeESUG
 
Automated Infrastructure Testing - Ranjib Dey
Automated Infrastructure Testing - Ranjib DeyAutomated Infrastructure Testing - Ranjib Dey
Automated Infrastructure Testing - Ranjib DeyThoughtworks
 
Unit Testing and Coverage for AngularJS
Unit Testing and Coverage for AngularJSUnit Testing and Coverage for AngularJS
Unit Testing and Coverage for AngularJSKnoldus Inc.
 
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
 
Automated Frontend Testing
Automated Frontend TestingAutomated Frontend Testing
Automated Frontend TestingNeil Crosby
 
Quick tour to front end unit testing using jasmine
Quick tour to front end unit testing using jasmineQuick tour to front end unit testing using jasmine
Quick tour to front end unit testing using jasmineGil Fink
 
Dependency Injection in .NET applications
Dependency Injection in .NET applicationsDependency Injection in .NET applications
Dependency Injection in .NET applicationsBabak Naffas
 
Scala for Test Automation
Scala for Test AutomationScala for Test Automation
Scala for Test Automationrthanavarapu
 

Similaire à Testing untestable code - phpday (20)

Testing untestable code - IPC12
Testing untestable code - IPC12Testing untestable code - IPC12
Testing untestable code - IPC12
 
Automated infrastructure testing - by Ranjib Dey
Automated infrastructure testing - by Ranjib DeyAutomated infrastructure testing - by Ranjib Dey
Automated infrastructure testing - by Ranjib Dey
 
Automated Infrastructure Testing
Automated Infrastructure TestingAutomated Infrastructure Testing
Automated Infrastructure Testing
 
Unit tests & TDD
Unit tests & TDDUnit tests & TDD
Unit tests & TDD
 
Test
TestTest
Test
 
Unit Testing Android Applications
Unit Testing Android ApplicationsUnit Testing Android Applications
Unit Testing Android Applications
 
Coding Naked 2023
Coding Naked 2023Coding Naked 2023
Coding Naked 2023
 
GlobalLogic Test Automation Online TechTalk “Test Driven Development as a Per...
GlobalLogic Test Automation Online TechTalk “Test Driven Development as a Per...GlobalLogic Test Automation Online TechTalk “Test Driven Development as a Per...
GlobalLogic Test Automation Online TechTalk “Test Driven Development as a Per...
 
Extreme
ExtremeExtreme
Extreme
 
Automated Infrastructure Testing - Ranjib Dey
Automated Infrastructure Testing - Ranjib DeyAutomated Infrastructure Testing - Ranjib Dey
Automated Infrastructure Testing - Ranjib Dey
 
Unit Testing and Coverage for AngularJS
Unit Testing and Coverage for AngularJSUnit Testing and Coverage for AngularJS
Unit Testing and Coverage for AngularJS
 
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
 
Automated Frontend Testing
Automated Frontend TestingAutomated Frontend Testing
Automated Frontend Testing
 
Quick tour to front end unit testing using jasmine
Quick tour to front end unit testing using jasmineQuick tour to front end unit testing using jasmine
Quick tour to front end unit testing using jasmine
 
Dependency Injection in .NET applications
Dependency Injection in .NET applicationsDependency Injection in .NET applications
Dependency Injection in .NET applications
 
Coding Naked
Coding NakedCoding Naked
Coding Naked
 
Unit test
Unit testUnit test
Unit test
 
Unit testing - A&BP CC
Unit testing - A&BP CCUnit testing - A&BP CC
Unit testing - A&BP CC
 
Gallio Crafting A Toolchain
Gallio Crafting A ToolchainGallio Crafting A Toolchain
Gallio Crafting A Toolchain
 
Scala for Test Automation
Scala for Test AutomationScala for Test Automation
Scala for Test Automation
 

Plus de 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
 
Phing for power users - frOSCon8
Phing for power users - frOSCon8Phing for power users - frOSCon8
Phing for power users - frOSCon8Stephan Hochdörfer
 
Offline strategies for HTML5 web applications - frOSCon8
Offline strategies for HTML5 web applications - frOSCon8Offline strategies for HTML5 web applications - frOSCon8
Offline strategies for HTML5 web applications - frOSCon8Stephan Hochdörfer
 
Offline Strategies for HTML5 Web Applications - oscon13
Offline Strategies for HTML5 Web Applications - oscon13Offline Strategies for HTML5 Web Applications - oscon13
Offline Strategies for HTML5 Web Applications - oscon13Stephan Hochdörfer
 
Real World Dependency Injection - oscon13
Real World Dependency Injection - oscon13Real World Dependency Injection - oscon13
Real World Dependency Injection - oscon13Stephan Hochdörfer
 
Dependency Injection in PHP - dwx13
Dependency Injection in PHP - dwx13Dependency Injection in PHP - dwx13
Dependency Injection in PHP - dwx13Stephan 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
 
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
 
Phing for power users - dpc_uncon13
Phing for power users - dpc_uncon13Phing for power users - dpc_uncon13
Phing for power users - dpc_uncon13Stephan 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
 
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
 
Real World Dependency Injection - phpugffm13
Real World Dependency Injection - phpugffm13Real World Dependency Injection - phpugffm13
Real World Dependency Injection - phpugffm13Stephan 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
 
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
 
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
 

Plus de Stephan Hochdörfer (20)

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...
 
Phing for power users - frOSCon8
Phing for power users - frOSCon8Phing for power users - frOSCon8
Phing for power users - frOSCon8
 
Offline strategies for HTML5 web applications - frOSCon8
Offline strategies for HTML5 web applications - frOSCon8Offline strategies for HTML5 web applications - frOSCon8
Offline strategies for HTML5 web applications - frOSCon8
 
Offline Strategies for HTML5 Web Applications - oscon13
Offline Strategies for HTML5 Web Applications - oscon13Offline Strategies for HTML5 Web Applications - oscon13
Offline Strategies for HTML5 Web Applications - oscon13
 
Real World Dependency Injection - oscon13
Real World Dependency Injection - oscon13Real World Dependency Injection - oscon13
Real World Dependency Injection - oscon13
 
Dependency Injection in PHP - dwx13
Dependency Injection in PHP - dwx13Dependency Injection in PHP - dwx13
Dependency Injection in PHP - 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 - dwx13
 
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
 
Phing for power users - dpc_uncon13
Phing for power users - dpc_uncon13Phing for power users - dpc_uncon13
Phing for power users - dpc_uncon13
 
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
 
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
 
Real World Dependency Injection - phpugffm13
Real World Dependency Injection - phpugffm13Real World Dependency Injection - phpugffm13
Real World Dependency Injection - phpugffm13
 
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
 
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
 
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 - phpday

  • 1. Testing untestable code Stephan Hochdörfer, bitExpert AG
  • 2. Testing untestable code About me  Stephan Hochdörfer, bitExpert AG  Department Manager Research Labs  enjoying PHP since 1999  S.Hochdoerfer@bitExpert.de  @shochdoerfer
  • 3. Testing untestable code No excuse for writing bad code!
  • 4. Testing untestable code Not to freak out!
  • 5. Testing untestable code Creativity matters!
  • 6. Testing untestable code "There is no secret to writing tests, there are only secrets to write testable code!" Miško Hevery
  • 7. Testing untestable code What is „untestable code“?
  • 8. Testing untestable code Wrong object construction “new” is evil! s
  • 9. Testing untestable code Tight coupling
  • 10. Testing untestable code Uncertainty
  • 11. Testing untestable code "...our test strategy requires us to have more control [...] of the sut." Gerard Meszaros, xUnit Test Patterns: Refactoring Test Code
  • 12. Testing untestable code In a perfect world... Unittest Unittest SUT SUT
  • 13. Testing untestable code Legacy code is not perfect... Dependency Dependency Unittest Unittest SUT SUT Dependency Dependency
  • 14. Testing untestable code ... Legacy code is not perfect... Dependency Dependency Unittest Unittest SUT SUT Dependency Dependency ...
  • 15. Testing untestable code ... Legacy code is not perfect... Dependency Dependency Unittest Unittest SUT SUT Dependency Dependency ...
  • 16. Testing untestable code How to get „testable“ code?
  • 17. Testing untestable code How to get „testable“ code? Refactoring
  • 18. Testing untestable code "Before you start refactoring, check that you have a solid suite of tests." Martin Fowler, Refactoring
  • 19. Testing untestable code Hope? - Nope...
  • 20. Testing untestable code Which path to take?
  • 21. Testing untestable code Which path to take? Do not change existing code!
  • 22. Testing untestable code Examples Object construction External resources Language issues
  • 23. Testing untestable code Object construction <?php class Car { private $Engine; public function __construct($sEngine) { $this->Engine = Engine::getByType($sEngine); } }
  • 24. Testing untestable code Object construction - 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');
  • 25. Testing untestable code Object construction <?php include('Engine.php'); class Car { private $Engine; public function __construct($sEngine) { $this->Engine = Engine::getByType($sEngine); } }
  • 26. Testing untestable code Object construction - 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();
  • 27. Testing untestable code Object construction – Stream Wrapper <?php class CustomWrapper { 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', 'CustomWrapper'); return true; } }
  • 28. Testing untestable code Object construction – Stream Wrapper stream_wrapper_unregister('file'); stream_wrapper_register('file', 'CustomWrapper');
  • 29. Testing untestable code Object construction – Stream Wrapper <?php class CustomWrapper { private $_handler ; function stream_read( $count ) { $content = fread($this->_handler, $count ); $content = str_replace ('Engine::getByType' , ' Abstract Engine::get' , $content ); return $content ; } }
  • 30. Testing untestable code Object construction – Namespaces <?php class Car { private $Engine; public function __construct($sEngine) { $this->Engine = CarEngine:: getByType($sEngine); } }
  • 31. Testing untestable code External resources
  • 32. Testing untestable code External resources Database Webservice Filesystem Mailserver
  • 33. Testing untestable code External resources – Mock database
  • 34. Testing untestable code External resources – Mock database Provide own implementation
  • 35. Testing untestable code External resources – Mock database ZF example: $db = new Custom_Db_Adapter(array()); Zend_Db_Table::setDefaultAdapter($db);
  • 36. Testing untestable code External resources – Mock database PHPUnit_Extensions_Database_TestCase
  • 37. Testing untestable code External resources – Mock database Proxy for your SQL Server
  • 38. Testing untestable code External resources – Mock webservice
  • 39. Testing untestable code External resources – Mock webservice Provide own implementation
  • 40. Testing untestable code External resources – Mock webservice Host redirect via /etc/hosts
  • 41. Testing untestable code External resources – Mock filesystem
  • 42. Testing untestable code External resources – Mock filesystem <?php // set up test environmemt vfsStream::setup('exampleDir'); // create directory in test enviroment mkdir(vfsStream::url('exampleDir').'/sample/'); // check if directory was created echo vfsStreamWrapper::getRoot()->hasChild('sample');
  • 43. Testing untestable code External resources – Mock Mailserver
  • 44. Testing untestable code External resources – Mock Mailserver Use fake mail server
  • 45. Testing untestable code External resources – Mock Mailserver $ cat /etc/php5/php.ini | grep sendmail_path sendmail_path=/usr/local/bin/logmail $ cat /usr/local/bin/logmail cat >> /tmp/logmail.log
  • 46. Testing untestable code Dealing with language issues
  • 47. Testing untestable code Dealing with language issues Testing your privates?
  • 48. Testing untestable code Dealing with language issues <?php class CustomWrapper { private $_handler; function stream_read($count) { $content = fread($this->_handler, $count); $content = str_replace( 'private function', 'public function', $content ); return $content; }
  • 49. Testing untestable code Dealing with language issues $myClass = new MyClass(); $reflectionClass = new ReflectionClass('MyClass'); $reflectionMethod = $reflectionClass-> getMethod('mydemo'); $reflectionMethod->setAccessible(true); $reflectionMethod->invoke($myClass);
  • 50. Testing untestable code Dealing with language issues Overwrite internal functions?
  • 51. Testing untestable code Dealing with language issues pecl install runkit-0.9
  • 52. Testing untestable code Dealing with language issues - Runkit <?php ini_set('runkit.internal_override', '1'); runkit_function_redefine('mail','','return true;'); ?>
  • 54. Testing untestable code What else? Generative Programming
  • 55. Testing untestable code Generative Programming Configuration Configuration 1 ... n Implementation Implementation Generator Generator Product components components Product Generator Generator application application
  • 56. Testing untestable code Generative Programming Configuration Configuration Application Application Implementation Implementation Generator Generator components components Testcases Testcases Generator Generator application application
  • 57. Testing untestable code Generative Programming A frame is a data structure for representing knowledge.
  • 58. Testing untestable code A Frame instance <?php class Car { private $Engine; public function __construct($sEngine) { $this->Engine = <!{Factory}!>:: getByType($sEngine); } }
  • 59. Testing untestable code The Frame controller public class MyFrameController extends SimpleFrameController { public void execute(Frame frame, FeatureConfig config) { if(config.hasFeature("unittest")) { frame.setSlot("Factory", "FactoryMock"); } else { frame.setSlot("Factory", "EngineFactory"); } } }
  • 60. Testing untestable code Generated result - Testcase <?php class Car { private $Engine; public function __construct($sEngine) { $this->Engine = FactoryMock:: getByType($sEngine); } }
  • 61. Testing untestable code Generated result - Application <?php class Car { private $Engine; public function __construct($sEngine) { $this->Engine = EngineFactory:: getByType($sEngine); } }
  • 62. Testing untestable code What is possible?
  • 63. Testing untestable code What is possible? Show / hide parts of the code
  • 64. Testing untestable code What is possible? Change content of global vars!
  • 65. Testing untestable code What is possible? Define pre- or postfixes!
  • 66. Testing untestable code Is it worth it?
  • 67. Testing untestable code Conclusions Change your mindset to write testable code!
  • 68. Testing untestable code Conclusions PHP is a swiss-army knife. Use it that way!