© Enkel/Shutterstock.com
Property-based Testing mit ScalaCheck

Gemeinsam stark


Über die Jahre ist der Scala-Werkzeugkasten immer weitergewachsen. Mit ScalaCheck [1], [2] kommt eine mächtige Testmethodik in Sachen Property-based Testing dazu. Der Property-basierte Ansatz ist kein Ersatz für beispielbasiertes Testen mittels Unit-Tests. Er ergänzt es vielmehr, vor allem, da Property-based Tests allgemeiner formuliert sind und üblicherweise andere Klassen von Fehlern identifizieren.

Von Anforderungsseite erhalten wir einen Wunsch: Der Fachbereich benötigt eine Funktion, die zwei Ganzzahlen miteinander addieren kann. Nichts einfacher als das, sagt der Entwickler und legt direkt mit der Implementierung los. Die Funktion ist schnell geschrieben, beispielbasierte Unit-Tests sollen die Korrektheit sicherstellen:

class AdderTest extends FlatSpec with Matchers { "Adder" should "yield 4 when I add 1 and 3" in { add(1, 3) shouldBe 4 } "Adder" should "yield 4 when I add 4 and 0" in { add(4, 0) shouldBe 4 } }

Doch kurz nach dem Ausrollen des Lieferpakets meldet sich der Betrieb zu Wort: Offenbar scheint es mit dem Addierer Schwierigkeiten zu geben. In der Analyse zeigt sich, dass die implementierte Funktion nicht ganz der Definition des Addierens entspricht.

object Adder { def add(a: Int, b: Int) = 4 }

Offensichtlich decken unsere beispielbasierten Testfälle das korrekte Verhalten des Addierers nur unzureichend ab. Wir haben uns einerseits darauf verlassen, dass unsere Testfälle für eine hinreichende Abdeckung sorgen, und andererseits unsere Implementierung – ganz nach Test-driven Development – minimalistisch ausgerichtet, sodass sie die Testfälle erfüllt.

Zugegeben, dieses Beispiel ist überspitzt, aber das ist in erster Linie der Einfachheit der zu implementierenden Funktion geschuldet. In der Praxis treten solche Erscheinungen dann auf, wenn die Spezifikation unklar ist und der Entwickler ohne Rücksprache mit dem Anforderer seinen Interpretationsspielraum nutzt, oder aber wenn beispielbasierte Tests schlicht unzureichend sind und weder Randfälle noch die bestimmenden Charakteristiken der implementierten Logik prüfen.

Um zurück zu unserem minimalistischen Beispiel zu kommen: Hinterfragen wir zunächst einmal die konkreten Anforderungen an die zu implementierende Funktion. Welche Eigenschaften muss eine Addierfunktion erfüllen? Wir können uns der Sache nähern, indem wir uns anschauen, was einen Addierer von anderen Funktionen, beispielsweise einem Subtrahierer, unterscheidet. Nun, ein Addierer sollte unabhängig von der Reihenfolge der Eingangspara...

Neugierig geworden?

Angebote für Teams

Für Firmen haben wir individuelle Teamlizenzen. Wir erstellen Ihnen gerne ein passendes Angebot.

Das Library-Modell:
IP-Zugang

Das Company-Modell:
Domain-Zugang