Eine Zusammenfassung der Coverage-Ergebnisse unterschiedlicher Varianten ist nur auf Zeilenbasis der ursprünglichen Quelldatei möglich. Aus der Analyse des Source-Codes jeder Variante kann ermittelt werden, welche Zeilen der ursprünglichen Quelldatei zu einem Statement/Branch oder zu einer Bedingung in dieser Variante gehören. Die Zeilen können daher wie folgt bewertet werden:
Auf diese Art können nicht getestete Codezeilen einfach entdeckt werden. In Bild 4 ist das Ergebnis der Hyper-Coverage auf Source-Codeebene dargestellt.
Der gelb markierte Teil zeigt einen Codebereich, für den entweder keine Tests vorhanden sind oder die Tests nicht ausgeführt wurden. Die rot markierten Teile zeigen fehlende Coverage aus unterschiedlichen Coverage-Testarten. Für die unten aufgelistete Funktion »func3« wurden genügend Tests durchgeführt, sodass die geforderte Code-Coverage erreicht wurde.
Der Vorteil der Hyper-Coverage besteht darin, dass zwar eine zeilenbasierte Auswertung vorgenommen wird, aber die zugrundeliegenden Coverage-Ergebnisse aus der gewählten Coverage-Art vollständig berücksichtigt werden. Wenn beispielsweise MC/DC-Coverage gefordert ist, dann muss für eine Zeile mit einer komplexen Bedingung in allen Varianten eine vollständige MC/DC-Coverage erreicht werden, damit die Zeile als erfolgreich bewertet gilt.
Die Ergebnisse aus einer erweiterten Analyse der Quelldateien können neben der Nutzung der Coverage-Ergebnisse auch zur Optimierung des Regressionstests benutzt werden. Ein optimierter Regressionstest von Software spart Zeit und Ressourcen und ermöglicht kontinuierliches Testen im Entwicklungsprozess. Wichtig ist die korrekte Erfassung von Abhängigkeiten, sodass nur die relevanten, aber vor allem auch die unbedingt notwendigen Tests wiederholt werden.
Codeänderungen nur aufgrund von dateibasierten Prüfungen der Quell- und Header-Dateien zu erkennen, ist in der Regel zu grob, weil z. B. die Änderungen eines globalen Headers dazu führen würden, dass alle Tests wiederholt werden müssten.
Aufgrund der oben geschilderten Source-Codeanalyse stehen deutlich genauere Informationen zur Erkennung von Änderungen zur Verfügung. Jede einzelne Funktion oder Methode kann sowohl textuell in der präprozessierten Datei auf Änderungen geprüft als auch zusätzlich auf Änderungen im Funktions-Interface geprüft werden. Ein Beispiel ist in Bild 5 dargestellt, dort ändert sich der Wert des Präprozessor-Makros »PI« von einer Version der Software zur nächsten Version. Dadurch ändert sich der präprozessierte Code der Funktion, obwohl sich der Originalcode der Funktion nicht geändert hat. Die Tests für diese Funktion müssen also eindeutig erneut durchgeführt werden.
Für die Ermittlung, welche Funktionen beim Regressionstest einer neuen Softwareversion erneut getestet werden müssen, sind folgende Prüfungen notwendig:
Eine solchermaßen eingeschränkte Liste von erneut durchzuführenden Tests ist in einem Continuous-Integration-Prozess sinnvoll, um die Gesamtlaufzeit der Tests bei häufigen Testläufen möglichst klein zu halten, z. B. zur Verifikation von Codeänderungen vor dem Commit. Für ein neues Release einer Software wäre trotzdem eine Durchführung aller verfügbaren Tests anzuraten, da sich niemals ausschließen lässt, dass im Analyseprozess ggf. notwendige Regressionstests übersehen wurden.
Eine Zertifizierung sicherheitskritischer Software erfordert umfangreiche und normgerechte Tests aller Funktionen. Die Vollständigkeit der Tests wird unter anderem über die Code-Coverage nachgewiesen – bei Softwarevarianten auch für alle Codevarianten. Mit einer erweiterten Analyse der Quelldateien lassen sich wertvolle Informationen gewinnen, um nach kleineren Codeänderungen insgesamt weniger Tests erneut durchführen zu müssen. Auch die Erkennung von identischen Codeanteilen in Varianten ermöglicht ein Zusammenfassen von Coverage-Ergebnissen aus verschiedenen Tests und damit eine schnellere Erreichung der gewünschten Codeabdeckung. Die mehrfache Nutzung von Tests in Varianten mit jeweils erweiterten oder angepassten Testdaten verringert ebenfalls den Aufwand für die Testerstellung.
Die Ermittlung einer Hyper-Coverage aus den verfügbaren Coverage-Ergebnissen erlaubt eine vollständige Sicht der Testabdeckung auf Quelldateiebene, ohne die spezifischen Coverage-Anforderungen der Standards und Normen für die Entwicklung sicherheitskritischer Software zu verwässern. Im Gegenteil: Mit der Hyper-Coverage lassen sich zuverlässig nicht getestete Stellen in den originalen C/C++-Quelldateien erkennen.
Der Autor
Michael Wittner
ist Diplom-Informatiker und Geschäftsführer von Razorcat Development. Er arbeitet seit mehr als 25 Jahren im Bereich Softwareentwicklung und Test.
Nach dem Studium der Informatik an der TU Berlin entwickelte er als wissenschaftlicher Mitarbeiter bei Daimler Testmethoden und Testwerkzeuge. Seit 1997 ist er geschäftsführender Gesellschafter von Razorcat Development, dem Hersteller des Unit-Testtools TESSY und CTE sowie des Testmanagement-Tools ITE und der Testspezifikationssprache CCDL.