Die häufigsten Irrtümer über Code-Coverage
Anbieter zum Thema
Über die Ermittlung und den Nutzen von Code-Coverage sind zahlreiche Halbwahrheiten und Irrtümer verbreitet. Der folgende Beitrag klärt über die häufigsten Fehlannahmen auf.

Sicherheitskritische Produkte benötigen eine Zertifizierung nach Standards wie DO-178, IEC 61508, ISO 26262 oder ähnlichen. Deshalb besteht für die Software der Produkte der Bedarf, die durch die Tests erreichte Code-Coverage nachzuweisen. Doch sind leider in der Praxis immer noch zahlreiche Fehlannahmen oder Halbwahrheiten weit verbreitet, wenn es um die Ermittlung dieser Maße geht. Damit soll dieser Beitrag aufräumen. Im Folgenden werden die 13 am häufigsten anzutreffenden Irrtümer hinsichtlich der Code-Coverage einmal näher erläutert.
Irrtum 1: Man kann immer 100% erreichen
Dies ist – natürlich – nicht der Fall. Es lassen sich leicht Fälle aus der Praxis finden, bei denen bedingt durch die Struktur des Codes oder die Zusammensetzung von Entscheidungen nicht 100% erreicht werden können.
Im folgenden ist ein Code-Schnipsel dargestellt, bei dem 100% Zweigabdeckung nicht erreicht werden kann (siehe auch Bild 1). Dabei handelt es sich um ein Beispiel aus der Praxis, das hier vereinfacht dargestellt ist:
switch (i&3)
{
case 0:
f0();
break;
case 1:
f1();
break;
case 2:
f2();
break;
case 3:
f3();
break;
}
Woran das liegt? Am fehlenden Ansprung der default-Marke in der Switch-Anweisung. Der Ausdruck (i&3) kann nur die Werte von 0 bis 3 annehmen. Das heißt, es wird immer eine der case-Marken angesprungen, aber nie die default-Marke. Dieser default-Zweig existiert immer, egal ob er explizit programmiert wurde oder nicht, so wie hier.
Irrtum 2: Ein Coverage-Maß hat nur einen Namen
Leider nein. Je nach Standard, Buch, Werkzeug oder Web-Seite werden für ein und dasselbe Maß unterschiedliche Namen verwendet.
Beispielweise verwendet [SPILLNER 2003] den englischen Begriff „modified branch condition decision testing“ für Minimale Mehrfachbedingungsüberdeckung, während [LIGGESMEYER] dieses Maß (mehr an die deutsche Bezeichnung angelehnt) „minimal multiple condition coverage“ nennt.
Auch in Büchern ein und desselben Autors finden sich in unterschiedlichen Auflagen unterschiedliche Bezeichnungen. So wird in [SPILLNER 2003] der Mehrfachbedingungsüberdeckungstest „branch condition combination testing“ genannt, während er in [SPILLNER 2012] „multiple condition testing“ heißt.
Irrtum 3: Ein Name bezeichnet immer dasselbe Coverage-Maß
Leider auch nicht. Insbesondere wenn Abkürzungen wie C0, C1, C2 oder gar C1+ verwendet werden, ist Vorsicht geboten. So verwendet beispielsweise [BEIZER] C1 zur Bezeichnung der Anweisungsüberdeckung, während [SPILLNER 2003 und 2012] C0 hierfür verwendet.
Irrtum 4: Es ist klar, wie Coverage gemessen wird
Durchaus nicht. In den Bildern 2 und 3 sind einige Zweifelsfälle aufgeführt: links zu sehen ist jeweils das fragliche Code-Schnipsel, und rechts das Messergebnis des Unit-/Modul-Testwerkzeugs TESSY [TESSY].
Die Switch-Anweisung auf der linken Seite in Bild 2 könnte aus zwei oder aus vier Zweigen bestehen. Falls nur zwei Zweige gezählt werden, führt zu den Marken „case 0“, „case 1“ und „case 2“ ein- und derselbe Zweig. Falls jedes Label als eigener Zweig gezählt wird, gibt es vier Zweige. Der Unterschied wird deutlich, wenn ein Testfall mit (i==1) ausgeführt wird. Ergeben sich dadurch 25% oder 50% Zweigüberdeckung? Auf der rechten Seite von Bild 2 erkennt man, dass für TESSY die Switch-Anweisung aus vier Zweigen besteht; der Testfall ergibt 25% Zweigüberdeckung (und nicht 50%). Begründet werden kann dies damit, dass anstelle der Zuweisung „a = 700“ ja auch z.B. „a = 1/(2-i)“ stehen könnte. Dann würde ein Testfall mit (i==2) zur Division durch 0 führen. Ein solcher Testfall kann aber leicht unterbleiben, wenn schon mit (i==1) die vollständige Coverage erreicht wird.
Eigentlich wählt der Fragezeichenoperator in Bild 3 nur zwischen Werten aus, die dann zugewiesen werden. Muss man hierfür einen oder zwei Zweige zählen? Auf der rechten Seite ist das Ergebnis der Ausführung eines Testfalls dargestellt, bei dem (a > b) war. Man erkennt, dass für TESSY der Fragezeichenoperator zwei Zweige besitzt, und durch den einen Testfall ein Zweig ausgeführt wurde, der andere jedoch nicht. Als Begründung für diese Zählweise kann man sich leicht ein Beispiel analog dem vorhergehenden Beispiel überlegen, z.B. indem man eine Zuweisung „ret_val = 1/(ret_val-b)“ nach der Zuweisung mit dem Fragezeichenoperator annimmt.
Irrtum 5: Für die Coverage ist es egal, wie der Code formuliert ist
Nein. Auch zwei funktional gleichwertiger Code-Schnipsel (d.h. die zu einer bestimmten Eingabe immer das gleiche Ergebnis liefern) in derselben Programmiersprache können zur Erreichung eines bestimmten Coverage-Maßes eine unterschiedliche Anzahl von Testfällen erfordern.
Der linke und der rechte Code-Schnipsel in Bild 4 ist jeweils funktional äquivalent. Trotzdem braucht man beispielsweise zur Erreichung von 100% Zweigabdeckung im Beispiel auf der linken Seite nur zwei Testfälle, während im anderen Beispiel sieben Testfälle notwendig sind.
Durch geeignete Programmierung kann man also sogar vermeiden, dass ein bestimmtes Coverage-Maß überhaupt geprüft werden muss. Wenn beispielsweise der gesamte Code wie rechts zu sehen formuliert ist – also ohne Verwendung von logischem UND und ODER– kann man aus 100% Zweigabdeckung beispielsweise 100% Bedingungsabdeckung (z.B. MC/DC) folgern, ohne letztere explizit zu messen.
Irrtum 6: Alles wird leichter mit„geschickter Programmierung“
Dies scheint eine Schlussfolgerung aus dem zuletzt behandelten Irrtum zu sein. Leider ist diese Schlussfolgerung nicht unbedingt richtig. Betrachten wir hierzu einmal das Beispiel in Bild 5.
Auf den ersten Blick sieht es so aus, als seien zur Erreichung von 100% MC/DC für den Code-Schnipsel auf der linken Seite nur zwei Testfälle notwendig, einer, bei dem decision zu wahr und einer, bei dem decision zu falsch evaluiert, weil der Programmierer die zusammengesetzte Bedingung geschickt „ausgelagert“ hat. Aber auf der rechten Seite ist zu erkennen, dass TESSY die zusammengesetzte Bedingung in der Zuweisung erkennt und deshalb drei Testfälle zur Erreichung von 100% MC/DC notwendig sind. Das ist auch sinnvoll, denn sonst könnte man durch Umformulierungen im Code die Coverage-Messung unterlaufen.
Setzen Sie ein Coverage-Messwerkzeug ein? Wissen Sie, wie dieses Werkzeug den obigen Fall behandelt?
Irrtum 7: Es reicht, Testfälle zur vollständigen Code-Abdeckung aus dem Code abzuleiten
Man kann natürlich aus dem zu testenden Code Testfälle ableiten, mit denen man eine 100% Code-Coverage erreicht. Es gibt sogar Werkzeuge, die dies automatisch für einen erledigen. Allerdings muss man sich dabei zweier Dinge bewusst sein:
- Durch aus dem Code abgeleitete Testfälle kann man keine Auslassungen im Code entdecken! Wurde beispielsweise vergessen, eine Abfrage zu implementieren, kann natürlich aus dem Code auch kein Testfall abgeleitet werden, der diese Abfrage prüft. Auch wenn man 100% Coverage erreicht, ist die Testaussage zweifelhaft, denn der Code wurde als vollständig vorausgesetzt.
- Das Ergebnis von automatisch abgeleiteten Testfällen sollte explizit überprüft werden. Unterlässt man dies, werden bei ihrer Ausführung nur schwerwiegende Probleme des Testobjekts, beispielsweise Abstürze, erkannt. Die Ableitung der Testergebnisse aus dem Code, bzw. die Hinnahme der Ergebnisse, die durch die Ausführung der aus dem Code abgeleiteten Testfälle erhalten werden, reduziert die Testaussage erheblich, denn dabei wird der Code als korrekt vorausgesetzt.
Irrtum 8: Code-Coverage misst die Qualität des Codes
Eigentlich nicht. Das einzige, was man sagen kann: Je höher die Prozentzahl der Code-Coverage für ein bestimmtes Coverage-Maß ist, umso besser ist es im Hinblick auf dieses Coverage-Maß getestet. Wenn 100% für ein bestimmtes Maß erreicht sind, heißt das nicht, dass man ausreichend getestet hat.
Irrtum 9: Code-Coverage misst die Qualität der Testfälle
Nicht immer. Als Beispiel betrachten wir eine Funktion, die den Sinus berechnet (siehe auch Bild 6):
double sinus(double x_deg)
{
int i;
double temp, x_rad;
int sign = -1;
x_rad = x_deg / 180 * pi;
temp = x_rad;
for(i=3); i<=(MAX_FAC-2); i+=2)
{
temp += sign * pot(x_rad,i) / fac(i);
sign *= -1;
}
return(temp);
}
Für die hier gezeigte Funktion genügt ein einziger Testfall, beispielsweise mit dem Eingabewert 0 (für x_deg), um 100% Zweigüberdeckung, 100% Modified Condition / Decision Coverage (MC/DC) und 100% Multiple Condition Coverage (MCC) zu erhalten. Als Ergebnis wird 0, der richtige und erwartete Sinus-Wert zurückgegeben. Aber der ausgeführte Testfall ist weder ein aussagekräftiger Testfall, noch ist ein einziger Testfall ausreichend, auch wenn 100% Coverage erzielt wird. Man braucht unbedingt weiter Testfälle, um z.B. herauszufinden, ob auch für 10 Grad der richtige Sinus-Wert berechnet wird.
Irrtum 10: Mit 100% MC/DC ist die Software fehlerfrei
Es ist zwar richtig, dass Modified Condition / Decision Coverage (MC/DC) eines der anspruchsvolleren Code-Coverage-Maße ist, das z.B. bei DO-178 für Produkte auf Level A (dem sicherheitskritischsten Level) nachgewiesen werden muss.
Allerdings sind zur Erreichung von 100% MC/DC normalerweise mehr Testfälle notwendig als für weniger anspruchsvolle Maße, beispielsweise Zweigabdeckung, d.h. der Testaufwand steigt.
Lohnt sich dieser erhöhte Testaufwand? Ja, wenn man unbegrenzten (Zeit-) Aufwand ins Testen stecken kann. Allerdings ist das Budget für’s Testen in realen Projekten üblicherweise doch sehr begrenzt. Deshalb sollte sich ein Projektleiter fragen, ob er das begrenzte Budget zur Erreichung von 100% MC/DC verwenden will, oder ob er es nicht besser in andere Tests investiert, beispielsweise in Reviews, Mutationstests oder statische Analyse. Denn auch 100% MC/DC garantieren keinen fehlerfreien Code, weil beispielsweise MC/DC wie jedes andere Code-Coverage-Maß unempfindlich gegenüber Fehler in Berechnungen ist.
Irrtum 11: Für die Coverage ist es egal, wie man eine zusammengesetzte Entscheidung formuliert
Die beiden zusammengesetzten Entscheidungen in Bild 7 sind funktional gleichwertig. Das heißt, das Ergebnis ist für alle möglichen Eingabekombinationen gleich. Allerdings ergeben sich (in der Programmiersprache C) Unterschiede in Bezug auf die Code-Coverage. Beispielweise sind im linken Beispiel fünf Testfälle notwendig, um 100% Multiple Condition Coverage zu erreichen; wohingegen es auf der rechten Seite nur vier sind.
Das liegt an der unvollständigen Evaluierung von Entscheidungen in der Programmiersprache C, denn sobald der Compiler weiß, wie das Gesamtergebnis lautet, kann er die Auswertung des Ausdrucks abbrechen („short-circuit operation“). Deshalb gibt es für das rechts zu sehende Beispiel vier mögliche Testfälle, die dann für 100% MCC ergeben. Da der C-Compiler Entscheidungen immer von links nach rechts evaluiert, wird die Wahl der rechten Formulierung im Mittel zu einer schnelleren Ausführung des Programms führen.
Irrtum 12: Für die Coverage spielt die Programmiersprache keine Rolle
Ist die Anzahl der Testfälle zur Erzielung eines bestimmten Coverage-Maßes unabhängig von der Programmiersprache? Wir betrachten den Ausdruck „A und B“, einmal in der Programmiersprache Pascal und einmal in der Programmiersprache C (siehe auch Bild 8).
Im gezeigten Bild sind die möglichen Testfälle in den jeweiligen Programmiersprachen angegeben. Um 100% einfache Bedingungsüberdeckung (jede Bedingung muss einmal wahr und einmal falsch sein) zur erreichen, benötigt man im Fall der Programmiersprache Pascal nur zwei Testfälle (im Beispiel Nr. 2 und Nr. 3), wohingegen im Fall der Programmiersprache C drei Testfälle notwendig sind (I, II, III). Die Ursache ist, dass Pascal eine Programmiersprache mit vollständiger Evaluierung ist und C nicht. Deshalb werden in C die Testfälle Nr. 1 und 2 zusammengefasst.
Irrtum 13: Zweigabdeckung subsumiert Anweisungsüberdeckung, also folgt aus 50% C1 auch 50% C0
Natürlich nicht. Wird etwa für den folgenden Code-Schnipsel ein einziger Testfall ausgeführt, erhält man 50% Zweigüberdeckung, aber nicht 50% Anweisungsüberdeckung.
if (decision)
{
a++;
a++;
}
else
{
a++;
}
Das liegt daran, dass die beiden Zweige eine unterschiedliche Anzahl von Anweisungen enthalten.
Was sollte man für das bestmögliche Ergebnis beachten?
Vergewissern Sie sich immer, dass Ihr Gesprächspartner unter einer Bezeichnung auch dasselbe Maß versteht wie Sie selbst, wenn es um das Thema Code-Coverage geht.
Wenn Sie ein Werkzeug zur Messung der Code-Coverage einsetzen: Prüfen Sie, wie das Werkzeug die geschilderten Zweifelsfälle behandelt.
Prüfen Sie außerdem, ob der Aufwand, den Sie zur Erreichung von z.B. 100% MC/DC erbringen müssen, im richtigen Verhältnis zu der dadurch erreichbaren verbesserten Testaussage steht, oder ob der Aufwand besser für andere Testaktivitäten verwendet werden sollte.
Schlussendlich sollten die oben gezeigten Beispiele auch eines klar machen: Lehnen Sie sich nicht entspannt zurück, nur weil Sie 100% Code-Coverage erreicht haben!
:quality(80)/images.vogel.de/vogelonline/bdb/827000/827020/original.jpg)
Code-Coverage undercover: Nutzen und Tücken Trace-basierter Codeabdeckung
:quality(80)/images.vogel.de/vogelonline/bdb/1408400/1408476/original.jpg)
Die zwei großen Fallen bei der Code Coverage
:quality(80)/images.vogel.de/vogelonline/bdb/1440200/1440228/original.jpg)
Code Coverage bei Embedded Systemen
Literatur
[TESSY] More about TESSY.
[SPILLNER 2003] Spillner, A., Linz, T.: Basiswissen Softwaretest, Heidelberg, 1. Auflage 2003. dpunkt-Verlag.
[SPILLNER 2012] Spillner, A., Linz, T.: Basiswissen Softwaretest, Heidelberg, 5. Auflage 2012. dpunkt-Verlag.
[LIGGESMEYER] Liggesmeyer, Peter: Software-Qualität: Testen, Analysieren und Verifizieren von Software. Heidelberg, Berlin, 2002. Spektrum Akademischer Verlag.
[BEIZER] Beizer, Boris: Software Testing Techniques, 2nd edition, New York, 1990.
[DO-178B] Software Considerations In Airborne Systems And Equipment Certification, RTCA, 1992.
[IEC 61508] Functional safety of electrical/electronic/programmable electronic safety-related systems, IEC.
[ED-94B] Final report for clarification of ED-12B DO-178B “Software considerations in airborne system and equipment certification”, Eurocae, 2001
* Frank Büchner ist Diplom-Informatiker und Principal Engineer Software Quality bei der Firma Hitex GmbH in Karlsruhe.
(ID:46165563)