testing untestable code - stpcon11
TRANSCRIPT
Testing untestable codeStephan Hochdörfer, bitExpert AG
Testing untestable code
About me
Stephan Hochdörfer, bitExpert AG
Department Manager Research Labs
@shochdoerfer
Testing untestable code
No excuse for writing bad code!
Not to freak out!
Testing untestable code
Testing untestable code
Creativity matters!
Testing untestable code
"There is no secret to writing tests, there are only secrets to write
testable code!" Miško Hevery
What is „untestable code“?
Testing untestable code
s
Testing untestable code
Wrong object construction
“new” is evil!
Testing untestable code
Tight coupling
Testing untestable code
Uncertainty
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
SUTSUTUnittestUnittest
In a perfect world...
Testing untestable code
SUTSUTUnittestUnittest
Legacy code is not perfect...
DependencyDependency
DependencyDependency
Testing untestable code
SUTSUTUnittestUnittest
Legacy code is not perfect...
DependencyDependency
DependencyDependency
...
...
Testing untestable code
SUTSUTUnittestUnittest
Legacy code is not perfect...
DependencyDependency
DependencyDependency
...
...
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
Hope? - Nope...
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
public class Car {private Engine engine;
public Car(String engine) {this.engine = EngineFactory.getByType(engine);
}}
public class MyLoader extends ClassLoader {protected Class findClass(String name)
throws ClassNotFoundException{
try {String path = name.replace('.', '/');// @TODO: change path and read file, // @TODO: define package// @TODO: define class
}catch(Exception e){
throw new ClassNotFoundException(name);}
}}
Testing untestable code
Object construction - Solution
Testing untestable code
Object construction - Solution II
<?phpclass MyStreamWrapper { 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', 'MyStreamWrapper'); return true; }}
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 db driver
Testing untestable code
External resources – Mock database
junit + dbunit
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
Do not forget!
Url redirection via /etc/hosts
Testing untestable code
External resources – Mock filesystem
Testing untestable code
External resources – Mock filesystem
Commons-VFS
vfsStream
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');
Testing untestable code
External resources – Mock Mailserver
Testing untestable code
External resources – Mock Mailserver
Use fake mail server
Testing untestable code
Dealing with language issues
Testing untestable code
Dealing with language issues
Testing your privates?
Testing untestable code
Dealing with language issues
final Method methods[] =o.getClass().getDeclaredMethods();for (int i = 0; i < methods.length; ++i) {
if (methodName.equals(methods[i].getName())) {try {
methods[i].setAccessible(true); return methods[i].invoke(o, params);} catch (IllegalAccessException ex) {}catch (InvocationTargetException ite) {}
}return null;
}
Testing untestable code
Dealing with language issues
Overwrite internal functions?
Testing untestable code
What else?
What else?
Testing untestable code
Generative Programming
Testing untestable code
Generative Programming
ConfigurationConfiguration
Implementationcomponents
Implementationcomponents
Generatorapplication
Generatorapplication
ProductProductGeneratorGenerator
1 ... n
Testing untestable code
Generative Programming
ConfigurationConfiguration
Implementationcomponents
Implementationcomponents
Generatorapplication
Generatorapplication
GeneratorGenerator
ApplicationApplication
TestcasesTestcases
Testing untestable code
Generative Programming
A frame is a data structure for representing knowledge.
Testing untestable code
A Frame instance
public class Car {private Engine engine;
public Car(String engine) {this.engine = <!{Factory}!>.getByType(engine);
}}
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");}
}}
Testing untestable code
Generated result - Testcase
public class Car {private Engine engine;
public Car(String engine) {this.engine = FactoryMock.getByType(engine);
}}
Testing untestable code
Generated result - Application
public class Car {private Engine engine;
public Car(String engine) {this.engine = EngineFactory.getByType(engine);
}}
Testing untestable code
What is possible?
Testing untestable code
What is possible?
Show / hide parts of the code
Testing untestable code
What is possible?
Change content of global vars!
Testing untestable code
What is possible?
Define pre- or postfixes!
Testing untestable code
Is it worth it?
Thank you for attending this session.
Please fill out an evaluation form.