SlideShare uma empresa Scribd logo
1 de 74
Baixar para ler offline
Testing untestable code
Testing untestable code

 Über mich

  Stephan Hochdörfer, bitExpert AG
  Department Manager Research Labs
  PHP Fanboy seit 1999
  S.Hochdoerfer@bitExpert.de
  @shochdoerfer
Testing untestable code

 Keine Entschuldigung für schlechten Code!
Testing untestable code




 Nicht ausflippen!
Testing untestable code




 Kreativität zählt!
Testing untestable code




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

 Was ist „untestbarer Code“?
Testing untestable code




 1. Falsche Instantiierung

         “new” is evil!
                          s
Testing untestable code



 2. Starke Kopplung
Testing untestable code




 Keine Wiederverwendbarkeit
Testing untestable code




 Nicht isolierbar, nicht testbar!
Testing untestable code




 3. Ungewissheit
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 einer perfekten Welt..




                  Unittest
                   Unittest   SUT
                               SUT
Testing untestable code

 Legacy code ist nicht perfekt...


                                    Abhängige
                                     Abhängige
                                      Klasse
                                       Klasse
       Unittest
        Unittest          SUT
                           SUT

                                    Abhängige
                                     Abhängige
                                      Klasse
                                       Klasse
Testing untestable code
                                    ...
 Legacy code ist nicht perfekt...


                                     Abhängige
                                      Abhängige
                                       Klasse
                                        Klasse
       Unittest
        Unittest          SUT
                           SUT

                                     Abhängige
                                      Abhängige
                                       Klasse
                                        Klasse




                                     ...
Testing untestable code
                                    ...
 Legacy code ist nicht perfekt...


                                     Abhängige
                                      Abhängige
                                       Klasse
                                        Klasse
       Unittest
        Unittest          SUT
                           SUT

                                     Abhängige
                                      Abhängige
                                       Klasse
                                        Klasse




                                     ...
Testing untestable code

 Wie erzeugt man „testbaren Code“?
Testing untestable code

 Wie erzeugt man „testbaren Code“?




                   Refactoring
Testing untestable code




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




 Hoffnung? ...ist nicht genug
Testing untestable code

 Wohin führt die Reise?
Testing untestable code

 Wohin führt die Reise?




           Vorhandenen Code nicht
                  ändern!
Testing untestable code

 Beispiele




 Objekterzeugung      Externe Ressourcen   Sprachbarrieren
Testing untestable code

 Objekterzeugung
 <?php
 class Car {
    private $engine;

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

 }
Testing untestable code

 Objekterzeugung - Autoload
 <?php
 function run_autoload($class) {
    $fileToInclude = strtolower($class).'.php';
    if(strtolower($class) == 'engine') {
       $fileToInclude = '/custom/mocks/'.
       $fileToInclude;
    }
    include($fileToInclude);
 }


 // Testcase
 spl_autoload_register('run_autoload');
 $car = new Car('Diesel');
 echo $car->run();
Testing untestable code

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

 class Car {
    private $engine;

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

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

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

 $car = new Car('Diesel');
 echo $car->run();
Testing untestable code

 Objekterzeugung – 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

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

 Objekterzeugung – 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

 Objekterzeugung – Namespaces
 <?php
 class Car {
    private $engine;

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

 Externe Ressourcen
Testing untestable code

 Externe Ressourcen



            Datenbank     Webservice



           Dateisystem    Mailserver
Testing untestable code

 Externe Ressourcen – Datenbank mocken
Testing untestable code

 Externe Ressourcen – Datenbank mocken




      Eigene Implementierung anbieten
Testing untestable code

 Externe Ressourcen – Datenbank mocken



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

 Externe Ressourcen – Datenbank mocken




 PHPUnit_Extensions_Database_TestCase
Testing untestable code

 Externe Ressourcen – Datenbank mocken




             Proxy for den SQL Server
Testing untestable code

 Externe Ressourcen – Webservice mocken
Testing untestable code

 Externe Ressourcen – Webservice mocken




      Eigene Implementierung anbieten
Testing untestable code

 Externe Ressourcen – Webservice mocken




              Host Alias via /etc/hosts
Testing untestable code

 Externe Ressourcen – Dateisytem mocken
Testing untestable code

 Externe Ressourcen – Dateisystem mocken
 <?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

 Externe Ressourcen – Mailserver mocken
Testing untestable code

 Externe Ressourcen – Mailserver mocken




           fake mail server verwenden
Testing untestable code

 Externe Ressourcen – Mailserver mocken

 $ 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

 Sprachbarrieren
Testing untestable code

 Sprachbarrieren




          private Methoden testen?
Testing untestable code

 Sprachbarrieren
 <?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

 Sprachbarrieren
 $myClass = new MyClass();

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

 Sprachbarrieren




                Interne Funktionen
                  überschreiben?
Testing untestable code

 Sprachbarrieren - Runkit




              pecl install runkit-0.9
Testing untestable code

 Sprachbarrieren - Runkit
 <?php

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

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

 ?>
Testing untestable code




 Spielraum?
Testing untestable code




 Abstrahieren du sollst!
Testing untestable code

 Was sonst?




        Generative Programmierung
Testing untestable code

 Generative Programmierung




                          Generator
                          Generator
Testing untestable code

 Generative Programmierung

                          Konfiguration
                           Konfiguration
                             (DSL)
                              (DSL)




                          Generator
                          Generator
Software generieren statt programmieren


 Generative Programmierung

                                          Konfiguration
                                           Konfiguration
                                             (DSL)
                                              (DSL)




   Implementierungs-
    Implementierungs-
     komponenten
                                          Generator
                                          Generator
      komponenten
Testing untestable code

 Generative Programmierung

                          Konfiguration
                           Konfiguration
                             (DSL)
                              (DSL)



                                           1..n
  Implementierungs-
   Implementierungs-
    komponenten
                          Generator
                          Generator          Produkt
     komponenten                              Produkt
Testing untestable code

 Generative Programmierung

                          Konfiguration
                           Konfiguration
                             (DSL)
                              (DSL)
                                             Tests
                                              Tests



  Implementierungs-
   Implementierungs-
    komponenten
                          Generator
                          Generator        Applikation
     komponenten                            Applikation
Testing untestable code

 Generative Programmierung




    Ein Frame ist eine Datenstruktur
        die Wissen repräsentiert.
Testing untestable code

 Eine Frame Instanz
 <?php
 class Car {
    private $engine;

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

 }
Testing untestable code

 Der 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

 Nach der Generierung - Testcase
 <?php
 class Car {
    private $engine;

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

 }
Testing untestable code

 Nach der Generierung - Applikation
 <?php
 class Car {
    private $engine;

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

 }
Testing untestable code

 Was ist möglich?
Testing untestable code

 Was ist möglich?




            Extraktion von Codezeilen
Testing untestable code

 Was ist möglich?




            Globale Inhalte verändern
Testing untestable code

 Was ist möglich?




       Pre- oder Postfixes für Methoden
Testing untestable code

 Wie weit sollte man gehen?
Vielen Dank!
Testing untestable code

 Bildquellen

 http://www.flickr.com/photos/andresrueda/3452940751/
 http://www.flickr.com/photos/andresrueda/3455410635/

Mais conteúdo relacionado

Semelhante a Testing untestable code - DCHH

Funktionstests in SAP
Funktionstests in SAPFunktionstests in SAP
Funktionstests in SAPCadaxo GmbH
 
Testgetriebene Softwareentwicklung
Testgetriebene SoftwareentwicklungTestgetriebene Softwareentwicklung
Testgetriebene Softwareentwicklungjlink
 
Mögen die Tests mit dir sein
Mögen die Tests mit dir seinMögen die Tests mit dir sein
Mögen die Tests mit dir seincodepitbull
 
Agiles Testing
Agiles TestingAgiles Testing
Agiles TestingNEOMO GmbH
 
Advanced Refactoring Patterns
Advanced Refactoring PatternsAdvanced Refactoring Patterns
Advanced Refactoring PatternsHendrik Lösch
 
Advanced Refactoring Patterns - Dev Day 2018
Advanced Refactoring Patterns - Dev Day 2018Advanced Refactoring Patterns - Dev Day 2018
Advanced Refactoring Patterns - Dev Day 2018Hendrik Lösch
 
Testen im EE-Umfeld – Seien Sie feige!
Testen im EE-Umfeld – Seien Sie feige!Testen im EE-Umfeld – Seien Sie feige!
Testen im EE-Umfeld – Seien Sie feige!gedoplan
 
Die nächste Generation des Unit Testing
Die nächste Generation des Unit TestingDie nächste Generation des Unit Testing
Die nächste Generation des Unit TestingDaniel Lehner
 
javaPersistenceInActionFeaturesJenseitsDesEntryLevels
javaPersistenceInActionFeaturesJenseitsDesEntryLevelsjavaPersistenceInActionFeaturesJenseitsDesEntryLevels
javaPersistenceInActionFeaturesJenseitsDesEntryLevelsgedoplan
 
JavaScript für Java-Entwickler W-JAX 2013
JavaScript für Java-Entwickler W-JAX 2013JavaScript für Java-Entwickler W-JAX 2013
JavaScript für Java-Entwickler W-JAX 2013Oliver Zeigermann
 
Wjax integrationsprojekte auf dem weg zur continuous delivery 2011 11-10
Wjax integrationsprojekte auf dem weg zur continuous delivery 2011 11-10Wjax integrationsprojekte auf dem weg zur continuous delivery 2011 11-10
Wjax integrationsprojekte auf dem weg zur continuous delivery 2011 11-10Ralf Sigmund
 
Feige sein! Testen im Java-EE-Umfeld
Feige sein! Testen im Java-EE-UmfeldFeige sein! Testen im Java-EE-Umfeld
Feige sein! Testen im Java-EE-Umfeldgedoplan
 
Einführung Vorgehensmodelle und Agile Software Entwicklung
Einführung Vorgehensmodelle und Agile Software EntwicklungEinführung Vorgehensmodelle und Agile Software Entwicklung
Einführung Vorgehensmodelle und Agile Software EntwicklungChristian Baranowski
 
Testgetriebene Entwicklung mit JavaScript - webtech 2010
Testgetriebene Entwicklung mit JavaScript - webtech 2010Testgetriebene Entwicklung mit JavaScript - webtech 2010
Testgetriebene Entwicklung mit JavaScript - webtech 2010Sebastian Sanitz
 
BED-Con - Tools für den täglichen Kampf als Entwickler
BED-Con - Tools für den täglichen Kampf als EntwicklerBED-Con - Tools für den täglichen Kampf als Entwickler
BED-Con - Tools für den täglichen Kampf als EntwicklerPatrick Baumgartner
 
Einführung in Puppet und Vagrant
Einführung in Puppet und VagrantEinführung in Puppet und Vagrant
Einführung in Puppet und Vagrants0enke
 
Unit testing mit Javascript
Unit testing mit JavascriptUnit testing mit Javascript
Unit testing mit Javascriptjoergreichert
 
Softwarequalitätssicherung mit Continuous Integration Tools
Softwarequalitätssicherung mit Continuous Integration ToolsSoftwarequalitätssicherung mit Continuous Integration Tools
Softwarequalitätssicherung mit Continuous Integration ToolsGFU Cyrus AG
 

Semelhante a Testing untestable code - DCHH (20)

Funktionstests in SAP
Funktionstests in SAPFunktionstests in SAP
Funktionstests in SAP
 
Testgetriebene Softwareentwicklung
Testgetriebene SoftwareentwicklungTestgetriebene Softwareentwicklung
Testgetriebene Softwareentwicklung
 
Mögen die Tests mit dir sein
Mögen die Tests mit dir seinMögen die Tests mit dir sein
Mögen die Tests mit dir sein
 
Agiles Testing
Agiles TestingAgiles Testing
Agiles Testing
 
Advanced Refactoring Patterns
Advanced Refactoring PatternsAdvanced Refactoring Patterns
Advanced Refactoring Patterns
 
Advanced Refactoring Patterns - Dev Day 2018
Advanced Refactoring Patterns - Dev Day 2018Advanced Refactoring Patterns - Dev Day 2018
Advanced Refactoring Patterns - Dev Day 2018
 
Testen im EE-Umfeld – Seien Sie feige!
Testen im EE-Umfeld – Seien Sie feige!Testen im EE-Umfeld – Seien Sie feige!
Testen im EE-Umfeld – Seien Sie feige!
 
Die nächste Generation des Unit Testing
Die nächste Generation des Unit TestingDie nächste Generation des Unit Testing
Die nächste Generation des Unit Testing
 
javaPersistenceInActionFeaturesJenseitsDesEntryLevels
javaPersistenceInActionFeaturesJenseitsDesEntryLevelsjavaPersistenceInActionFeaturesJenseitsDesEntryLevels
javaPersistenceInActionFeaturesJenseitsDesEntryLevels
 
Property Based Testing
Property Based TestingProperty Based Testing
Property Based Testing
 
Continuous Delivery
Continuous DeliveryContinuous Delivery
Continuous Delivery
 
JavaScript für Java-Entwickler W-JAX 2013
JavaScript für Java-Entwickler W-JAX 2013JavaScript für Java-Entwickler W-JAX 2013
JavaScript für Java-Entwickler W-JAX 2013
 
Wjax integrationsprojekte auf dem weg zur continuous delivery 2011 11-10
Wjax integrationsprojekte auf dem weg zur continuous delivery 2011 11-10Wjax integrationsprojekte auf dem weg zur continuous delivery 2011 11-10
Wjax integrationsprojekte auf dem weg zur continuous delivery 2011 11-10
 
Feige sein! Testen im Java-EE-Umfeld
Feige sein! Testen im Java-EE-UmfeldFeige sein! Testen im Java-EE-Umfeld
Feige sein! Testen im Java-EE-Umfeld
 
Einführung Vorgehensmodelle und Agile Software Entwicklung
Einführung Vorgehensmodelle und Agile Software EntwicklungEinführung Vorgehensmodelle und Agile Software Entwicklung
Einführung Vorgehensmodelle und Agile Software Entwicklung
 
Testgetriebene Entwicklung mit JavaScript - webtech 2010
Testgetriebene Entwicklung mit JavaScript - webtech 2010Testgetriebene Entwicklung mit JavaScript - webtech 2010
Testgetriebene Entwicklung mit JavaScript - webtech 2010
 
BED-Con - Tools für den täglichen Kampf als Entwickler
BED-Con - Tools für den täglichen Kampf als EntwicklerBED-Con - Tools für den täglichen Kampf als Entwickler
BED-Con - Tools für den täglichen Kampf als Entwickler
 
Einführung in Puppet und Vagrant
Einführung in Puppet und VagrantEinführung in Puppet und Vagrant
Einführung in Puppet und Vagrant
 
Unit testing mit Javascript
Unit testing mit JavascriptUnit testing mit Javascript
Unit testing mit Javascript
 
Softwarequalitätssicherung mit Continuous Integration Tools
Softwarequalitätssicherung mit Continuous Integration ToolsSoftwarequalitätssicherung mit Continuous Integration Tools
Softwarequalitätssicherung mit Continuous Integration Tools
 

Mais de 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
 
Testing untestable code - ConFoo13
Testing untestable code - ConFoo13Testing untestable code - ConFoo13
Testing untestable code - ConFoo13Stephan 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
 

Mais de Stephan Hochdörfer (20)

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
 
Testing untestable code - ConFoo13
Testing untestable code - ConFoo13Testing untestable code - ConFoo13
Testing untestable code - ConFoo13
 
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
 
Testing untestable code - IPC12
Testing untestable code - IPC12Testing untestable code - IPC12
Testing untestable code - IPC12
 
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
 

Testing untestable code - DCHH

  • 2. Testing untestable code Über mich  Stephan Hochdörfer, bitExpert AG  Department Manager Research Labs  PHP Fanboy seit 1999  S.Hochdoerfer@bitExpert.de  @shochdoerfer
  • 3. Testing untestable code Keine Entschuldigung für schlechten Code!
  • 4. Testing untestable code Nicht ausflippen!
  • 5. Testing untestable code Kreativität zählt!
  • 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 Was ist „untestbarer Code“?
  • 8. Testing untestable code 1. Falsche Instantiierung “new” is evil! s
  • 9. Testing untestable code 2. Starke Kopplung
  • 10. Testing untestable code Keine Wiederverwendbarkeit
  • 11. Testing untestable code Nicht isolierbar, nicht testbar!
  • 12. Testing untestable code 3. Ungewissheit
  • 13. Testing untestable code "...our test strategy requires us to have more control [...] of the sut." Gerard Meszaros, xUnit Test Patterns: Refactoring Test Code
  • 14. Testing untestable code In einer perfekten Welt.. Unittest Unittest SUT SUT
  • 15. Testing untestable code Legacy code ist nicht perfekt... Abhängige Abhängige Klasse Klasse Unittest Unittest SUT SUT Abhängige Abhängige Klasse Klasse
  • 16. Testing untestable code ... Legacy code ist nicht perfekt... Abhängige Abhängige Klasse Klasse Unittest Unittest SUT SUT Abhängige Abhängige Klasse Klasse ...
  • 17. Testing untestable code ... Legacy code ist nicht perfekt... Abhängige Abhängige Klasse Klasse Unittest Unittest SUT SUT Abhängige Abhängige Klasse Klasse ...
  • 18. Testing untestable code Wie erzeugt man „testbaren Code“?
  • 19. Testing untestable code Wie erzeugt man „testbaren Code“? Refactoring
  • 20. Testing untestable code "Before you start refactoring, check that you have a solid suite of tests." Martin Fowler, Refactoring
  • 21. Testing untestable code Hoffnung? ...ist nicht genug
  • 22. Testing untestable code Wohin führt die Reise?
  • 23. Testing untestable code Wohin führt die Reise? Vorhandenen Code nicht ändern!
  • 24. Testing untestable code Beispiele Objekterzeugung Externe Ressourcen Sprachbarrieren
  • 25. Testing untestable code Objekterzeugung <?php class Car { private $engine; public function __construct($engine) { $this->engine = Engine::getByType($engine); } }
  • 26. Testing untestable code Objekterzeugung - Autoload <?php function run_autoload($class) { $fileToInclude = strtolower($class).'.php'; if(strtolower($class) == 'engine') { $fileToInclude = '/custom/mocks/'. $fileToInclude; } include($fileToInclude); } // Testcase spl_autoload_register('run_autoload'); $car = new Car('Diesel'); echo $car->run();
  • 27. Testing untestable code Objekterzeugung <?php include('Engine.php'); class Car { private $engine; public function __construct($engine) { $this->engine = Engine::getByType($engine); } }
  • 28. Testing untestable code Objekterzeugung - include_path <?php ini_set('include_path', '/custom/mocks/'.PATH_SEPARATOR. ini_get('include_path')); // Testcase include('car.php'); $car = new Car('Diesel'); echo $car->run();
  • 29. Testing untestable code Objekterzeugung – 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; } }
  • 30. Testing untestable code Objekterzeugung – Stream Wrapper stream_wrapper_unregister('file'); stream_wrapper_register('file', 'CustomWrapper');
  • 31. Testing untestable code Objekterzeugung – 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 ; } }
  • 32. Testing untestable code Objekterzeugung – Namespaces <?php class Car { private $engine; public function __construct($engine) { $this->engine = CarEngine:: getByType($engine); } }
  • 33. Testing untestable code Externe Ressourcen
  • 34. Testing untestable code Externe Ressourcen Datenbank Webservice Dateisystem Mailserver
  • 35. Testing untestable code Externe Ressourcen – Datenbank mocken
  • 36. Testing untestable code Externe Ressourcen – Datenbank mocken Eigene Implementierung anbieten
  • 37. Testing untestable code Externe Ressourcen – Datenbank mocken ZF Beispiel: $db = new Custom_Db_Adapter(array()); Zend_Db_Table::setDefaultAdapter($db);
  • 38. Testing untestable code Externe Ressourcen – Datenbank mocken PHPUnit_Extensions_Database_TestCase
  • 39. Testing untestable code Externe Ressourcen – Datenbank mocken Proxy for den SQL Server
  • 40. Testing untestable code Externe Ressourcen – Webservice mocken
  • 41. Testing untestable code Externe Ressourcen – Webservice mocken Eigene Implementierung anbieten
  • 42. Testing untestable code Externe Ressourcen – Webservice mocken Host Alias via /etc/hosts
  • 43. Testing untestable code Externe Ressourcen – Dateisytem mocken
  • 44. Testing untestable code Externe Ressourcen – Dateisystem mocken <?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');
  • 45. Testing untestable code Externe Ressourcen – Mailserver mocken
  • 46. Testing untestable code Externe Ressourcen – Mailserver mocken fake mail server verwenden
  • 47. Testing untestable code Externe Ressourcen – Mailserver mocken $ cat /etc/php5/php.ini | grep sendmail_path sendmail_path=/usr/local/bin/logmail $ cat /usr/local/bin/logmail cat >> /tmp/logmail.log
  • 48. Testing untestable code Sprachbarrieren
  • 49. Testing untestable code Sprachbarrieren private Methoden testen?
  • 50. Testing untestable code Sprachbarrieren <?php class CustomWrapper { private $_handler; function stream_read($count) { $content = fread($this->_handler, $count); $content = str_replace( 'private function', 'public function', $content ); return $content; }
  • 51. Testing untestable code Sprachbarrieren $myClass = new MyClass(); $reflectionClass = new ReflectionClass('MyClass'); $reflectionMethod = $reflectionClass-> getMethod('mydemo'); $reflectionMethod->setAccessible(true); $reflectionMethod->invoke($myClass);
  • 52. Testing untestable code Sprachbarrieren Interne Funktionen überschreiben?
  • 53. Testing untestable code Sprachbarrieren - Runkit pecl install runkit-0.9
  • 54. Testing untestable code Sprachbarrieren - Runkit <?php ini_set('runkit.internal_override', '1'); runkit_function_redefine('mail','','return true;'); ?>
  • 56. Testing untestable code Abstrahieren du sollst!
  • 57. Testing untestable code Was sonst? Generative Programmierung
  • 58. Testing untestable code Generative Programmierung Generator Generator
  • 59. Testing untestable code Generative Programmierung Konfiguration Konfiguration (DSL) (DSL) Generator Generator
  • 60. Software generieren statt programmieren Generative Programmierung Konfiguration Konfiguration (DSL) (DSL) Implementierungs- Implementierungs- komponenten Generator Generator komponenten
  • 61. Testing untestable code Generative Programmierung Konfiguration Konfiguration (DSL) (DSL) 1..n Implementierungs- Implementierungs- komponenten Generator Generator Produkt komponenten Produkt
  • 62. Testing untestable code Generative Programmierung Konfiguration Konfiguration (DSL) (DSL) Tests Tests Implementierungs- Implementierungs- komponenten Generator Generator Applikation komponenten Applikation
  • 63. Testing untestable code Generative Programmierung Ein Frame ist eine Datenstruktur die Wissen repräsentiert.
  • 64. Testing untestable code Eine Frame Instanz <?php class Car { private $engine; public function __construct($engine) { $this->engine = <!{Factory}!>:: getByType($engine); } }
  • 65. Testing untestable code Der 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"); } } }
  • 66. Testing untestable code Nach der Generierung - Testcase <?php class Car { private $engine; public function __construct($engine) { $this->engine = FactoryMock:: getByType($engine); } }
  • 67. Testing untestable code Nach der Generierung - Applikation <?php class Car { private $engine; public function __construct($engine) { $this->engine = EngineFactory:: getByType($engine); } }
  • 68. Testing untestable code Was ist möglich?
  • 69. Testing untestable code Was ist möglich? Extraktion von Codezeilen
  • 70. Testing untestable code Was ist möglich? Globale Inhalte verändern
  • 71. Testing untestable code Was ist möglich? Pre- oder Postfixes für Methoden
  • 72. Testing untestable code Wie weit sollte man gehen?
  • 74. Testing untestable code Bildquellen http://www.flickr.com/photos/andresrueda/3452940751/ http://www.flickr.com/photos/andresrueda/3455410635/