Testing untestable code - oscon 2012
Upcoming SlideShare
Loading in...5
×
 

Testing untestable code - oscon 2012

on

  • 1,160 views

 

Statistics

Views

Total Views
1,160
Views on SlideShare
1,138
Embed Views
22

Actions

Likes
2
Downloads
4
Comments
0

1 Embed 22

http://lanyrd.com 22

Accessibility

Categories

Upload Details

Uploaded via as Adobe PDF

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

Testing untestable code - oscon 2012 Testing untestable code - oscon 2012 Presentation Transcript

  • Testing untestable codeStephan 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 "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 "...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 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); echo $oCar­>run();
  • 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,        AbstractEngine::get, $content); return $content; } }
  • 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 databasePHPUnit_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 Dealing with language issues pecl install funcall-0.3.0alpha
  • Testing untestable code Dealing with language issues - Funcall <?php function my_func($arg1, $arg2) {     return $arg1.$arg2; } function post_cb($args,$result, $process_time) {   // return custom result based on  $args } fc_add_post(my_func,post_cb); var_dump(my_func(php, c));
  • Testing untestable code Dealing with language issues funcall for methods?
  • Testing untestable code Dealing with language issues git clone https://github/juliens/AOP
  • Testing untestable code Dealing with language issues - AOP <?php aop_add_after(Car::drive*,  adviceForDrive);
  • Testing untestable code Dealing with language issues - AOP <?php $advice = function(AopTriggeredJoinpoint $jp) {   $returnValue =       $jp­>getReturnedValue();   // modify the return value   $returnValue = 1234;   $jp­>setReturnedValue($returnValue); }; aop_add_after(Car­>drive(), $advice);
  • Testing untestable code What else? Generative Programming
  • Testing untestable code Generative Programming Configuration Configuration (DSL) (DSL) 1..n Implementation- Implementation- components Generator Generator Product components Product
  • Testing untestable code Generative Programming Configuration Configuration (DSL) (DSL) Customer 22 Customer Implementation- Implementation- components Generator Generator Customer 11 components Customer
  • Testing untestable code Generative Programming Configuration Configuration (DSL) (DSL) Test Test Enviroment Enviroment Implementation- Implementation- components Generator Generator Prod. Prod. components Enviroment Enviroment
  • Testing untestable code Generative Programming A frame is a data structure for representing knowledge.
  • Testing untestable code Frame <?php class Car { private $Engine; public function __construct($sEngine) { $this­>Engine = <!{Factory}!>:: getByType($sEngine); } }
  • Testing untestable code ContentProvider for the Frame public class MyContentProvider extends     AbstractContentProvider {     public SlotConfiguration computeSlots(         FeatureConfiguration config) {         SlotConfiguration sl = new SlotConfiguration();         if(config.hasFeature("unittest")) {             sl.put("Factory", "FactoryMock");         } else {             sl.put("Factory", "EngineFactory");         }         return sl;     } }
  • Testing untestable code Generated result – Test Enviroment <?php class Car { private $Engine; public function __construct($sEngine) { $this­>Engine = FactoryMock:: getByType($sEngine); } }
  • Testing untestable code Generated result – Prod. Enviroment <?php class Car { private $Engine; public function __construct($sEngine) { $this­>Engine = EngineFactory:: getByType($sEngine); } }
  • Testing untestable code Curious for more? http://replicatorframework.org
  • Thank you!
  • Please rate: http://bit.ly/ML0alS