testing untestable code - confoo13
DESCRIPTION
TRANSCRIPT
![Page 1: Testing untestable code - ConFoo13](https://reader033.vdocument.in/reader033/viewer/2022051818/54b4fd414a7959b9428b4811/html5/thumbnails/1.jpg)
Testing untestable codeStephan Hochdörfer, bitExpert AG
![Page 2: Testing untestable code - ConFoo13](https://reader033.vdocument.in/reader033/viewer/2022051818/54b4fd414a7959b9428b4811/html5/thumbnails/2.jpg)
Testing untestable code
About me
Stephan Hochdörfer
Head of IT at bitExpert AG, Germany
enjoying PHP since 1999
@shochdoerfer
![Page 3: Testing untestable code - ConFoo13](https://reader033.vdocument.in/reader033/viewer/2022051818/54b4fd414a7959b9428b4811/html5/thumbnails/3.jpg)
Testing untestable code
No excuse for writing bad code!
![Page 4: Testing untestable code - ConFoo13](https://reader033.vdocument.in/reader033/viewer/2022051818/54b4fd414a7959b9428b4811/html5/thumbnails/4.jpg)
![Page 5: Testing untestable code - ConFoo13](https://reader033.vdocument.in/reader033/viewer/2022051818/54b4fd414a7959b9428b4811/html5/thumbnails/5.jpg)
![Page 6: Testing untestable code - ConFoo13](https://reader033.vdocument.in/reader033/viewer/2022051818/54b4fd414a7959b9428b4811/html5/thumbnails/6.jpg)
Testing untestable code
"Hang the rules. They're more like guidelines anyway."
Elizabeth Swann, Pirates of the Caribbean
![Page 7: Testing untestable code - ConFoo13](https://reader033.vdocument.in/reader033/viewer/2022051818/54b4fd414a7959b9428b4811/html5/thumbnails/7.jpg)
Testing untestable code
"There is no secret to writing tests, there are only secrets to write
testable code!" Miško Hevery
![Page 8: Testing untestable code - ConFoo13](https://reader033.vdocument.in/reader033/viewer/2022051818/54b4fd414a7959b9428b4811/html5/thumbnails/8.jpg)
What is „untestable code“?
Testing untestable code
![Page 9: Testing untestable code - ConFoo13](https://reader033.vdocument.in/reader033/viewer/2022051818/54b4fd414a7959b9428b4811/html5/thumbnails/9.jpg)
![Page 10: Testing untestable code - ConFoo13](https://reader033.vdocument.in/reader033/viewer/2022051818/54b4fd414a7959b9428b4811/html5/thumbnails/10.jpg)
![Page 11: Testing untestable code - ConFoo13](https://reader033.vdocument.in/reader033/viewer/2022051818/54b4fd414a7959b9428b4811/html5/thumbnails/11.jpg)
![Page 12: Testing untestable code - ConFoo13](https://reader033.vdocument.in/reader033/viewer/2022051818/54b4fd414a7959b9428b4811/html5/thumbnails/12.jpg)
![Page 13: Testing untestable code - ConFoo13](https://reader033.vdocument.in/reader033/viewer/2022051818/54b4fd414a7959b9428b4811/html5/thumbnails/13.jpg)
![Page 14: Testing untestable code - ConFoo13](https://reader033.vdocument.in/reader033/viewer/2022051818/54b4fd414a7959b9428b4811/html5/thumbnails/14.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 15: Testing untestable code - ConFoo13](https://reader033.vdocument.in/reader033/viewer/2022051818/54b4fd414a7959b9428b4811/html5/thumbnails/15.jpg)
Testing untestable code
SUTSUTUnittestUnittest
In a perfect world...
![Page 16: Testing untestable code - ConFoo13](https://reader033.vdocument.in/reader033/viewer/2022051818/54b4fd414a7959b9428b4811/html5/thumbnails/16.jpg)
Testing untestable code
SUTSUTUnittestUnittest
Legacy code is not perfect...
DependencyDependency
DependencyDependency
![Page 17: Testing untestable code - ConFoo13](https://reader033.vdocument.in/reader033/viewer/2022051818/54b4fd414a7959b9428b4811/html5/thumbnails/17.jpg)
Testing untestable code
SUTSUTUnittestUnittest
Legacy code is not perfect...
DependencyDependency
DependencyDependency
...
...
![Page 18: Testing untestable code - ConFoo13](https://reader033.vdocument.in/reader033/viewer/2022051818/54b4fd414a7959b9428b4811/html5/thumbnails/18.jpg)
Testing untestable code
SUTSUTUnittestUnittest
Legacy code is not perfect...
DependencyDependency
DependencyDependency
...
...
![Page 19: Testing untestable code - ConFoo13](https://reader033.vdocument.in/reader033/viewer/2022051818/54b4fd414a7959b9428b4811/html5/thumbnails/19.jpg)
Testing untestable code
How to get „testable“ code?
![Page 20: Testing untestable code - ConFoo13](https://reader033.vdocument.in/reader033/viewer/2022051818/54b4fd414a7959b9428b4811/html5/thumbnails/20.jpg)
Testing untestable code
How to get „testable“ code?
Refactoring
![Page 21: Testing untestable code - ConFoo13](https://reader033.vdocument.in/reader033/viewer/2022051818/54b4fd414a7959b9428b4811/html5/thumbnails/21.jpg)
Testing untestable code
"Before you start refactoring, check that you have a solid suite of
tests."Martin Fowler, Refactoring
![Page 22: Testing untestable code - ConFoo13](https://reader033.vdocument.in/reader033/viewer/2022051818/54b4fd414a7959b9428b4811/html5/thumbnails/22.jpg)
![Page 23: Testing untestable code - ConFoo13](https://reader033.vdocument.in/reader033/viewer/2022051818/54b4fd414a7959b9428b4811/html5/thumbnails/23.jpg)
Testing untestable code
Which path to take?
![Page 24: Testing untestable code - ConFoo13](https://reader033.vdocument.in/reader033/viewer/2022051818/54b4fd414a7959b9428b4811/html5/thumbnails/24.jpg)
Testing untestable code
Which path to take?
Do not change existing code!
![Page 25: Testing untestable code - ConFoo13](https://reader033.vdocument.in/reader033/viewer/2022051818/54b4fd414a7959b9428b4811/html5/thumbnails/25.jpg)
Testing untestable code
Examples
Object Construction External resources Language issues
![Page 26: Testing untestable code - ConFoo13](https://reader033.vdocument.in/reader033/viewer/2022051818/54b4fd414a7959b9428b4811/html5/thumbnails/26.jpg)
Testing untestable code
Object construction<?phpclass Car {
private $Engine;
public function __construct($sEngine) {$this>Engine = Engine::getByType($sEngine);
}
}
![Page 27: Testing untestable code - ConFoo13](https://reader033.vdocument.in/reader033/viewer/2022051818/54b4fd414a7959b9428b4811/html5/thumbnails/27.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');echo $oCar>run();
![Page 28: Testing untestable code - ConFoo13](https://reader033.vdocument.in/reader033/viewer/2022051818/54b4fd414a7959b9428b4811/html5/thumbnails/28.jpg)
Testing untestable code
Object construction<?phpinclude('Engine.php');
class Car {private $Engine;
public function __construct($sEngine) {$this>Engine = Engine::getByType($sEngine);
}}
![Page 29: Testing untestable code - ConFoo13](https://reader033.vdocument.in/reader033/viewer/2022051818/54b4fd414a7959b9428b4811/html5/thumbnails/29.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 30: Testing untestable code - ConFoo13](https://reader033.vdocument.in/reader033/viewer/2022051818/54b4fd414a7959b9428b4811/html5/thumbnails/30.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 31: Testing untestable code - ConFoo13](https://reader033.vdocument.in/reader033/viewer/2022051818/54b4fd414a7959b9428b4811/html5/thumbnails/31.jpg)
Testing untestable code
Object construction – Stream Wrapperstream_wrapper_unregister('file');stream_wrapper_register('file', 'CustomWrapper');
![Page 32: Testing untestable code - ConFoo13](https://reader033.vdocument.in/reader033/viewer/2022051818/54b4fd414a7959b9428b4811/html5/thumbnails/32.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 33: Testing untestable code - ConFoo13](https://reader033.vdocument.in/reader033/viewer/2022051818/54b4fd414a7959b9428b4811/html5/thumbnails/33.jpg)
Testing untestable code
External resources
![Page 34: Testing untestable code - ConFoo13](https://reader033.vdocument.in/reader033/viewer/2022051818/54b4fd414a7959b9428b4811/html5/thumbnails/34.jpg)
Testing untestable code
External resources
Database Webservice
Filesystem Mailserver
![Page 35: Testing untestable code - ConFoo13](https://reader033.vdocument.in/reader033/viewer/2022051818/54b4fd414a7959b9428b4811/html5/thumbnails/35.jpg)
Testing untestable code
External resources – Mock database
![Page 36: Testing untestable code - ConFoo13](https://reader033.vdocument.in/reader033/viewer/2022051818/54b4fd414a7959b9428b4811/html5/thumbnails/36.jpg)
Testing untestable code
External resources – Mock database
Provide own implementation
![Page 37: Testing untestable code - ConFoo13](https://reader033.vdocument.in/reader033/viewer/2022051818/54b4fd414a7959b9428b4811/html5/thumbnails/37.jpg)
Testing untestable code
External resources – Mock database
ZF1 example:$db = new Custom_Db_Adapter(array());Zend_Db_Table::setDefaultAdapter($db);
![Page 38: Testing untestable code - ConFoo13](https://reader033.vdocument.in/reader033/viewer/2022051818/54b4fd414a7959b9428b4811/html5/thumbnails/38.jpg)
Testing untestable code
External resources – Mock database
PHPUnit_Extensions_Database_TestCase
![Page 39: Testing untestable code - ConFoo13](https://reader033.vdocument.in/reader033/viewer/2022051818/54b4fd414a7959b9428b4811/html5/thumbnails/39.jpg)
Testing untestable code
External resources – Mock databaserequire_once "PHPUnit/Extensions/Database/TestCase.php";
class MySampleTest extends PHPUnit_Extensions_Database_TestCase{ public function getConnection() { $pdo = new PDO('sqlite::memory:'); return $this>createDefaultDBConnection
$pdo, ':memory:'); }
public function getDataSet() { return $this>createFlatXMLDataSet(
dirname(__FILE__).'/_files/data.xml' );
}}
![Page 40: Testing untestable code - ConFoo13](https://reader033.vdocument.in/reader033/viewer/2022051818/54b4fd414a7959b9428b4811/html5/thumbnails/40.jpg)
Testing untestable code
External resources – Mock database
Proxy for your SQL Server
![Page 41: Testing untestable code - ConFoo13](https://reader033.vdocument.in/reader033/viewer/2022051818/54b4fd414a7959b9428b4811/html5/thumbnails/41.jpg)
Testing untestable code
External resources – Mock webservice
![Page 42: Testing untestable code - ConFoo13](https://reader033.vdocument.in/reader033/viewer/2022051818/54b4fd414a7959b9428b4811/html5/thumbnails/42.jpg)
Testing untestable code
External resources – Mock webservice
Provide own implementation
![Page 43: Testing untestable code - ConFoo13](https://reader033.vdocument.in/reader033/viewer/2022051818/54b4fd414a7959b9428b4811/html5/thumbnails/43.jpg)
Testing untestable code
External resources – Mock webservice
Host redirect via /etc/hosts
![Page 44: Testing untestable code - ConFoo13](https://reader033.vdocument.in/reader033/viewer/2022051818/54b4fd414a7959b9428b4811/html5/thumbnails/44.jpg)
Testing untestable code
External resources – Mock filesystem
![Page 45: Testing untestable code - ConFoo13](https://reader033.vdocument.in/reader033/viewer/2022051818/54b4fd414a7959b9428b4811/html5/thumbnails/45.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 46: Testing untestable code - ConFoo13](https://reader033.vdocument.in/reader033/viewer/2022051818/54b4fd414a7959b9428b4811/html5/thumbnails/46.jpg)
Testing untestable code
External resources – Mock Mailserver
![Page 47: Testing untestable code - ConFoo13](https://reader033.vdocument.in/reader033/viewer/2022051818/54b4fd414a7959b9428b4811/html5/thumbnails/47.jpg)
Testing untestable code
External resources – Mock Mailserver
Use fake mail server
![Page 48: Testing untestable code - ConFoo13](https://reader033.vdocument.in/reader033/viewer/2022051818/54b4fd414a7959b9428b4811/html5/thumbnails/48.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 49: Testing untestable code - ConFoo13](https://reader033.vdocument.in/reader033/viewer/2022051818/54b4fd414a7959b9428b4811/html5/thumbnails/49.jpg)
Testing untestable code
Dealing with language issues
![Page 50: Testing untestable code - ConFoo13](https://reader033.vdocument.in/reader033/viewer/2022051818/54b4fd414a7959b9428b4811/html5/thumbnails/50.jpg)
Testing untestable code
Dealing with language issues
Testing your privates?
![Page 51: Testing untestable code - ConFoo13](https://reader033.vdocument.in/reader033/viewer/2022051818/54b4fd414a7959b9428b4811/html5/thumbnails/51.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 52: Testing untestable code - ConFoo13](https://reader033.vdocument.in/reader033/viewer/2022051818/54b4fd414a7959b9428b4811/html5/thumbnails/52.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 53: Testing untestable code - ConFoo13](https://reader033.vdocument.in/reader033/viewer/2022051818/54b4fd414a7959b9428b4811/html5/thumbnails/53.jpg)
Testing untestable code
Dealing with language issues
Overwrite internal functions?
![Page 54: Testing untestable code - ConFoo13](https://reader033.vdocument.in/reader033/viewer/2022051818/54b4fd414a7959b9428b4811/html5/thumbnails/54.jpg)
Testing untestable code
Dealing with language issues
pecl install runkit-0.9
![Page 55: Testing untestable code - ConFoo13](https://reader033.vdocument.in/reader033/viewer/2022051818/54b4fd414a7959b9428b4811/html5/thumbnails/55.jpg)
Testing untestable code
Dealing with language issues - Runkit<?php
ini_set('runkit.internal_override', '1');
runkit_function_redefine('mail','','return true;');
?>
![Page 56: Testing untestable code - ConFoo13](https://reader033.vdocument.in/reader033/viewer/2022051818/54b4fd414a7959b9428b4811/html5/thumbnails/56.jpg)
Testing untestable code
Dealing with language issues
pecl install funcall-0.3.0alpha
![Page 57: Testing untestable code - ConFoo13](https://reader033.vdocument.in/reader033/viewer/2022051818/54b4fd414a7959b9428b4811/html5/thumbnails/57.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 58: Testing untestable code - ConFoo13](https://reader033.vdocument.in/reader033/viewer/2022051818/54b4fd414a7959b9428b4811/html5/thumbnails/58.jpg)
Testing untestable code
Dealing with language issues
funcall for methods?
![Page 59: Testing untestable code - ConFoo13](https://reader033.vdocument.in/reader033/viewer/2022051818/54b4fd414a7959b9428b4811/html5/thumbnails/59.jpg)
Testing untestable code
Dealing with language issues
git clone https://github/juliens/AOP
![Page 60: Testing untestable code - ConFoo13](https://reader033.vdocument.in/reader033/viewer/2022051818/54b4fd414a7959b9428b4811/html5/thumbnails/60.jpg)
Testing untestable code
Dealing with language issues - AOP
<?php
aop_add_after('Car::drive*', 'adviceForDrive');
![Page 61: Testing untestable code - ConFoo13](https://reader033.vdocument.in/reader033/viewer/2022051818/54b4fd414a7959b9428b4811/html5/thumbnails/61.jpg)
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);
![Page 62: Testing untestable code - ConFoo13](https://reader033.vdocument.in/reader033/viewer/2022051818/54b4fd414a7959b9428b4811/html5/thumbnails/62.jpg)
<?php$all_tables_query = ' SELECT table_name, MAX(version) asversion FROM ...';$all_tables_result = PMA_query_as_controluser($all_tables_query);
// If a HEAD version existsif (PMA_DBI_num_rows($all_tables_result) > 0) {?> <div id="tracked_tables"> <h3><?php echo __('Tracked tables');?></h3><?php}
Testing untestable code
And now? Spaghetti mess...
![Page 63: Testing untestable code - ConFoo13](https://reader033.vdocument.in/reader033/viewer/2022051818/54b4fd414a7959b9428b4811/html5/thumbnails/63.jpg)
![Page 64: Testing untestable code - ConFoo13](https://reader033.vdocument.in/reader033/viewer/2022051818/54b4fd414a7959b9428b4811/html5/thumbnails/64.jpg)
![Page 65: Testing untestable code - ConFoo13](https://reader033.vdocument.in/reader033/viewer/2022051818/54b4fd414a7959b9428b4811/html5/thumbnails/65.jpg)
What else?
Testing untestable code
Generative Programming
![Page 66: Testing untestable code - ConFoo13](https://reader033.vdocument.in/reader033/viewer/2022051818/54b4fd414a7959b9428b4811/html5/thumbnails/66.jpg)
Testing untestable code
Generative Programming
Configuration(DSL)
Configuration(DSL)
Implementation-components
Implementation-components GeneratorGenerator
ProductProduct
1..n
![Page 67: Testing untestable code - ConFoo13](https://reader033.vdocument.in/reader033/viewer/2022051818/54b4fd414a7959b9428b4811/html5/thumbnails/67.jpg)
Testing untestable code
Generative Programming
Configuration(DSL)
Configuration(DSL)
Implementation-components
Implementation-components GeneratorGenerator
Customer 1Customer 1
Customer 2Customer 2
![Page 68: Testing untestable code - ConFoo13](https://reader033.vdocument.in/reader033/viewer/2022051818/54b4fd414a7959b9428b4811/html5/thumbnails/68.jpg)
Testing untestable code
Generative Programming
Configuration(DSL)
Configuration(DSL)
Implementation-components
Implementation-components GeneratorGenerator Prod.
Enviroment
Prod.Enviroment
TestEnviroment
TestEnviroment
![Page 69: Testing untestable code - ConFoo13](https://reader033.vdocument.in/reader033/viewer/2022051818/54b4fd414a7959b9428b4811/html5/thumbnails/69.jpg)
Testing untestable code
Generative Programming
A frame is a data structure for representing knowledge.
![Page 70: Testing untestable code - ConFoo13](https://reader033.vdocument.in/reader033/viewer/2022051818/54b4fd414a7959b9428b4811/html5/thumbnails/70.jpg)
Testing untestable code
Frame<?phpclass Car {
private $Engine;
public function __construct($sEngine) {$this>Engine = <!{Factory}!>::
getByType($sEngine);}
}
![Page 71: Testing untestable code - ConFoo13](https://reader033.vdocument.in/reader033/viewer/2022051818/54b4fd414a7959b9428b4811/html5/thumbnails/71.jpg)
Testing untestable code
ContentProvider for the Framepublic 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; }}
![Page 72: Testing untestable code - ConFoo13](https://reader033.vdocument.in/reader033/viewer/2022051818/54b4fd414a7959b9428b4811/html5/thumbnails/72.jpg)
Testing untestable code
Generated result – Test Enviroment<?phpclass Car {
private $Engine;
public function __construct($sEngine) {$this>Engine = FactoryMock::
getByType($sEngine);}
}
![Page 73: Testing untestable code - ConFoo13](https://reader033.vdocument.in/reader033/viewer/2022051818/54b4fd414a7959b9428b4811/html5/thumbnails/73.jpg)
Testing untestable code
Generated result – Prod. Enviroment<?phpclass Car {
private $Engine;
public function __construct($sEngine) {$this>Engine = EngineFactory::
getByType($sEngine);}
}
![Page 74: Testing untestable code - ConFoo13](https://reader033.vdocument.in/reader033/viewer/2022051818/54b4fd414a7959b9428b4811/html5/thumbnails/74.jpg)
Curious for more?
Testing untestable code
http://replicatorframework.org
![Page 75: Testing untestable code - ConFoo13](https://reader033.vdocument.in/reader033/viewer/2022051818/54b4fd414a7959b9428b4811/html5/thumbnails/75.jpg)
Thank you!
![Page 76: Testing untestable code - ConFoo13](https://reader033.vdocument.in/reader033/viewer/2022051818/54b4fd414a7959b9428b4811/html5/thumbnails/76.jpg)
http://joind.in/7972
![Page 77: Testing untestable code - ConFoo13](https://reader033.vdocument.in/reader033/viewer/2022051818/54b4fd414a7959b9428b4811/html5/thumbnails/77.jpg)
Testing untestable code
Flickr Credits
http://www.flickr.com/photos/andresrueda/3452940751/
http://www.flickr.com/photos/andresrueda/3455410635/