Ü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.
Methode mit zugeordnetem Kontrollflussgraphen
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.
Kontrollflussgraph mit markierten ausgeführten Knoten
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.
Kontrollflussgraph mit markierten ausgeführten Kanten
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