2. Testing untestable code
About me
Stephan Hochdörfer
Head of IT at bitExpert AG, Germany
enjoying PHP since 1999
S.Hochdoerfer@bitExpert.de
@shochdoerfer
14. Testing untestable code
"...our test strategy requires us to
have more control [...] of the sut."
Gerard Meszaros, xUnit Test Patterns: Refactoring Test
Code
26. Testing untestable code
Object construction
<?php
class Car {
private $Engine;
public function __construct($sEngine) {
$this>Engine = Engine::getByType($sEngine);
}
}
28. Testing untestable code
Object construction
<?php
include('Engine.php');
class Car {
private $Engine;
public function __construct($sEngine) {
$this>Engine = Engine::getByType($sEngine);
}
}
45. 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');
57. 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'));
60. Testing untestable code
Dealing with language issues - AOP
<?php
aop_add_after('Car::drive*',
'adviceForDrive');
61. 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);
62. Testing untestable code
And now? Spaghetti mess...
<?php
$all_tables_query = ' SELECT table_name, MAX(version) as
version FROM ...';
$all_tables_result =
PMA_query_as_controluser($all_tables_query);
// If a HEAD version exists
if (PMA_DBI_num_rows($all_tables_result) > 0) {
?>
<div id="tracked_tables">
<h3><?php echo __('Tracked tables');?></h3>
<?php
}
69. Testing untestable code
Generative Programming
A frame is a data structure
for representing knowledge.
70. Testing untestable code
Frame
<?php
class Car {
private $Engine;
public function __construct($sEngine) {
$this>Engine = <!{Factory}!>::
getByType($sEngine);
}
}
71. 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;
}
}
72. Testing untestable code
Generated result – Test Enviroment
<?php
class Car {
private $Engine;
public function __construct($sEngine) {
$this>Engine = FactoryMock::
getByType($sEngine);
}
}
73. Testing untestable code
Generated result – Prod. Enviroment
<?php
class Car {
private $Engine;
public function __construct($sEngine) {
$this>Engine = EngineFactory::
getByType($sEngine);
}
}