Zufallsbasiertes Testen mit QuickCheck
Agenda Einführung Haskell QuickCheck Zusammenfassung Einführung: Testen
Einführung Testen als essenzieller Bestandteil gewährleistet Robustheit und Qualität von Software Kosten in Höhe von 50% der Entwicklungskosten Forderung nach Effizienz von Testmethodiken Zufallsbasiertes Testen als effiziente Methodik Kein Starres Definieren von Testfällen Generierung von Zufallsdaten für Input automatisch Grundlage ist eine Verteilung Überprüfung eines Moduls mit Zufallsdaten vorwiegend Black-Box-Testing Auch white-box (pfadabdeckung), aber komplexer (-> Nutzung des Implementierungscodes)
Vergleich d. Outputs mit Soll Black-Box-Testing Inputparameter Code Vergleich d. Outputs mit Soll Implementierung bleibt verborgen Lediglich Spezifikation der Funktionalität erforderlich Paarweise Erzeugung von Input/Output-Daten Vergleich von Soll- und erzeugtem Output Erzeugung der Inputdaten willkürlich oder kalkuliert Prädestiniert für zufallsbasierte bzw. automatisierte Methodik Wahl der Verteilung relevant für Qualität eines Tests Relevanz von deklarativen Programmiersprachen Relevanz von dekl. Programmiersprachen: keine Seiteneffekte -> schnelles Durchlaufen möglich Aber: auch in Java zb Ansätze vorhanden
White-Box-Testing Benutzung, falls Spezifikation schwierig Code wird herangezogen Control-Flow-Testing Pfadabdeckung Jeder Pfad mindestens 1-fach abgedeckt Data-Flow-Testing Bildung von Chains mit 3 Informationen (Var, Wert, Nutzung) Ansätze zur Anwendung auch im deklarativen Umfeld EVENTUELL diese Folie RAUSNEHMEN UND nur bei Black-Box-Testing stichpunktartig in Notiz erwähnen Alternative ist White-Box-Testing: Bietet sich an, wenn Spezifikation schwierig ist (-> Bei komplexen Algorithmen…) Data-Flow Testing (Var, Wertzuweisung, Nutzung), Control-Flow Testing (Pfaddeckung) Oft manuell, da codeinterpretation schwierig Aber: auch automatisierte, zufallsbasierte Methodiken vorhanden (data-flow) Ansatz auch im imparativen Umfeld (-> Java)
Agenda Einführung Haskell QuickCheck Zusammenfassung Einführung: Testen
Haskell Haskell als deklarative Programmiersprache Beispiel: Formulierung eines Problems durch Funktionen/Definitionen Keine Explizite Konzeption Haskell evaluiert Funktionen auf Grundlage eines Inputs Zustandslos Beispiel: Schnell, keine seiteneffekte (prinzipiell), mehrere neue Durchläufe nach modifikation einfach möglich
Haskell Zufallsbasierter Kontext Generierung verschiedener ‚n‘ Aufruf von ‚aufsummieren‘ mit jeweiligem ‚n‘ Vergleich des Ergebnisses mit Referenz/Spezifikation Falls alle Durchläufe korrekt, ist ‚aufsummieren‘ „korrekt“ Referenz: zb Gaußformel „korrekt“ weil: keine 100%ige Garantie!!
Haskell Generierung von einfachen Typen trivial Zustandlosigkeit von Haskell vorteilhaft (Seiteneffekte) Zustandlosigkeit wirkt sich auf Generierung aus Generierung von komplexen Datenstrukturen (Bäume) nicht möglich Abhilfe: Monaden 5 1 10
Monaden Begriff der Mathematik Umsetzung von imperativen Prinzipien (Zustand) Ursprünglich für Input/Output von dekl. Programmen Hilft bei der Generierung komplexer Datenstrukturen Hier als text (courier new) einfügen
Agenda Einführung Haskell QuickCheck Zusammenfassung Einführung: Testen
QuickCheck In Haskell geschriebenes Modul In Haskell als solches einsetzbar Umfasst rund 300 Zeilen (lightweight) Testmethodik im Rahmen dekl. Programmiersprache Black-Box-Testing Zufallsbasiert auf Grund von Verteilungen
Konzept Festlegung der Generatoren: ebenfalls eigene Kreationen möglich, in Haskell Erstellung der Property: in Haskell, nimmt Rückgriff auf zu testende Komponenten, gibt Wert vom Typ Bool zurück Anstoß von QuickCheck im Interpreter durch Rückgriff auf das Modul QuickCHeck und Aufruf der Property Property?: Property enthält Validierung der zu prüfenden Komponente, indem bspw. Ein anderer Algorithmus dagegen gehalten wird oder Resultate validiert werden Mehrere durchläufe (100 std), damit möglichst alle facetten abgedeckt werden -> keine absolute Sicherheit
Beispiel Haskell-Interpreter: Falsches Definition: Die einzelnen Testfälle werden bei positivem Ausgang der Durchläufe nicht angezeigt. Sollen diese dennoch ausgegeben werden, so kann das Kommando „verboseCheck“ verwendet werden und es erfolgt eine Darstellung aller generierter Inputparameter Einfach: kein nebenher benötigter Algorithmus, da hier direkt mulitpliziert werden kann Problem: Validation bei schwierigeren Problemen
Komplexeres Problem -> Validierung nicht so einfach wie beim Vorgänger! -> Überprüfung, ob aufsteigende Reihenfolge gegeben ist + Length
Funktionalität Benutzung bedingter Properties möglich Generierung erfolgt je Durchlauf solange, bis Property erfüllt Gefahr: Verzerrung der Verteilung Restriktion der Bedingung verwirft bspw. bestimmte, notwendige Testdaten Beispiel: sortierte Liste als Bedingung fast nur kurze Listen als Input Änderung des Ausgabetyps der Property in „Property“!
Funktionalität Überwachung von Inputparametern Monitoring durch Klassifikation „classify“ „collect“
Selbstdefinierte Generatoren Hohe Qualität eines Tests gefordert Annäherung der Testdaten an die tatsächlichen Versuch der Anlehnung einer Verteilung Berücksichtigung komplexer Typen Forderung zur Konzeption eigener Generatoren Beispiel Liste: Generator für sortierte Listen Bedingung entfällt Listenlängen repräsentativ
Selbstdefinierte Generatoren Eigener Typ instanziiert Klasse: Eigener Generator muss spezifiziert werden Standardtypen haben bereits Instanzen Basisgeneratoren können kombiniert werden Beispiel: weitere: oneof, frequency, size Abstraktes ‚Gen‘ ist Instanz der Haskell-Klasse „Monad“ Berücksichtigung der Monadenfunktionalität Eigen. Gen : Klasse wird instanziiert mit eigenem Typen. Der Generator „Gen“ muss dann festgelegt werden. Size wichtig für zb Liste oder Baum, damit nicht endlose Rekursionen entstehen
Demo Binärbaum mit Funktionen ‚suche‘ ‚loesche‘ und ‚einfuegen‘ Sized wendet Int-Wert auf Generator an und gibt einen zurück (-> Limit) -- Do – Konzept entspricht Monadenfunktion ‚&‘ ListM4 ist Mapoperator ‚*‘ Return ist ‚lift‘-op
Binärbaum Der Aufruf erfolgt im Haskell-Interpreter Die Properties werden getestet In diesem Beispiel liegt der Anteil der Binärbaumgröße von [1,2,3] bei etwa 20-30%
Agenda Einführung Haskell QuickCheck Zusammenfassung Einführung: Testen
Zusammenfassung QuickCheck ist probates Mittel zum Testen Nachteil Schnell, effektiv, flexibel, einfach im Umgang Überwachung der Testläufe Geringe Testkosten Nachteil Keine Garantie bei postulierter Fehlerfreiheit Konzeption komplexer Properties Generatorenentwurf kann komplex werden Ausblick White-Box-Testing (Data-Flow) mit QuickCheck White-Box-Testing bei Java Aufwand hält sich in Grenzen, einfach, schnell durchführbar, modifikationen (->flexibel) Probleme: Spezifikationen + …!!
Vielen Dank für die Aufmerksamkeit! Ende Vielen Dank für die Aufmerksamkeit! Fragen?
Backup
Backup
Backup
Backup