22
Unit Tests als Spezifikation? Nicole Rauch, Marc Philipp 26. November 2010

Unit Tests als Spezifikation?

Embed Size (px)

DESCRIPTION

Ohne automatisierte Tests wäre TDD, das Kernstück von XP, undenkbar. Häufig wird auch behauptet, dass Tests das Verhalten des Codes dokumentieren. Doch ist dies tatsächlich der Fall? Traditionelle Tests überprüfen das Verhalten beispielhaft anhand einiger (hoffentlich) gut gewählter Eingabewerte oder Szenarien. Doch was ist mit Werten, die man beim Schreiben des Tests vergessen hat? Hier fehlt dann nicht nur der Test, sondern auch die Dokumentation! Testing Tools für funktionale Sprachen, wie z. B. QuickCheck für Haskell, verwenden seit jeher eine komplett andere Herangehensweise. Statt explizit Eingabewerte anzugeben, spezifiziert man charakteristische Eigenschaften des Codes, die unter bestimmten Voraussetzungen gelten sollen. Bei der Testausführung werden diese Eigenschaften dann anhand automatisch generierter Eingabewerte verifiziert. JUnit bietet seit einiger Zeit die Möglichkeit, solche Eigenschaften als sog. Theories zu formulieren. Was im Vergleich mit QuickCheck und anderen aber fehlt, ist die automatische Erzeugung von Eingabewerten aus einer wie auch immer gearteten Spezifikation heraus. In dieser Session werden zuerst die theoretischen Hintergründe von Spezifikationstechniken angerissen und betrachtet, welche Eigenschaften ein Test braucht, um als gute Spezifikation dienen zu können. Anschließend werden die beiden oben genannten Techniken anhand praktischer Beispiele verglichen, kombiniert und diskutiert.

Citation preview

Page 1: Unit Tests als Spezifikation?

Unit Tests als Spezifikation?Nicole Rauch, Marc Philipp26. November 2010

Page 2: Unit Tests als Spezifikation?

Eine einfache Funktion

public double f ( double x ) {

if( x < 5.0 ) return 3.0;

else if( x < 10.0 ) return 2.0;

else return 4.0;

}

Beispielwerte für f:

x f( x )1 33 37 212 4

Unit-Tests für f:

@Test public void valuesOfF() {

assertEquals( 3.0, f( 1.0 ), 0.01 );

assertEquals( 3.0, f( 3.0 ), 0.01 );

assertEquals( 2.0, f( 7.0 ), 0.01 );

assertEquals( 4.0, f( 12.0 ), 0.01 );

}

Nicole Rauch, Marc Philipp Unit Tests als Spezifikation?

Page 3: Unit Tests als Spezifikation?

Eine einfache Funktion

public double f ( double x ) {

if( x < 5.0 ) return 3.0;

else if( x < 10.0 ) return 2.0;

else return 4.0;

}

Beispielwerte für f:

x f( x )1 33 37 212 4

Nicole Rauch, Marc Philipp Unit Tests als Spezifikation?

Page 4: Unit Tests als Spezifikation?

Was ist das Problem?

„Traditional test suites verify a few well-picked scenarios or exampleinputs. However, such example-based testing does not uncovererrors in legal inputs that the test writer overlooked.“

[Saff et.al.]

Nicole Rauch, Marc Philipp Unit Tests als Spezifikation?

Page 5: Unit Tests als Spezifikation?

Eine Alternative: Spezifikationen

Eine geeignete mathematische Spezifikation ist z. B.:

∀x . (x < 5 ⇒ f (x) = 3)∧ (5 ≤ x < 10 ⇒ f (x) = 2)∧ (10 ≤ x ⇒ f (x) = 4)

Nicole Rauch, Marc Philipp Unit Tests als Spezifikation?

Page 6: Unit Tests als Spezifikation?

Eine Lösung: JUnit Theories

I Herkömmliche Tests benutzen Beispiele:I Überprüfung des Verhaltens unter ausgewählten EingabenI Entwickler ist dafür verantwortlich, charakteristische Beispiele

zu wählenI Eine Theory verallgemeinert eine Menge von Tests:

I Vorbedingung wird explizit angegebenI Assertion muss für alle Eingaben gelten, die die

Vorbedingungen erfüllen

Nicole Rauch, Marc Philipp Unit Tests als Spezifikation?

Page 7: Unit Tests als Spezifikation?

Theories für unsere Funktion

@Theory

public void valuesLessThan5( double x ) {

assumeTrue( x < 5.0 );

assertEquals( 3.0, f(x), 0.01 );

}

@Theory

public void valuesBetween5And10( double x ) {

assumeTrue( 5.0 <= x );

assumeTrue( x < 10.0 );

assertEquals( 2.0, f(x), 0.01 );

}

@Theory

public void values10OrGreater( double x ) {

assumeTrue( 10.0 <= x );

assertEquals( 4.0, f(x), 0.01 );

}

Nicole Rauch, Marc Philipp Unit Tests als Spezifikation?

Page 8: Unit Tests als Spezifikation?

Woher kommen die Eingabewerte?

@DataPoint

public static double VALUE1 = 1.0;

@DataPoint

public static double VALUE2 = 3.0;

@DataPoint

public static double VALUE3 = 7.0;

@DataPoint

public static double VALUE4 = 12.0;

Nicole Rauch, Marc Philipp Unit Tests als Spezifikation?

Page 9: Unit Tests als Spezifikation?

DEMO

Nicole Rauch, Marc Philipp Unit Tests als Spezifikation?

Page 10: Unit Tests als Spezifikation?

ScalaCheck

I Generatoren erzeugen randomisierte TestwerteI Test ist grün nach 100 erfolgreichen DurchläufenI Test ist rot nach 500 unpassenden Eingaben

Nicole Rauch, Marc Philipp Unit Tests als Spezifikation?

Page 11: Unit Tests als Spezifikation?

Das war’s!

Wirklich?

Nicole Rauch, Marc Philipp Unit Tests als Spezifikation?

Page 12: Unit Tests als Spezifikation?

Objekte

Nicole Rauch, Marc Philipp Unit Tests als Spezifikation?

Page 13: Unit Tests als Spezifikation?

Eine User Story

Als Benutzer möchte ich einer PersonAdressen zuordnen können.

Die Person soll jede Adresse nureinmal enthalten.

Nicole Rauch, Marc Philipp Unit Tests als Spezifikation?

Page 14: Unit Tests als Spezifikation?

DEMO

Nicole Rauch, Marc Philipp Unit Tests als Spezifikation?

Page 15: Unit Tests als Spezifikation?

Bob

BobHamburg

Karlsruhe

Bob

Hamburg

Karlsruhe

Hamburg

Nicole Rauch, Marc Philipp Unit Tests als Spezifikation?

Page 16: Unit Tests als Spezifikation?

QuickCheck für Java?Erste Ansätze

QuickCheck-Portierung [quickcheck.dev.java.net]

I Stellt Generatoren für Standardtypen zur VerfügungI Benutzung über for-Schleifen im Unit Test

JCheck [jcheck.org]

I Generatoren müssen an jedem Test angegeben werdenI Verschachtelte AnnotationsI Keine Wiederverwendung von Theories

Nicole Rauch, Marc Philipp Unit Tests als Spezifikation?

Page 17: Unit Tests als Spezifikation?

QuickCheck für Java?Neuer Ansatz

JUnit-QuickCheck

I Eleganter neuer AnsatzI Basiert auf JUnit TheoriesI Parameter werden mit @Forall annotiertI Vordefinierte Generatoren für Standard-TypenI Steckt noch in den Kinderschuhen

Nicole Rauch, Marc Philipp Unit Tests als Spezifikation?

Page 18: Unit Tests als Spezifikation?

DEMO

Nicole Rauch, Marc Philipp Unit Tests als Spezifikation?

Page 19: Unit Tests als Spezifikation?

Unterschiede

ScalaCheck

I Generatoren erzeugen randomisierte TestwerteI Test ist grün nach 100 erfolgreichen DurchläufenI Test ist rot nach 500 unpassenden Eingaben

JUnit-QuickCheck

I Generiert pro Parameter 100 EingabewerteI Bei 2 Parametern 10.000 Kombinationen, bei drei 1.000.000I Test ist grün, wenn alle passenden Eingaben erfolgreich sindI Test ist rot, wenn kein passender Eingabewert gefunden wurde

Nicole Rauch, Marc Philipp Unit Tests als Spezifikation?

Page 20: Unit Tests als Spezifikation?

Fazit

Was macht einen guten Unit Test aus?Er vermittelt durch Beispiele schnell ein intuitives Verständnis.

Was macht eine gute Spezifikation aus?Sie beschreibt die zugrundeliegenden Regeln durch Abstraktion.

Geht beides zusammen?Es gibt kein Entweder-oder; beide Teile sind wichtig.

Nicole Rauch, Marc Philipp Unit Tests als Spezifikation?

Page 21: Unit Tests als Spezifikation?

Das war’s!

Wirklich!

Nicole Rauch, Marc Philipp Unit Tests als Spezifikation?

Page 22: Unit Tests als Spezifikation?

Vielen Dank!

Code & Folien auf GitHub:

https://github.com/marcphilipp/xpdays2010/

Nicole

E-Mail [email protected] @NicoleRauch

Marc

E-Mail [email protected] @marcphilipp

Nicole Rauch, Marc Philipp Unit Tests als Spezifikation?