Haskell und Testen - Überblick QuickCheck
QuickCheck ist ein Testwerkzeug für die Sprache Haskell. Es wird als leichtgewichtig bezeichntet. In 350 Zeilen Code ist die Funktionalität des leistungsstarken Testingframeworks implementiert. QuickCheck ist in Form einer "domain-specific embeded language" (DSEL) realisiert. D.h. QuickCheck ist in Form von Kombinatoren in Haskell implementiert und unter Verwendung des Typsystems von Haskell in Haskell eingebundnen.
Das zentrale Konzept von QuickCheck ist die Formulierung von Eigenschaften und der Test von Eigenschaften von Programmen. Dabei werden die Eingenschaften durch Funktionen mit Hilfe der Kombinatoren in Haskell beschrieben und können automatisiert getestet werden. Wobei der Abgleich zwischen den erwarteten Eigenschaften gegen eine große Anzahl von Testfällen den Test bilden. Alle Tests basieren somit auf sogenannten Eigenschaften bzw. Properties und den zugehörigen Testfällen.
Bezüglich der notwendigen Testfälle ist es mit QuickCheck möglich mit automatisch, "zufallsbedingt" erzeugten Testdaten oder mit Hilfe spezifischer Testdatengeneratoren erzeugte Testdaten zu arbeiten. Wobei es sich bei "zufallsbedingt" erzeugten Testdaten lediglich um bereits in QuickCheck definierte Generatoren für die Standardtypen von Haskell handelt.
Mit dem Ansatz der automatisiert "zufallsbedingt" erzeugten Testdaten setzt sich QuickCheck konzeptioniell von den klasssischen UnitTestFrameworks ab. So auch von dem UnitTestFramework HUnit, denn hier sind, wie für UnitTestFrameworks üblich, lediglich Assertions also Zusicherungen möglich. d.h. der Vergleich zwischen einem konktreten, erwarteten Wert und der zugehörigen Funktion mit den konkreten Werten für die Parameter.
Die Autoren Koen Claessen und John Hughes sprechen in dem Zusammenhang mit diesem konzeptionellem Ansatz auch von "Automatic Specification-Based Testing". Sie benennen damit die Möglichkeit mit QuickCheck eine Definition unter Test zu erzeugen, damit also eine testbare, ausführbare Spezifikation, bei der die erwarteten Eigenschaften der Funktionen unter Einsatz bzw. Test verifizieren werden können, zu erstellen. Der Vorteil der automatisiert, "zufallsbedingt" erzeugten Testdaten liegt darin, dass sie auf Grund ihrer Feinkörnigkeit mit sehr hoher Genauigkeit die Funktionalität spezifizieren.
Claessen und Hughes raten beim Einsatz von QuickCheck Tests innerhalb der Module mit den zu testenden Funktionalitäten zu implementieren. Sie zielen dabei auf den Aspekt der so entstehenden zusätzlichen testbaren Dokumentation / Spezifikation ab.
Mit Ausnahme der IO Monade, die auch laut Koen und Hughes schwierig zu testen ist, eignen sich funktionale Programmiersprachen besonders für die Anwendung von Testverfahren, da sie keine Zustände haben (s. destructive Updates) und somit keine keine bzw. kaum Seiteneffekte im Vergleich zu imperativen Programmiersprachen möglich sind.
In dieser Ausarbeitung werden im folgenden über Beispiele eine Reihe von Kombinatoren vorgestellt und erläutert.
Code generated with AusarbeitungGenerator Version 1.1, weblink