Debugging für Profis Branch Coverage für optimierten Code

Code Coverage ist nicht gleich Code Coverage. So gibt es deutliche Unterschiede bei den Messverfahren und der Interpretation der Ergebnisse. Wer auf Nummer sicher gehen will, kommt deshalb nicht am Branch Coverage vorbei. Das aber will richtig verwendet und verstanden sein.

Ganz allgemein betrachtet ist Code Coverage erst einmal nur eine Methode, um während eines Softwaretests festzustellen, ob alle möglichen Programmteile – wahlweise auch alle möglichen Verzweigungen – dabei auch tatsächlich ausgeführt werden, der Test also auch wirklich vollständig ist. Das Code Coverage selbst trifft dabei an sich keine Aussage über die Softwarequalität im Sinne von Fehlerfreiheit und Funktion.

Prinzipiell wird das Code Coverage in verschiedene Stufen unterteilt, wobei sich die Literatur hinsichtlich der Bezeichnungen jedoch nicht immer ganz einig ist. Schaut man beispielsweise in die für die funktionale Sicherheit im Automotive-Bereich bestimmende Norm ISO-26262, so werden dort folgende Coverage-Stufen unterschieden:

Statement Coverage

Das Statement Coverage ermittelt, welcher Programmcode durch die Tests erreicht und damit ausgeführt wurde. Aussagen zu Verzweigungen können daraus nicht abgeleitet werden. Mit Statement Coverage kann zwar auch »dead code«, also nicht ausgeführter Programmcode, aufgespürt werden, insgesamt werden die die aktuellen Anforderungen an die Testqualität aber meistens nicht erfüllt.

Branch Coverage

Beim Branch Coverage wird die Ausführung aller möglichen Programmverzweigungen betrachtet. So muss zum Beispiel eine einfache IF-Anweisung für die Bedingung einmal den Wahrheitswert WAHR und einmal den Wert FALSCH annehmen. Für ein vollständiges Branch Coverage ist automatisch das Statement Coverage ableitbar, da implizit alle Anweisungen erreicht werden müssen.

MC/DC (Modified Condition/Decision Coverage)

Beim MC/DC ist vorgegeben, dass für einen umfassenden Test alle in zusammengesetzten Bedingungen enthaltenen Einzelbedingungen jeweils beide Wahrheitswerte annehmen. Dies stellt sicher, dass jede Einzelbedingung auch unabhängig von den anderen beteiligten Einzelbedingungen das Gesamtergebnis bestimmt. Insbesondere für Schleifen mit bedingtem Code ist MC/DC in der Praxis allerdings ein äußerst aufwendiges Verfahren.

Für welche der eben genannten Coverage-Stufen der Nachweis durch den Test erbracht werden muss, hängt von der Sicherheitsrelevanz des zu testenden Moduls ab. Die ISO 26262 beispielsweise definiert diese Sicherheitsrelevanz über »Automotive Safety Integrity Levels« (ASIL). Darauf basierend erfolgt der Nachweis der einzelnen Coverage-Stufen, jedoch nur als Empfehlung (Tabelle). Dabei wird speziell dem als »highly recommended« eingestuften Branch Coverage eine hohe Bedeutung beigemessen. Auch andere Normen wie die für den Luftfahrtbereich wichtige DO-178C verlangen für mittlere bis höhere Softwarelevels – vergleichbar mit den ASILs – einen entsprechenden Nachweis. Deshalb fokussiert sich der Beitrag in den folgenden Abschnitten auf das Branch Coverage, und zwar speziell im Hinblick auf dessen Gewinnung durch Trace auf realer Hardware und den daraus resultierenden Besonderheiten und Herausforderungen bei optimiertem Code.