Testing untestable code
 Stephan Hochdörfer, bitExpert AG
Testing untestable code

 About me

  Stephan Hochdörfer, bitExpert AG

  Department Manager Research Labs

  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


 public class Car {
    private Engine engine;

     public Car(String engine) {
        this.engine = EngineFactory.getByType(engine);
     }
 }
Testing untestable code

 Object construction - Solution
 public class MyLoader extends ClassLoader {
    protected Class findClass(String name)
       throws ClassNotFoundException
    {
       try {
          String path = name.replace('.', '/');
          // @TODO: change path and read file,
          // @TODO: define package
          // @TODO: define class
       }
       catch(Exception e){
          throw new ClassNotFoundException(name);
       }
    }
 }
Testing untestable code

 Object construction - Solution II
 <?php
 class MyStreamWrapper {
   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', 'MyStreamWrapper');
         return true;
     }
 }
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 db driver
Testing untestable code

 External resources – Mock database




                      junit + dbunit
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



                     Do not forget!

           Url redirection via /etc/hosts
Testing untestable code

 External resources – Mock filesystem
Testing untestable code

 External resources – Mock filesystem



                    Commons-VFS

                          vfsStream
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

 Dealing with language issues
Testing untestable code

 Dealing with language issues




             Testing your privates?
Testing untestable code

 Dealing with language issues
 final Method methods[] =
 o.getClass().getDeclaredMethods();
 for (int i = 0; i < methods.length; ++i) {
    if (methodName.equals(methods[i].getName())) {
       try {
          methods[i].setAccessible(true);
          return methods[i].invoke(o, params);
       }
       catch (IllegalAccessException ex) {
       }
       catch (InvocationTargetException ite) {
       }
    }
    return null;
 }
Testing untestable code

 Dealing with language issues




       Overwrite internal functions?
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


 public class Car {
    private Engine engine;

     public Car(String engine) {
        this.engine = <!{Factory}!>.getByType(engine);
     }
 }
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


 public class Car {
    private Engine engine;

     public Car(String engine) {
        this.engine = FactoryMock.getByType(engine);
     }
 }
Testing untestable code

 Generated result - Application


 public class Car {
    private Engine engine;

     public Car(String engine) {
        this.engine = EngineFactory.getByType(engine);
     }
 }
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?
Thank you for attending this session.




 Please fill out an evaluation form.

Testing untestable code - STPCon11