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
"...our test strategy requires us to
have more control [...] of the sut."
Gerard Meszaros, xUnit Test Patterns: Refactoring Test
Code
Testing untestable code
Object construction
<?php
class Car {
private $Engine;
public function __construct($sEngine) {
$this->Engine = Engine::getByType($sEngine);
}
}
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 – Namespaces
<?php
class Car {
private $Engine;
public function __construct($sEngine) {
$this->Engine = CarEngine::
getByType($sEngine);
}
}
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
Generative Programming
A frame is a data structure
for representing knowledge.
Testing untestable code
A Frame instance
<?php
class Car {
private $Engine;
public function __construct($sEngine) {
$this->Engine = <!{Factory}!>::
getByType($sEngine);
}
}
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
<?php
class Car {
private $Engine;
public function __construct($sEngine) {
$this->Engine = FactoryMock::
getByType($sEngine);
}
}
Testing untestable code
Generated result - Application
<?php
class Car {
private $Engine;
public function __construct($sEngine) {
$this->Engine = EngineFactory::
getByType($sEngine);
}
}