Strukturorientiertes Testen funktionaler Programme

Funktionale Programmierung ermöglicht das Erstellen von Programmen auf einem hohen Abstraktionsniveau. Eine Anzahl erfolgreicher Softwareprojekte unter Verwendung funktionaler Sprachen lässt eine wachsende Relevanz funktionaler Programmierung für die industrielle Softwareentwicklung erwarten. Gerade für die industrielle Nutzung einer Programmiersprache ist jedoch eine ausreichende Werkzeugunterstützung notwendig. Die Verfügbarkeit solcher Werkzeuge für funktionale Sprachen ist bisher noch nicht ausreichend, insbesondere auch was das Testen funktionaler Programme betrifft. Speziell das strukturorientierte Testen funktionaler Programme ist bisher kaum berücksichtigt worden. Bei dem Versuch, Ansätze zum strukturorientierten Testen von der imperativen Programmierung auf funktionale Programme zu übertragen, treten zwei Hauptprobleme auf: Funktionen höherer Ordnung komplizieren die Erstellung von Flussgraphen, und die Verwendung komplexer kontrollflussorientierter Überdeckungskriterien scheitert daran, dass die dazu passenden Programmkonstrukte in funktionalen Programmen kaum vorkommen. Zur Flussgrapherstellung wird hier ein Ansatz vorgestellt, der durch iterierte Datenflussanalyse die Ziele von Funktionsaufrufen höherer Ordnung berechnet. Dieser Ansatz basiert auf dem 0CFA-Verfahren, das in Übersetzern für funktionale Sprachen zum Einsatz kommt. Die Flussgraphen für das strukturorientierte Testen müssen insbesondere für die Programmierer in der jeweiligen Sprache verständlich sein und eine möglichst große Ähnlichkeit mit dem repräsentierten Code aufweisen. Dazu wird ein spezielles Konzept bidirektionaler Aufrufkanten eingeführt. Für den Überdeckungstest in der funktionalen Programmierung bieten sich datenflussorientierte Überdeckungskriterien an. Diese sind weitgehend unabhängig von den verwendeten Programmkonstrukten und können auch für funktionale Sprachen mit verzögerter Auswertung sinnvoll eingesetzt werden. Sequenzen von Definitions-Verwendungs-Paaren erlauben es, den Datenfluss von Werten losgelöst von den transportierenden Variablen zu betrachten.