Kontrollflussgraph Beispiel Essay

Überdeckungsmaße

Kurzform

Für Überdeckungstests wird zunächst festgelegt, was überdeckt werden soll, dann werden Tests durchgeführt und überprüft, wie hoch die resultierende Überdeckung ist. Ein konkretes Beispiel sind die Überdeckungen von Programmanweisungen. Das Ziel ist es dann, dass jede Anweisung mindestens einmal durchgeführt wird. Man hat so die Gewissheit, dass es keine Stelle im Programm gibt, die immer zu Fehlern führt. Durch verschiedene Varianten von Abdeckungen können unterschiedliche Aspekte behandelt werden. Überdeckungen sind dabei für alle graphischen Ablaufbeschreibungen, wie Aktivitäts- und Zustandsdiagramme, möglich. Überdeckungen können nur sinnvoll von Werkzeugen berechnet werden, dabei wird protokolliert, was bei der Ausführung der zu untersuchenden Software ausgeführt wird.

Varianten von Überdeckungen (angelehnt an [Kle09])

Zu jedem imperativen Programm kann man einen sogenannten Kontrollflussgraphen (KFG) konstruieren. Dabei entspricht jede Anweisung einem Knoten und die Verbindungen zwischen den Knoten der möglichen Nacheinanderausführung der Anweisungen.

Obiges Bild zeigt links eine Java-Methode und rechts den zugehörigen KFG.

C0-Überdeckung (Anweisungsüberdeckung)

Bei der C0-Überdeckung ist es das Ziel, dass möglichst jede Anweisung einmal durchlaufen wird. Ein Testfall wird durch mögliche Eingaben sowie die erwarteten Ausgaben beschrieben und führt dazu, dass gewisse Anweisungen durchlaufen werden.

Der Testfall mit x=5 und y=5 führt dazu, dass die im Bild markierten Anweisungen durchgeführt werden. Man spricht hier von einer Anweisungsüberdeckung von 6/7, da fünf der sieben Knoten besucht wurden. Man erkennt, dass man in den meisten Fällen mehrere Testfälle angeben muss, um eine vollständige Überdeckung zu erreichen. In diesem Fall reicht ein zweiter Testfall mit x=11 und y=5 aus.

C1-Überdeckung (Zweigüberdeckung)

Bei der C1-Überdeckung ist es das Ziel, dass jede Kante des KFG mindestens einmal genutzt wird.

Der Testfall mit x=5 und y=5 führt dazu, dass die im Bild markierten Kanten durchlaufen werden. Man spricht von einer Pfadüberdeckung von 5/8, da fünf der acht Kanten genutzt werden. Nimmt man den oben genutzten Testfall x=11 und y=5 dazu, erhält man insgesamt nur eine Überdeckung von 7/8. Dies zeigt, dass eine C0-Überdeckung einfacher zu erreichen ist als eine C1-Überdeckung. Aus der Definition der vollständigen C1-Überdeckung folgt, dass diese auch eine vollständige C0-Überdeckung ist. Die beiden Testfälle x=5 und y=5, sowie x=15 und y=0 ergeben eine vollständige C1-Überdeckung.

C2-Überdeckung (einfache Bedingungsüberdeckung)

Bei der C2-Überdeckung interessiert man sich nur für die elementaren Bedingungen im Programm. Im Beispiel sind dies x>0, y>0, x>10 und y<10. Für eine vollständige C2-Überdeckung wird gefordert, dass bei der Testausführung jede elementare Bedingung einmal nach wahr und einmal nach falsch ausgewertet wird. Betrachtet man nur x>0 und y>0 ist dies durch die beiden Testfälle x=5 und y=0 sowie x=0 und y=5 der Fall. Für die zusammengesetzte Bedingung x>0 && y>0 bedeutet dies aber, dass sie in beiden Fällen nach falsch ausgewertet wird. Es folgt daraus, dass man aus einer vollständigen C2-Überdeckung nicht auf eine vollständige C1- oder C0-Überdeckung schließen kann. Aus vollständigen C0- und C1-Überdeckungen kann man auch nicht auf eine C2-Überdeckung schließen, da in den vorherigen Beispielen x>0 immer nach wahr ausgewertet wurde. Kritisch bei der C2-Überdeckung ist die sogenannte Kurzschlussauswertung zu beachten. Soll z. B. a && b ausgewertet werden und ist die Auswertung von a bereits falsch, wird zur Geschwindigkeitssteigerung b gar nicht mehr betrachtet. In unserem Beispiel heißt dies, dass beim zweiten Test y=5 keinen Einfluss mehr hat und man einen Test mit positiven x- und y-Werten ergänzen muss.

C3-Überdeckung (minimale Mehrfachüberdeckung)

Die C3-Überdeckung erweitert den Ansatz der C2-Überdeckung um die Betrachtung der zusammengesetzten Bedingungen. Im Beispiel werden damit die sechs Bedingungen x>0, y>0, x>10, y<10, x>0 && y>0 und x>10 && y<10 betrachtet. Dadurch wird gewährleistet, dass eine vollständige C3-Überdeckung auch garantiert eine vollständige C1-Überdeckung liefert. Im Beispiel ist dies durch die Testfälle x=15 und y=5, x=15 und y=15, x=15 und y=0 sowie x=0 und y=5 der Fall. Wieder ist der Einfluss der Kurzschlussauswertung zu beachten.

Weitere kontrollflussbezogene Überdeckungen

Es gibt in der Literatur [Lig02] viele weitere Überdeckungen, die sich mit der Hintereinanderausführung von Anweisungen beschäftigen und z. B. fordern, dass Schleifen eine minimale und maximale Anzahl durchlaufen werden. Bei den Bedingungen kann man z. B. fordern, dass es Tests gibt, mit denen man zeigt, dass jede elementare Bedingung b in einer zusammengesetzten Bedingung für das Ergebnis der Auswertung der zusammengesetzten Bedingung verantwortlich ist. Man benötigt dabei für b zwei Tests, bei denen außer für b die restlichen Bedingungen immer die genau gleichen Werte bei der Auswertung liefern und nur die Auswertung von b einmal wahr und einmal falsch liefert.

Datenflussbezogene Überdeckungen

Anders als beim bisher betrachteten Kontrollfluss, interessiert man sich beim Datenfluss für die Auswirkung einzelner Variablen bzw. einzelner Anweisungen. Man kann sich für eine Anweisung z. B. fragen, ob sie Auswirkungen auf das restliche Programm hat. Dazu werden dann zwei Tests benötigt, in denen jeweils die Anweisung ausgeführt wird und die danach zu unterschiedlichen Abläufen führen. Hier sind wieder viele Varianten von Überdeckungstests möglich.

Überdeckungen und Objektorientierung

Überdeckungsmaße spielen auch bei objektorientierten Programmen eine wesentliche Rolle bei der Qualitätssicherung. Man muss aber die zusätzliche Komplexität beachten, die z. B. durch die dynamische Polymorphie eingeführt wird. Betrachtet man die einfache Bedingung ob.getValue()>42, so kann die Klasse von ob eine wichtige Rolle spielen. Wird z. B. der Typ O (Klasse oder Interface) für ob angegeben und erbt O1 von O und O2 von O, so kann ob ein Objekt aller drei Klassen sein, die sich alle leicht unterschiedlich verhalten. Man muss sich dann bei Überdeckungen fragen, ob Tests mit allen Varianten von ob durchgeführt wurden. Weiterhin muss man bei der Objektorientierung beachten, dass auch Ausnahmebehandlungen, wie try-catch-Blöcke, Verzweigungen im Programmablauf darstellen.

Fazit zu Überdeckungen

Überdeckungen, gerade C1 und C2, spielen bei der Qualitätssicherung eine wesentliche Rolle. Dabei sind vollständige Überdeckungen meist selten zu erreichen, was in der Vielfalt der Ablaufmöglichkeiten z. B. mit schwer zu testenden try-catch-Blöcken liegen kann. Da man sich bei Überdeckungen immer fragt, welche Auswirkung ein Befehl, eine Bedingung oder eine Variable haben kann, findet man durch solche Ansätze viele kleine Fehler. Um effizient mit Überdeckungstests arbeiten zu können, ist eine Automatisierung der wiederholten Testausführung mit der Berechnung und Analyse der Überdeckungen unerlässlich. Generell ist beim Überdeckungsansatz zu beachten, dass man zwar genau die inneren Details der Abläufe prüft, es aber nicht festgestellt werden kann, ob das Programm überhaupt seine ursprüngliche Aufgabenstellung erfüllt.


Zurück zur Methodenübersicht
Zurück zur CSI-Hauptseite

Verfahren

Pfadüberdeckung

Beschreibung
Die Pfadüberdeckung (engl. path coverage) zur Ermittlung der Testfälle konzentriert sich auf die einzelnen Pfade des Testobjekts. Pfade stellen hier die “Gesamtwege” des Kontrollflusses durch den Code des Testobjekts dar. Je nach festgelegtem Ziel sind ein gewisser Anteil oder alle Pfade im Code des Testobjekts zu durchlaufen. Da reale Programme, wie später noch gezeigt wird, aber oft eine sehr große Anzahl von möglichen Pfaden aufweisen, ist ein Durchlaufen sämtlicher Pfade während des Tests u.U. nicht möglich, zum Beispiel bei Schleifen. Um die bei der Pfadabdeckung notwendigen Testfälle zu identifizieren, orientiert man sich auch hier sinnvollerweise am Kontrollflussgraphen des Testobjekts.

In einem solchen Graphen werden einzelne Anweisungen oder Blöcke von sequenziellen Anweisungen als Knoten, und der Kontrollfluß zwischen Anweisungen oder Blöcken als Kanten (Zweige) dargestellt. Ein Pfad repräsentiert also eine bestimmte Abfolge von Zweigen durch ein Programmstück.

Beispiel:
Gegeben sei wiederum die Methode zur Berechnung der Fakultät einer Zahl x. Da Fakultäten nur von natürlichen Zahlen und Null berechnet werden können, wird der übergebene ganzzahlige Wert dahingehend durch die Methode überprüft, und gegebenenfalls der Fehlercode -1 zurückgegeben.

Anhand des Programmtexts wird nun der zugehörige Kontrollflussgraph abgeleitet:


Abb.: Beispiel eines Kontrollflussgraphen

Ein möglicher Pfad durch diesen Kontrollflussgraphen wird z.B. durch die Kantenabfolge beschrieben, was die Ausnahmebehandlung der Methode bei negativen Werten für x darstellt. Weitere Pfade wären z.B. (Schleife wird nicht durchlaufen, d.h. x ist 0 oder 1) oder (Schleife wird einmal durchlaufen, d.h. x ist 2). Falls die Schleife mehrmals durchlaufen werden soll, so muß ein Rücksprung zum Schleifenanfang über Kante g erfolgen. Der zugehörige Pfad für x gleich 3 ist . Darüberhinaus existieren aber noch weitere Pfade, wie z.B. . Die Anzahl der Schleifendurchgänge kann durch Vergrößern von x solange erhöht werden, bis die maximal darstellbare Zahl für result auf dem Rechner erreicht ist. Daraus wird deutlich, dass bei der Pfadüberdeckung u.U. sehr viele Testfälle gebildet werden, und es stellt sich somit die Frage, welche dieser Testfälle sinnvollerweise ausgewählt werden sollen. Das C2-Abdeckungsmaß schreibt dazu vor, dass Testfälle generiert werden müssen, die
1. enthaltene Schleifen nicht durchlaufen
2. enthaltene Schleifen nicht oft durchlaufen
3. enthaltene Schleifen oft durchlaufen
wobei alle drei Bedingungen durch die Menge der Testfälle abgedeckt werden müssen. Für die Methode entspricht das den folgenden Testfällen:

Der Wert für häufige Schleifendurchläufe wurde hier auf 5039 festgelegt, um die Ausführungsdauer von Testfall #4 zu begrenzen. Die Entscheidung, wie oft eine Schleife im Test durchlaufen werden sollte, hängt jedoch stark vom Testobjekt, der zu Verfügung stehenden Hardware, und dem zu erwartenden Kosten-Nutzen-Verhältnis ab.

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *