testing untestable code - phpconpl11
TRANSCRIPT
![Page 1: Testing untestable code - phpconpl11](https://reader033.vdocument.in/reader033/viewer/2022052822/554f80fcb4c905435d8b49ba/html5/thumbnails/1.jpg)
Testing untestable code
![Page 2: Testing untestable code - phpconpl11](https://reader033.vdocument.in/reader033/viewer/2022052822/554f80fcb4c905435d8b49ba/html5/thumbnails/2.jpg)
Testing untestable code
About me
Stephan Hochdörfer, bitExpert AG
Department Manager Research Labs
enjoying PHP since 1999
@shochdoerfer
![Page 3: Testing untestable code - phpconpl11](https://reader033.vdocument.in/reader033/viewer/2022052822/554f80fcb4c905435d8b49ba/html5/thumbnails/3.jpg)
Testing untestable code
No excuse for writing bad code!
![Page 4: Testing untestable code - phpconpl11](https://reader033.vdocument.in/reader033/viewer/2022052822/554f80fcb4c905435d8b49ba/html5/thumbnails/4.jpg)
Not to freak out!
Testing untestable code
![Page 5: Testing untestable code - phpconpl11](https://reader033.vdocument.in/reader033/viewer/2022052822/554f80fcb4c905435d8b49ba/html5/thumbnails/5.jpg)
Testing untestable code
Creativity matters!
![Page 6: Testing untestable code - phpconpl11](https://reader033.vdocument.in/reader033/viewer/2022052822/554f80fcb4c905435d8b49ba/html5/thumbnails/6.jpg)
Testing untestable code
"There is no secret to writing tests, there are only secrets to write
testable code!" Miško Hevery
![Page 7: Testing untestable code - phpconpl11](https://reader033.vdocument.in/reader033/viewer/2022052822/554f80fcb4c905435d8b49ba/html5/thumbnails/7.jpg)
What is „untestable Code“?
Testing untestable code
![Page 8: Testing untestable code - phpconpl11](https://reader033.vdocument.in/reader033/viewer/2022052822/554f80fcb4c905435d8b49ba/html5/thumbnails/8.jpg)
s
Testing untestable code
1. Wrong object construction
“new” is evil!
![Page 9: Testing untestable code - phpconpl11](https://reader033.vdocument.in/reader033/viewer/2022052822/554f80fcb4c905435d8b49ba/html5/thumbnails/9.jpg)
Testing untestable code
2. Tight coupling
![Page 10: Testing untestable code - phpconpl11](https://reader033.vdocument.in/reader033/viewer/2022052822/554f80fcb4c905435d8b49ba/html5/thumbnails/10.jpg)
No code reuse!
Testing untestable code
![Page 11: Testing untestable code - phpconpl11](https://reader033.vdocument.in/reader033/viewer/2022052822/554f80fcb4c905435d8b49ba/html5/thumbnails/11.jpg)
No isolation → not testable!
Testing untestable code
![Page 12: Testing untestable code - phpconpl11](https://reader033.vdocument.in/reader033/viewer/2022052822/554f80fcb4c905435d8b49ba/html5/thumbnails/12.jpg)
Testing untestable code
3. Uncertainty
![Page 13: Testing untestable code - phpconpl11](https://reader033.vdocument.in/reader033/viewer/2022052822/554f80fcb4c905435d8b49ba/html5/thumbnails/13.jpg)
Testing untestable code
"...our test strategy requires us to have more control [...] of the sut."
Gerard Meszaros, xUnit Test Patterns: Refactoring Test Code
![Page 14: Testing untestable code - phpconpl11](https://reader033.vdocument.in/reader033/viewer/2022052822/554f80fcb4c905435d8b49ba/html5/thumbnails/14.jpg)
Testing untestable code
SUTSUTUnittestUnittest
In a perfect world...
![Page 15: Testing untestable code - phpconpl11](https://reader033.vdocument.in/reader033/viewer/2022052822/554f80fcb4c905435d8b49ba/html5/thumbnails/15.jpg)
Testing untestable code
SUTSUTUnittestUnittest
Legacy code is not perfect...
DependencyDependency
DependencyDependency
![Page 16: Testing untestable code - phpconpl11](https://reader033.vdocument.in/reader033/viewer/2022052822/554f80fcb4c905435d8b49ba/html5/thumbnails/16.jpg)
Testing untestable code
SUTSUTUnittestUnittest
Legacy code is not perfect...
DependencyDependency
DependencyDependency
...
...
![Page 17: Testing untestable code - phpconpl11](https://reader033.vdocument.in/reader033/viewer/2022052822/554f80fcb4c905435d8b49ba/html5/thumbnails/17.jpg)
Testing untestable code
SUTSUTUnittestUnittest
Legacy code is not perfect...
DependencyDependency
DependencyDependency
...
...
![Page 18: Testing untestable code - phpconpl11](https://reader033.vdocument.in/reader033/viewer/2022052822/554f80fcb4c905435d8b49ba/html5/thumbnails/18.jpg)
Testing untestable code
How to get „testable“ code?
![Page 19: Testing untestable code - phpconpl11](https://reader033.vdocument.in/reader033/viewer/2022052822/554f80fcb4c905435d8b49ba/html5/thumbnails/19.jpg)
Testing untestable code
How to get „testable“ code?
Refactoring
![Page 20: Testing untestable code - phpconpl11](https://reader033.vdocument.in/reader033/viewer/2022052822/554f80fcb4c905435d8b49ba/html5/thumbnails/20.jpg)
Testing untestable code
"Before you start refactoring, check that you have a solid suite of tests."
Martin Fowler, Refactoring
![Page 21: Testing untestable code - phpconpl11](https://reader033.vdocument.in/reader033/viewer/2022052822/554f80fcb4c905435d8b49ba/html5/thumbnails/21.jpg)
Testing untestable code
Hope? - Nope...
![Page 22: Testing untestable code - phpconpl11](https://reader033.vdocument.in/reader033/viewer/2022052822/554f80fcb4c905435d8b49ba/html5/thumbnails/22.jpg)
Testing untestable code
Which path to take?
![Page 23: Testing untestable code - phpconpl11](https://reader033.vdocument.in/reader033/viewer/2022052822/554f80fcb4c905435d8b49ba/html5/thumbnails/23.jpg)
Testing untestable code
Which path to take?
Do not change existing code!
![Page 24: Testing untestable code - phpconpl11](https://reader033.vdocument.in/reader033/viewer/2022052822/554f80fcb4c905435d8b49ba/html5/thumbnails/24.jpg)
Testing untestable code
Examples
Object Construction External resources Language issues
![Page 25: Testing untestable code - phpconpl11](https://reader033.vdocument.in/reader033/viewer/2022052822/554f80fcb4c905435d8b49ba/html5/thumbnails/25.jpg)
Testing untestable code
Object construction
<?phpclass Car {
private $Engine;
public function __construct($sEngine) {$this->Engine = Engine::getByType($sEngine);
}
}
![Page 26: Testing untestable code - phpconpl11](https://reader033.vdocument.in/reader033/viewer/2022052822/554f80fcb4c905435d8b49ba/html5/thumbnails/26.jpg)
Testing untestable code
Object construction - Autoload<?phpfunction run_autoload($psClass) {
$sFileToInclude = strtolower($psClass).'.php';if(strtolower($psClass) == 'engine') {
$sFileToInclude = '/custom/mocks/'. $sFileToInclude;
}include($sFileToInclude);
}
// Testcasespl_autoload_register('run_autoload');$oCar = new Car('Diesel');
![Page 27: Testing untestable code - phpconpl11](https://reader033.vdocument.in/reader033/viewer/2022052822/554f80fcb4c905435d8b49ba/html5/thumbnails/27.jpg)
Testing untestable code
Object construction
<?phpinclude('Engine.php');
class Car {private $Engine;
public function __construct($sEngine) {$this->Engine = Engine::getByType($sEngine);
}}
![Page 28: Testing untestable code - phpconpl11](https://reader033.vdocument.in/reader033/viewer/2022052822/554f80fcb4c905435d8b49ba/html5/thumbnails/28.jpg)
Testing untestable code
Object construction - include_path
<?phpini_set('include_path',
'/custom/mocks/'.PATH_SEPARATOR.ini_get('include_path'));
// Testcaseinclude('car.php');
$oCar = new Car('Diesel');echo $oCar->run();
![Page 29: Testing untestable code - phpconpl11](https://reader033.vdocument.in/reader033/viewer/2022052822/554f80fcb4c905435d8b49ba/html5/thumbnails/29.jpg)
Testing untestable code
Object construction – Stream Wrapper
<?phpclass 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; }}
![Page 30: Testing untestable code - phpconpl11](https://reader033.vdocument.in/reader033/viewer/2022052822/554f80fcb4c905435d8b49ba/html5/thumbnails/30.jpg)
Testing untestable code
Object construction – Stream Wrapper
stream_wrapper_unregister('file');stream_wrapper_register('file', 'CustomWrapper');
![Page 31: Testing untestable code - phpconpl11](https://reader033.vdocument.in/reader033/viewer/2022052822/554f80fcb4c905435d8b49ba/html5/thumbnails/31.jpg)
Testing untestable code
Object construction – Stream Wrapper
<?phpclass CustomWrapper {
private $_handler;
function stream_read( $count) {$content = fread($this->_handler, $count);$content = str_replace ('Engine::getByType' ,
'AbstractEngine::get' , $content);return $content;
}}
![Page 32: Testing untestable code - phpconpl11](https://reader033.vdocument.in/reader033/viewer/2022052822/554f80fcb4c905435d8b49ba/html5/thumbnails/32.jpg)
Testing untestable code
Object construction – Namespaces
<?phpclass Car {
private $Engine;
public function __construct($sEngine) {$this->Engine = \Car\Engine::
getByType($sEngine);}
}
![Page 33: Testing untestable code - phpconpl11](https://reader033.vdocument.in/reader033/viewer/2022052822/554f80fcb4c905435d8b49ba/html5/thumbnails/33.jpg)
Testing untestable code
External resources
![Page 34: Testing untestable code - phpconpl11](https://reader033.vdocument.in/reader033/viewer/2022052822/554f80fcb4c905435d8b49ba/html5/thumbnails/34.jpg)
Testing untestable code
External resources
Database Webservice
Filesystem Mailserver
![Page 35: Testing untestable code - phpconpl11](https://reader033.vdocument.in/reader033/viewer/2022052822/554f80fcb4c905435d8b49ba/html5/thumbnails/35.jpg)
Testing untestable code
External resources – Mock database
![Page 36: Testing untestable code - phpconpl11](https://reader033.vdocument.in/reader033/viewer/2022052822/554f80fcb4c905435d8b49ba/html5/thumbnails/36.jpg)
Testing untestable code
External resources – Mock database
Provide own implementation
![Page 37: Testing untestable code - phpconpl11](https://reader033.vdocument.in/reader033/viewer/2022052822/554f80fcb4c905435d8b49ba/html5/thumbnails/37.jpg)
Testing untestable code
External resources – Mock database
ZF example:
$db = new Custom_Db_Adapter(array());Zend_Db_Table::setDefaultAdapter($db);
![Page 38: Testing untestable code - phpconpl11](https://reader033.vdocument.in/reader033/viewer/2022052822/554f80fcb4c905435d8b49ba/html5/thumbnails/38.jpg)
Testing untestable code
External resources – Mock database
PHPUnit_Extensions_Database_TestCase
![Page 39: Testing untestable code - phpconpl11](https://reader033.vdocument.in/reader033/viewer/2022052822/554f80fcb4c905435d8b49ba/html5/thumbnails/39.jpg)
Testing untestable code
External resources – Mock database
Proxy for your SQL Server
![Page 40: Testing untestable code - phpconpl11](https://reader033.vdocument.in/reader033/viewer/2022052822/554f80fcb4c905435d8b49ba/html5/thumbnails/40.jpg)
Testing untestable code
External resources – Mock webservice
![Page 41: Testing untestable code - phpconpl11](https://reader033.vdocument.in/reader033/viewer/2022052822/554f80fcb4c905435d8b49ba/html5/thumbnails/41.jpg)
Testing untestable code
External resources – Mock webservice
Provide own implementation
![Page 42: Testing untestable code - phpconpl11](https://reader033.vdocument.in/reader033/viewer/2022052822/554f80fcb4c905435d8b49ba/html5/thumbnails/42.jpg)
Testing untestable code
External resources – Mock webservice
Host redirect via /etc/hosts
![Page 43: Testing untestable code - phpconpl11](https://reader033.vdocument.in/reader033/viewer/2022052822/554f80fcb4c905435d8b49ba/html5/thumbnails/43.jpg)
Testing untestable code
External resources – Mock filesystem
![Page 44: Testing untestable code - phpconpl11](https://reader033.vdocument.in/reader033/viewer/2022052822/554f80fcb4c905435d8b49ba/html5/thumbnails/44.jpg)
Testing untestable code
External resources – Mock filesystem
<?php
// set up test environmemtvfsStream::setup('exampleDir');
// create directory in test enviromentmkdir(vfsStream::url('exampleDir').'/sample/');
// check if directory was createdecho vfsStreamWrapper::getRoot()->hasChild('sample');
![Page 45: Testing untestable code - phpconpl11](https://reader033.vdocument.in/reader033/viewer/2022052822/554f80fcb4c905435d8b49ba/html5/thumbnails/45.jpg)
Testing untestable code
External resources – Mock Mailserver
![Page 46: Testing untestable code - phpconpl11](https://reader033.vdocument.in/reader033/viewer/2022052822/554f80fcb4c905435d8b49ba/html5/thumbnails/46.jpg)
Testing untestable code
External resources – Mock Mailserver
Use fake mail server
![Page 47: Testing untestable code - phpconpl11](https://reader033.vdocument.in/reader033/viewer/2022052822/554f80fcb4c905435d8b49ba/html5/thumbnails/47.jpg)
Testing untestable code
External resources – Mock Mailserver
$ cat /etc/php5/php.ini | grep sendmail_pathsendmail_path=/usr/local/bin/logmail
$ cat /usr/local/bin/logmailcat >> /tmp/logmail.log
![Page 48: Testing untestable code - phpconpl11](https://reader033.vdocument.in/reader033/viewer/2022052822/554f80fcb4c905435d8b49ba/html5/thumbnails/48.jpg)
Testing untestable code
Dealing with language issues
![Page 49: Testing untestable code - phpconpl11](https://reader033.vdocument.in/reader033/viewer/2022052822/554f80fcb4c905435d8b49ba/html5/thumbnails/49.jpg)
Testing untestable code
Dealing with language issues
Testing your privates?
![Page 50: Testing untestable code - phpconpl11](https://reader033.vdocument.in/reader033/viewer/2022052822/554f80fcb4c905435d8b49ba/html5/thumbnails/50.jpg)
Testing untestable code
Dealing with language issues
<?phpclass CustomWrapper {
private $_handler;
function stream_read($count) {$content = fread($this->_handler, $count);$content = str_replace(
'private function', 'public function', $content );
return $content;}
![Page 51: Testing untestable code - phpconpl11](https://reader033.vdocument.in/reader033/viewer/2022052822/554f80fcb4c905435d8b49ba/html5/thumbnails/51.jpg)
Testing untestable code
Dealing with language issues
$myClass = new MyClass();
$reflectionClass = new ReflectionClass('MyClass');$reflectionMethod = $reflectionClass->
getMethod('mydemo');$reflectionMethod->setAccessible(true);$reflectionMethod->invoke($myClass);
![Page 52: Testing untestable code - phpconpl11](https://reader033.vdocument.in/reader033/viewer/2022052822/554f80fcb4c905435d8b49ba/html5/thumbnails/52.jpg)
Testing untestable code
Dealing with language issues
Overwrite internal functions?
![Page 53: Testing untestable code - phpconpl11](https://reader033.vdocument.in/reader033/viewer/2022052822/554f80fcb4c905435d8b49ba/html5/thumbnails/53.jpg)
Testing untestable code
Dealing with language issues
pecl install runkit-0.9
![Page 54: Testing untestable code - phpconpl11](https://reader033.vdocument.in/reader033/viewer/2022052822/554f80fcb4c905435d8b49ba/html5/thumbnails/54.jpg)
Testing untestable code
Dealing with language issues - Runkit
<?php
ini_set('runkit.internal_override', '1');
runkit_function_redefine('mail','','returntrue;');
?>
![Page 55: Testing untestable code - phpconpl11](https://reader033.vdocument.in/reader033/viewer/2022052822/554f80fcb4c905435d8b49ba/html5/thumbnails/55.jpg)
Testing untestable code
Dealing with language issues
pecl install funcall-0.3.0alpha
![Page 56: Testing untestable code - phpconpl11](https://reader033.vdocument.in/reader033/viewer/2022052822/554f80fcb4c905435d8b49ba/html5/thumbnails/56.jpg)
Testing untestable code
Dealing with language issues - Funcall
<?phpfunction 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'));
![Page 57: Testing untestable code - phpconpl11](https://reader033.vdocument.in/reader033/viewer/2022052822/554f80fcb4c905435d8b49ba/html5/thumbnails/57.jpg)
Testing untestable code
What else?
![Page 58: Testing untestable code - phpconpl11](https://reader033.vdocument.in/reader033/viewer/2022052822/554f80fcb4c905435d8b49ba/html5/thumbnails/58.jpg)
What else?
Testing untestable code
Generative Programming
![Page 59: Testing untestable code - phpconpl11](https://reader033.vdocument.in/reader033/viewer/2022052822/554f80fcb4c905435d8b49ba/html5/thumbnails/59.jpg)
Testing untestable code
Generative Programming
ConfigurationConfiguration
Implementationcomponents
Implementationcomponents
Generatorapplication
Generatorapplication
ProductProductGeneratorGenerator
1 ... n
![Page 60: Testing untestable code - phpconpl11](https://reader033.vdocument.in/reader033/viewer/2022052822/554f80fcb4c905435d8b49ba/html5/thumbnails/60.jpg)
Testing untestable code
Generative Programming
ConfigurationConfiguration
Implementationcomponents
Implementationcomponents
Generatorapplication
Generatorapplication
GeneratorGenerator
ApplicationApplication
TestcasesTestcases
![Page 61: Testing untestable code - phpconpl11](https://reader033.vdocument.in/reader033/viewer/2022052822/554f80fcb4c905435d8b49ba/html5/thumbnails/61.jpg)
Testing untestable code
Generative Programming
A frame is a data structure for representing knowledge.
![Page 62: Testing untestable code - phpconpl11](https://reader033.vdocument.in/reader033/viewer/2022052822/554f80fcb4c905435d8b49ba/html5/thumbnails/62.jpg)
Testing untestable code
A Frame instance
<?phpclass Car {
private $Engine;
public function __construct($sEngine) {$this->Engine = <!{Factory}!>::
getByType($sEngine);}
}
![Page 63: Testing untestable code - phpconpl11](https://reader033.vdocument.in/reader033/viewer/2022052822/554f80fcb4c905435d8b49ba/html5/thumbnails/63.jpg)
Testing untestable code
The Frame controller
public class MyFrameController extendsSimpleFrameController {
public void execute(Frame frame, FeatureConfigconfig) {
if(config.hasFeature("unittest")) { frame.setSlot("Factory", "FactoryMock");}else { frame.setSlot("Factory", "EngineFactory");}
}}
![Page 64: Testing untestable code - phpconpl11](https://reader033.vdocument.in/reader033/viewer/2022052822/554f80fcb4c905435d8b49ba/html5/thumbnails/64.jpg)
Testing untestable code
Generated result - Testcase
<?phpclass Car {
private $Engine;
public function __construct($sEngine) {$this->Engine = FactoryMock::
getByType($sEngine);}
}
![Page 65: Testing untestable code - phpconpl11](https://reader033.vdocument.in/reader033/viewer/2022052822/554f80fcb4c905435d8b49ba/html5/thumbnails/65.jpg)
Testing untestable code
Generated result - Application
<?phpclass Car {
private $Engine;
public function __construct($sEngine) {$this->Engine = EngineFactory::
getByType($sEngine);}
}
![Page 66: Testing untestable code - phpconpl11](https://reader033.vdocument.in/reader033/viewer/2022052822/554f80fcb4c905435d8b49ba/html5/thumbnails/66.jpg)
Testing untestable code
What is possible?
![Page 67: Testing untestable code - phpconpl11](https://reader033.vdocument.in/reader033/viewer/2022052822/554f80fcb4c905435d8b49ba/html5/thumbnails/67.jpg)
Testing untestable code
What is possible?
Show / hide parts of the code
![Page 68: Testing untestable code - phpconpl11](https://reader033.vdocument.in/reader033/viewer/2022052822/554f80fcb4c905435d8b49ba/html5/thumbnails/68.jpg)
Testing untestable code
What is possible?
Change content of global vars!
![Page 69: Testing untestable code - phpconpl11](https://reader033.vdocument.in/reader033/viewer/2022052822/554f80fcb4c905435d8b49ba/html5/thumbnails/69.jpg)
Testing untestable code
What is possible?
Define pre- or postfixes!
![Page 70: Testing untestable code - phpconpl11](https://reader033.vdocument.in/reader033/viewer/2022052822/554f80fcb4c905435d8b49ba/html5/thumbnails/70.jpg)
Testing untestable code
Is it worth it?
![Page 71: Testing untestable code - phpconpl11](https://reader033.vdocument.in/reader033/viewer/2022052822/554f80fcb4c905435d8b49ba/html5/thumbnails/71.jpg)
Testing untestable code
Conclusions
Change your mindset to write testable code!
![Page 72: Testing untestable code - phpconpl11](https://reader033.vdocument.in/reader033/viewer/2022052822/554f80fcb4c905435d8b49ba/html5/thumbnails/72.jpg)
Testing untestable code
Conclusions
PHP is a swiss-army knife. Use it that way!
![Page 73: Testing untestable code - phpconpl11](https://reader033.vdocument.in/reader033/viewer/2022052822/554f80fcb4c905435d8b49ba/html5/thumbnails/73.jpg)
http://joind.in/3922
![Page 74: Testing untestable code - phpconpl11](https://reader033.vdocument.in/reader033/viewer/2022052822/554f80fcb4c905435d8b49ba/html5/thumbnails/74.jpg)
Testing untestable code
Bildquellen
http://www.flickr.com/photos/andresrueda/3452940751/
http://www.flickr.com/photos/andresrueda/3455410635/