73
Testing untestable code Dem Legacy Code ein Schnippchen schlagen Stephan Hochdörfer bitExpert AG

Testing untestable code - Herbstcampus12

Embed Size (px)

DESCRIPTION

 

Citation preview

Page 1: Testing untestable code - Herbstcampus12

Testing untestable codeDem Legacy Code ein Schnippchen schlagen

Stephan HochdörferbitExpert AG

Page 2: Testing untestable code - Herbstcampus12

Testing untestable code

Über mich

Stephan Hochdörfer, bitExpert AG

Department Manager Research Labs

[email protected]

@shochdoerfer

Page 3: Testing untestable code - Herbstcampus12

Testing untestable code

Keine Entschuldigung für schlechten Code!

Page 4: Testing untestable code - Herbstcampus12
Page 5: Testing untestable code - Herbstcampus12
Page 6: Testing untestable code - Herbstcampus12

Testing untestable code

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

testable code!" Miško Hevery

Page 7: Testing untestable code - Herbstcampus12

Was ist „untestbarer Code“?

Testing untestable code

Page 8: Testing untestable code - Herbstcampus12
Page 9: Testing untestable code - Herbstcampus12
Page 10: Testing untestable code - Herbstcampus12
Page 11: Testing untestable code - Herbstcampus12
Page 12: Testing untestable code - Herbstcampus12
Page 13: Testing untestable code - Herbstcampus12

Testing untestable code

"...our test strategy requires us to have more control [...] of the sut."Gerard Meszaros, xUnit Test Patterns: Refactoring Test

Code

Page 14: Testing untestable code - Herbstcampus12

Testing untestable code

SUTSUTUnittestUnittest

In einer perfekten Welt..

Page 15: Testing untestable code - Herbstcampus12

Testing untestable code

SUTSUTUnittestUnittest

Legacy code ist nicht perfekt...

AbhängigeKlasse

AbhängigeKlasse

AbhängigeKlasse

AbhängigeKlasse

Page 16: Testing untestable code - Herbstcampus12

Testing untestable code

SUTSUTUnittestUnittest

Legacy code ist nicht perfekt...

AbhängigeKlasse

AbhängigeKlasse

AbhängigeKlasse

AbhängigeKlasse

...

...

Page 17: Testing untestable code - Herbstcampus12

Testing untestable code

SUTSUTUnittestUnittest

Legacy code ist nicht perfekt...

AbhängigeKlasse

AbhängigeKlasse

AbhängigeKlasse

AbhängigeKlasse

...

...

Page 18: Testing untestable code - Herbstcampus12

Testing untestable code

Wie erzeugt man „testbaren Code“?

Page 19: Testing untestable code - Herbstcampus12

Testing untestable code

Wie erzeugt man „testbaren Code“?

Refactoring

Page 20: Testing untestable code - Herbstcampus12

Testing untestable code

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

tests."Martin Fowler, Refactoring

Page 21: Testing untestable code - Herbstcampus12
Page 22: Testing untestable code - Herbstcampus12

Testing untestable code

Wohin führt die Reise?

Page 23: Testing untestable code - Herbstcampus12

Testing untestable code

Wohin führt die Reise?

Wichtig: vorhandenen Code nicht verändern!

Page 24: Testing untestable code - Herbstcampus12

Testing untestable code

Beispiele

Objekterzeugung Externe Ressourcen Sprachbarrieren

Page 25: Testing untestable code - Herbstcampus12

Testing untestable code

Objekterzeugung

public class Car {private Engine engine;

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

}}

Page 26: Testing untestable code - Herbstcampus12

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);}

}}

Page 27: Testing untestable code - Herbstcampus12

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;

}}

Page 28: Testing untestable code - Herbstcampus12

Testing untestable code

Objekterzeugung – Stream Wrapper<?phpclass CustomWrapper {

private $_handler;

function stream_read($count) {$content = fread($this­>_handler, $count);$content = str_replace('Engine::getByType',

       ' Engine2::getByType', $content);return $content;

}}

Page 29: Testing untestable code - Herbstcampus12

Testing untestable code

Externe Ressourcen

Page 30: Testing untestable code - Herbstcampus12

Testing untestable code

Externe Ressourcen

Datenbank Webservice

Dateisystem Mailserver

Page 31: Testing untestable code - Herbstcampus12

Testing untestable code

Externe Ressourcen – Datenbank mocken

Page 32: Testing untestable code - Herbstcampus12

Testing untestable code

Externe Ressourcen – Datenbank mocken

Eigene Implementierung anbieten

Page 33: Testing untestable code - Herbstcampus12

Testing untestable code

Externe Ressourcen – Datenbank mocken

junit + dbunit

Page 34: Testing untestable code - Herbstcampus12

Testing untestable code

Externe Ressourcen – Datenbank mocken

PHPUnit_Extensions_Database_TestCase

Page 35: Testing untestable code - Herbstcampus12

Testing untestable code

Externe Ressourcen – Datenbank mocken

Proxy für den SQL Server

Page 36: Testing untestable code - Herbstcampus12

Testing untestable code

Externe Ressourcen – Webservice mocken

Page 37: Testing untestable code - Herbstcampus12

Testing untestable code

Externe Ressourcen – Webservice mocken

Eigene Implementierung anbieten

Page 38: Testing untestable code - Herbstcampus12

Testing untestable code

Externe Ressourcen – Webservice mocken

Host Alias via /etc/hosts

Page 39: Testing untestable code - Herbstcampus12

Testing untestable code

Externe Ressourcen – Dateisytem mocken

Page 40: Testing untestable code - Herbstcampus12

Testing untestable code

Externe Ressourcen – Dateisytem mocken

Commons-VFS

Page 41: Testing untestable code - Herbstcampus12

Testing untestable code

Externe Ressourcen – Dateisytem mocken

vfsStream

Page 42: Testing untestable code - Herbstcampus12

Testing untestable code

Externe Ressourcen – Dateisystem mocken

Page 43: Testing untestable code - Herbstcampus12

Testing untestable code

Externe Ressourcen – Mailserver mocken

Page 44: Testing untestable code - Herbstcampus12

Testing untestable code

Externe Ressourcen – Mailserver mocken

fake mail server verwenden

Page 45: Testing untestable code - Herbstcampus12

Testing untestable code

Externe Ressourcen – Mailserver mocken

Dumbster – Fake SMTP server

public class SimpleSmtpServerTest extends TestCase {  public void testSend() {    SimpleSmtpServer server = SimpleSmtpServer.start();

    // send your message here....

    server.stop();

    assertTrue(server.getReceivedEmailSize() == 1);    Iterator emailIter = server.getReceivedEmail();    SmtpMessage email = (SmtpMessage)emailIter.next();    assertTrue(email.getBody().equals("Test Body"));  }}

Page 46: Testing untestable code - Herbstcampus12

Testing untestable code

Externe Ressourcen – Mailserver mocken

Wem Dumbster zu blöd ist nutzt wiser ;)

Page 47: Testing untestable code - Herbstcampus12

Testing untestable code

Externe Ressourcen – Mailserver mocken

Wiser - The Wiser framework for unit testing mail

wiser.setPort(2500);wiser.start();

for (WiserMessage message : wiser.getMessages()){        String envelopeSender = 

message.getEnvelopeSender();        String envelopeReceiver = 

message.getEnvelopeReceiver();

        MimeMessage mess = message.getMimeMessage();

        // process the message...}

Page 48: Testing untestable code - Herbstcampus12

Testing untestable code

Sprachbarrieren

Page 49: Testing untestable code - Herbstcampus12

Testing untestable code

Sprachbarrieren

private Methoden testen?

Page 50: Testing untestable code - Herbstcampus12

Testing untestable code

Sprachbarrierenfinal 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;  

}

Page 51: Testing untestable code - Herbstcampus12

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;

}}

Page 52: Testing untestable code - Herbstcampus12

Testing untestable code

Sprachbarrieren

Interne Funktionen überschreiben?

Page 53: Testing untestable code - Herbstcampus12

Testing untestable code

Sprachbarrieren - Runkit

pecl install runkit-0.9

Page 54: Testing untestable code - Herbstcampus12

Testing untestable code

Sprachbarrieren - Runkit<?php

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

runkit_function_redefine('mail','','return true;');

Page 55: Testing untestable code - Herbstcampus12

Testing untestable code

Was nun? Was tun?<?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}

Page 56: Testing untestable code - Herbstcampus12
Page 57: Testing untestable code - Herbstcampus12
Page 58: Testing untestable code - Herbstcampus12

Was sonst?

Testing untestable code

Generative Programmierung

Page 59: Testing untestable code - Herbstcampus12

Testing untestable code

Generative Programmierung

Konfiguration(DSL)

Konfiguration(DSL)

Implementierungs-komponenten

Implementierungs-komponenten GeneratorGenerator

ProduktProdukt

1..n

Page 60: Testing untestable code - Herbstcampus12

Testing untestable code

Generative Programmierung

Konfiguration(DSL)

Konfiguration(DSL)

Implementierungs-komponenten

Implementierungs-komponenten GeneratorGenerator

Kunde 1Kunde 1

Kunde 2Kunde 2

Page 61: Testing untestable code - Herbstcampus12

Testing untestable code

Generative Programmierung

Konfiguration(DSL)

Konfiguration(DSL)

Implementierungs-komponenten

Implementierungs-komponenten GeneratorGenerator Prod.

Umgebung

Prod.Umgebung

TestUmgebung

TestUmgebung

Page 62: Testing untestable code - Herbstcampus12

Testing untestable code

Generative Programmierung

Ein Frame ist eine Datenstruktur die Wissen repräsentiert.

Page 63: Testing untestable code - Herbstcampus12

Testing untestable code

Frame<?phpclass Car {

private $Engine;

public function __construct($sEngine) {$this­>Engine = <!{Factory}!>::

getByType($sEngine);}

}

Page 64: Testing untestable code - Herbstcampus12

Testing untestable code

Der ContentProvider für den 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 65: Testing untestable code - Herbstcampus12

Testing untestable code

Ergebnis der Generierung: Test Umgebung<?phpclass Car {

private $Engine;

public function __construct($sEngine) {$this­>Engine = FactoryMock::

getByType($sEngine);}

}

Page 66: Testing untestable code - Herbstcampus12

Testing untestable code

Ergebnis der Generierung: Prod. Umgebung<?phpclass Car {

private $Engine;

public function __construct($sEngine) {$this­>Engine = EngineFactory::

getByType($sEngine);}

}

Page 67: Testing untestable code - Herbstcampus12

Lust auf mehr?

Testing untestable code

http://replicatorframework.org

Page 68: Testing untestable code - Herbstcampus12

Testing untestable code

Was ist möglich?

Page 69: Testing untestable code - Herbstcampus12

Testing untestable code

Was ist möglich?

Extraktion von Codezeilen

Page 70: Testing untestable code - Herbstcampus12

Testing untestable code

Was ist möglich?

Globale Inhalte verändern

Page 71: Testing untestable code - Herbstcampus12

Testing untestable code

Was ist möglich?

Pre- oder Postfixes für Methoden

Page 72: Testing untestable code - Herbstcampus12

Testing untestable code

Wie weit sollte man gehen?

Page 73: Testing untestable code - Herbstcampus12

Vielen Dank!