Beim Test von Software-Varianten sind sicherheitsrelevante Normen wie die ISO 26262 zu berücksichtigen. Sicherheitskritische Applikationen müssen bei einer Fehlfunktion weiter funktionieren. Darüber hinaus lassen sich mit den Tests sowohl überflüssige Arbeiten als auch Nachbesserungen vermeiden.
Die Herausforderung beim Testen von Software-Varianten besteht darin, dass jede Variante vollständig getestet werden muss. Nachfolgend wird eine Methode zur Wiederverwendung und Vererbung von Variantentests vorgestellt. Über die Definition von Basistests, die an Variantentests vererbt werden, kann redundante Arbeit vermieden werden. Bei jeder Änderung der Applikation müssen die Tests nur an einer Stelle gepflegt werden.
Sicherheitskritische Normen der verschiedenen Industriezweige, wie die ISO 26262 für die Automobiltechnik oder die IEC 62304 für die Medizintechnik verlangen beim Test eine vollständige Code-Abdeckung (Code-Coverage). Das bedeutet, dass jede Software-Variante vollständig getestet werden muss. In der Praxis geschieht das oft durch Kopieren der Tests einer Variante und der Anpassung der kopierten Tests an die jeweils andere Variante.
Neue Anforderungen oder Änderungen der Software verteuern einen solchen Test der Varianten aufgrund redundant durchzuführender Änderungen in allen Varianten. Neben dem hohen Aufwand bei der Pflege und Erweiterung solcher Tests können sich zum Beispiel durch Copy&Paste sehr leicht Fehler einschleichen, durch die letztendlich auch sicherheitskritische Fehler in der Applikation unentdeckt bleiben können.
Was ist eine Variante?
Es gibt verschiedene Möglichkeiten, Software-Varianten zu erstellen, zum Beispiel C/C++ Source Code:
Eine Software-Variante ist durch eine bestimmte Konfiguration eines Software-Moduls, beispielsweise einer C-Quelldatei, definiert. Diese Variante muss nicht notwendigerweise funktional sein, es kann sich auch um eine abstrakte Variante handeln. Erst durch spezifische Einstellungen – in der Regel über Defines – werden aus einer abstrakten Basis-Variante die tatsächlich verwendbaren Software-Varianten.
Testziel: Code-Coverage
Für die vollständige Code-Abdeckung jeder Variante könnte das Messergebnis der Code-Coverage des variantenspezifischen Codes mit dem Messergebnis des gemeinsam genutzten Codes zusammengezählt werden. In Bild 1 ist ein einfaches Beispiel einer Code-Variante dargestellt, bei der zur Variable „level“ noch ein weiterer Wert aufaddiert werden soll.
Der gelb markierte Programmierfehler, nämlich das Fehlen des Additionsoperators in der Zeile 16, könnte unentdeckt bleiben, wenn der gemeinsam genutzte Code aus den Zeilen 19 bis 23 nicht auch in der Variante getestet wird.
Es reicht daher nicht, einzelne Teile eines mit Hilfe von Defines zusammengesetzten Varianten-Codes zu testen und die Messergebnisse der Code Coverage zusammenzuzählen: Jede Code-Variante ist wie ein eigenständiges Programm zu sehen, da ausgeblendete oder dazugekommene Teile die gemeinsamen Teile beeinflussen können.
Anhand eines Beispiels wird im Folgenden eine Methode zur Erstellung und Pflege von Variantentests vorgestellt. Das Beispiel behandelt eine Funktion zur Statusanzeige des Tankinhalts verschiedener Fahrzeugvarianten, Pkw und Lkw. Erschwerend kommt hinzu, dass die Fahrzeugvarianten „Lkw“ mit einem Zusatztank ausgestattet sein können, dessen Pegelstand ebenfalls berücksichtigt werden soll.
Beispielfunktion
Als Beispiel soll eine Funktion dienen, die bezogen auf den Füllstand des Tanks eines Fahrzeugs einen Status zurückliefert.
Die Spezifikation ist in Bild 2 in grafischer Form gegeben: Die Funktion soll eine Warnung oder einen Alarm zurückgeben, wenn jeweils ein definierter Pegelstand unterschritten wird. Ansonsten liefert die Funktion den Wert „Normal“.
Eine einfache Implementierung dieser Funktion könnte wie in Bild 3 dargestellt aussehen. Über die Varianten-Konfiguration – #define.