Testing untestable code - gearconf11

Preview:

DESCRIPTION

 

Citation preview

Testing untestable code

Testing untestable code

Über mich

Stephan Hochdörfer, bitExpert AG

Department Manager Research Labs

S.Hochdoerfer@bitExpert.de

@shochdoerfer

Testing untestable code

Keine Entschuldigung für schlechten Code!

Nicht ausflippen!

Testing untestable code

Testing untestable code

Kreativität zählt!

Testing untestable code

"There is no secret to writing tests, there are only secrets to write

testable code!" Miško Hevery

Was ist „untestbarer Code“?

Testing untestable code

s

Testing untestable code

1. Falsche Instantiierung

“new” is evil!

Testing untestable code

2. Starke Kopplung

Keine Wiederverwendbarkeit

Testing untestable code

Nicht isolierbar, nicht testbar!

Testing untestable code

Testing untestable code

3. Ungewissheit

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 einer perfekten Welt..

Testing untestable code

SUTSUTUnittestUnittest

Legacy code ist nicht perfekt...

AbhängigeKlasse

AbhängigeKlasse

AbhängigeKlasse

AbhängigeKlasse

Testing untestable code

SUTSUTUnittestUnittest

Legacy code ist nicht perfekt...

AbhängigeKlasse

AbhängigeKlasse

AbhängigeKlasse

AbhängigeKlasse

...

...

Testing untestable code

SUTSUTUnittestUnittest

Legacy code ist nicht perfekt...

AbhängigeKlasse

AbhängigeKlasse

AbhängigeKlasse

AbhängigeKlasse

...

...

Testing untestable code

Wie erzeugt man „testbaren Code“?

Testing untestable code

Wie erzeugt man „testbaren Code“?

Refactoring

Testing untestable code

"Before you start refactoring, check that you have a solid suite of tests."

Martin Fowler, Refactoring

Testing untestable code

Hoffnung? ...ist nicht genug

Testing untestable code

Wohin führt die Reise?

Testing untestable code

Wohin führt die Reise?

Vorhandenen Code nicht ändern!

Testing untestable code

Beispiele

Objekterzeugung Externe Ressourcen Sprachbarrieren

Testing untestable code

Objekterzeugung

public class Car {private Engine engine;

public Car(String engine) {this.engine = EngineFactory.getByType(engine);

}}

Testing untestable code

Objekterzeugung - Autoload

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

Objekterzeugung – 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; }}

Testing untestable code

Objekterzeugung – 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;

}}

Testing untestable code

Externe Ressourcen

Testing untestable code

Externe Ressourcen

Datenbank Webservice

Dateisystem Mailserver

Testing untestable code

Externe Ressourcen – Datenbank mocken

Testing untestable code

Externe Ressourcen – Datenbank mocken

Eigene Implementierung anbieten

Testing untestable code

Externe Ressourcen – Datenbank mocken

junit + dbunit

Testing untestable code

Externe Ressourcen – Datenbank mocken

PHPUnit_Extensions_Database_TestCase

Testing untestable code

Externe Ressourcen – Datenbank mocken

Proxy für den SQL Server

Testing untestable code

Externe Ressourcen – Webservice mocken

Testing untestable code

Externe Ressourcen – Webservice mocken

Eigene Implementierung anbieten

Testing untestable code

Externe Ressourcen – Webservice mocken

Host Alias via /etc/hosts

Testing untestable code

Externe Ressourcen – Dateisytem mocken

Testing untestable code

Externe Ressourcen – Dateisytem mocken

Commons-VFS

Testing untestable code

Externe Ressourcen – Dateisytem mocken

vfsStream

Testing untestable code

Externe Ressourcen – Dateisystem mocken

<?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

Externe Ressourcen – Mailserver mocken

Testing untestable code

Externe Ressourcen – Mailserver mocken

fake mail server verwenden

Testing untestable code

Sprachbarrieren

Testing untestable code

Sprachbarrieren

private Methoden testen?

Testing untestable code

Sprachbarrieren

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

Sprachbarrieren

<?phpclass CustomWrapper {

private $_handler;

function stream_read($count) {$content = fread($this->_handler, $count);$content = str_replace(

'private function', 'public function', $content );

return $content;}

Testing untestable code

Sprachbarrieren

Interne Funktionen überschreiben?

Testing untestable code

Sprachbarrieren - Runkit

pecl install runkit-0.9

Testing untestable code

Sprachbarrieren - Runkit

<?php

ini_set('runkit.internal_override', '1');

runkit_function_redefine('mail','','returntrue;');

?>

Testing untestable code

Spielraum?

Testing untestable code

Abstrahieren du sollst!

Was sonst?

Testing untestable code

Generative Programmierung

Generative Programmierung

Testing untestable code

GeneratorGenerator

Generative Programmierung

Testing untestable code

Konfiguration(DSL)

Konfiguration(DSL)

GeneratorGenerator

Generative Programmierung

Software generieren statt programmieren

Konfiguration(DSL)

Konfiguration(DSL)

Implementierungs-komponenten

Implementierungs-komponenten GeneratorGenerator

Generative Programmierung

Testing untestable code

Konfiguration(DSL)

Konfiguration(DSL)

Implementierungs-komponenten

Implementierungs-komponenten GeneratorGenerator

ProduktProdukt

1..n

Generative Programmierung

Testing untestable code

Konfiguration(DSL)

Konfiguration(DSL)

Implementierungs-komponenten

Implementierungs-komponenten GeneratorGenerator

ApplikationApplikation

TestsTests

Testing untestable code

Generative Programmierung

Ein Frame ist eine Datenstrukturdie Wissen repräsentiert.

Testing untestable code

Eine Frame Instanz

public class Car {private Engine engine;

public Car(String engine) {this.engine = <!{Factory}!>.getByType(engine);

}}

Testing untestable code

Der 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

Nach der Generierung - Testcase

public class Car {private Engine engine;

public Car(String engine) {this.engine = FactoryMock.getByType(engine);

}}

Testing untestable code

Nach der Generierung - Applikation

public class Car {private Engine engine;

public Car(String engine) {this.engine = EngineFactory.getByType(engine);

}}

Testing untestable code

Was ist möglich?

Testing untestable code

Was ist möglich?

Extraktion von Codezeilen

Testing untestable code

Was ist möglich?

Globale Inhalte verändern

Testing untestable code

Was ist möglich?

Pre- oder Postfixes für Methoden

Testing untestable code

Wie weit sollte man gehen?

Vielen Dank!

Testing untestable code

Bildquellen

http://www.flickr.com/photos/andresrueda/3452940751/

http://www.flickr.com/photos/andresrueda/3455410635/

Recommended