Suchen

Komponententest für sicherheitsrelevante Software

| Autor / Redakteur: Reinhold Schmid * / Franz Graser

Bei Komponententests werden die Einzelteile eines Softwaresystems auf ihre Korrektheit getestet. Zur Zeit erfolgen diese Tests noch überwiegend händisch. Der Artikel stellt einen Automatisierungsansatz vor.

Firma zum Thema

Bild 1: Beim Testwerkzeug GAIO CoverageMaster wird die zu testende Software auf einem MPU-Simulator ausgeführt. Das Erstellen einer speziellen Testapplikation ist nicht nötig. Die Verwendung des MPU-Simulators erlaubt es, die Ausführung des Programmcodes detailliert zu überwachen.
Bild 1: Beim Testwerkzeug GAIO CoverageMaster wird die zu testende Software auf einem MPU-Simulator ausgeführt. Das Erstellen einer speziellen Testapplikation ist nicht nötig. Die Verwendung des MPU-Simulators erlaubt es, die Ausführung des Programmcodes detailliert zu überwachen.
(Bild: GAIO)

Bei der Entwicklung von Systemen und Komponenten, von deren Funktion die Sicherheit der Benutzer abhängt, verlangt der Gesetzgeber die penible Einhaltung von Vorschriften und Standards. Speziell im Automobilbereich, wo das Versagen sicherheitsrelevanter Systeme (Bremsen, Lenkung, Rückhaltesysteme) katastrophale Folgen haben kann, werden strenge Maßstäbe angelegt.

So schreiben Standards wie IEEE 829, IEEE 61508 oder ISO 26262 zwingend vor, dass jede Software vor ihrem Einsatz in solchen Systemen auf funktionaler Ebene zu testen ist. Um einen solchen Komponententest sachgerecht vornehmen zu können, sind zunächst Testumgebung und Teststrategien zu entwickeln sowie Testziele zu formulieren.

Bei der Ausarbeitung des Vorgehens ist es ratsam, sich an den Richtlinien des Software Testing Qualifications Board (ISTQB) zu orientieren. Demach dient der Komponententest dem Aufspüren von Programmfehlern und der Verifikation von Softwaremodulen, Objekten, Klassen und Ähnlichem, sofern sie getrennt vom Rest des Systems testbar sind. Der Test von Komponenten erfolgt mit einer Entwicklungsumgebung. Dabei sollten die Entwickler beteiligt sein, die den zu testenden Code geschrieben haben.

Programmfehler sollen unmittelbar behoben werden

Wird ein Programmfehler identifiziert, soll er laut ISTQB unmittelbar behoben werden, ohne ein formales Fehlermanagement einzuschalten. Aus dieser Definition wird deutlich, dass der Komponententest als integraler Bestandteil des Entwicklungsprozesses zu verstehen ist und eine geeignete Test- und Debugging-Vorrichtung erfordert.

In der Praxis erfolgen Komponententests nur zu einem geringen Teil automatisiert. Der weitaus größere Teil wird händisch erledigt. Das führt dazu, dass viele Fehler nicht während dieser Phase des Entwicklungsprozesses entdeckt werden, sondern erst später in der Phase der Systemintegration ans Licht kommen.

Grundsätzlich gilt: Je später im Entwicklungsprozess ein Fehler entdeckt wird, desto teurer kommt es, ihn zu beheben. Zudem verschlechtert diese Vorgehensweise die Effizienz des Entwicklungsprozesses, während zugleich die Codequalität sinkt.

Die verpflichtende Anwendung von Standards zur funktionalen Sicherheit wie IEC61508 und ISO 26262 ist ein starkes Motiv, der traditionellen Vorgehensweise den Rücken zu kehren und eine stringente Haltung hinsichtlich der Komponententests einzunehmen. Dazu bietet sich der Einsatz des Komponententest-Simulators CoverageMaster winAMS von GAIO Technology an. Die Software unterstützt Entwicklungsabteilungen bei der Erstellung von Teststrategien und erlaubt weitgehend automatische Tests bei Software, die in C und C++ entwickelt wurde.

Vor allem in der Automobilindustrie erfährt dieser Simulator mittlerweile eine hohe Akzeptanz, was nicht zuletzt auf die Einführung von Standards zur Funktionalen Sicherheit wie ISO 26262 zurückzuführen ist. Dieser Standard enthält viele verpflichtende Vorgaben hinsichtlich der funktionalen Sicherheit bei der Abarbeitung des bekannten V-Modells.

Zu diesen Vorgaben gehören auch die Regeln zum Testen von Komponenten. Unternehmen, die diese Vorgaben bereits umgesetzt haben und die Empfehlungen des Standards IEEE 829 zur strukturierten Dokumentation von Software-Lifecycles befolgen, haben in der Regel wenig Probleme mit der Implementierung von Komponententests. Organisationen, die keine klare Grenze zwischen Komponententests und Debugging ziehen, werden sich dagegen wahrscheinlich mit standardgerechten Tests zu Beginn nicht leicht tun. Typischerweise sind drei Hindernisse zu überwinden:

  • Widerstand auf psychologischer Ebene seitens der Entwickler gegen die Übertragung zusätzlicher Aufgaben.
  • Widerstand der Leitungsebene angesichts zusätzlicher Kosten.
  • Einrichten der für das Testen notwendigen Infrastruktur und Prozesse.

Die Einführung von Softwaretests auf der Komponentenebene ist leichter zu verstehen, wenn man das zu entwickelnde Produkt mit einem mechanischen System vergleicht: Beim Bau mechanischer Systeme ist es selbstverständlich, die Komponenten vor der Montage auf Fehler zu inspizieren. Erst wenn die Fehlerfreiheit aller mechanischen Bauteile festgestellt ist, erfolgt die Montage.

Kann diese Fehlerfreiheit nicht festgestellt werden, kann auch keine Garantie für die Funktion des Gesamtsystems übernommen werden. Diese Betrachtung gilt es auf Softwaresysteme und -komponenten zu übertragen. Es genügt indes nicht, den Entwicklern diese Betrachtungsweise näher zu bringen. Selbst wenn sie im Team akzeptiert ist, sind weitere psychologische Hürden zu überwinden. Die Vorstellung, dass Komponententests eine zusätzliche Belastung darstellen, kann der korrekten Ausführung der Tests entgegenwirken. Als Belastung werden vor allem folgende fünf Aufgaben empfunden:

  • Ausarbeitung des Testkonzepts,
  • Ausführung der Tests,
  • Abdeckungserfassung,
  • Zusammenfassung der Ergebnisse in einem Testbericht,
  • Beheben von im Test entdeckten Fehlern.

Je nach Testgegenstand können manche Aufgaben lediglich Zeit in Anspruch nehmen, während andere die Anwendung testbezogener Techniken erfordern. Der richtige Einsatz der GAIO-Tools spart Zeit und eröffnet zusätzliche Möglichkeiten.

Überblick über die Tools für den Komponententest

CoverageMaster winAMS (CM) ist ein Werkzeug für den Test von Embedded-Softwarekomponenten, die in C/C++ geschrieben wurde. Zum Testen führt es den Softwarecode (bzw. die darin beschriebenen Funktionen) aus. Hierbei verwendet es einen MPU-Simulator, der den Objekt-Code der zu testenden Komponenten in unveränderter Form verarbeitet.

Bild 2: Die Kopplung von GAIO CoverageMaster mit CasePlayer2, einem Tool zur statischen Programmanalyse, erlaubt die automatische Erzeugung von Testdaten für die Abdeckungsanalyse.
Bild 2: Die Kopplung von GAIO CoverageMaster mit CasePlayer2, einem Tool zur statischen Programmanalyse, erlaubt die automatische Erzeugung von Testdaten für die Abdeckungsanalyse.
(Bild: GAIO)

Dieser Ansatz erlaubt es, das Verhalten der zu testenden Software zu verifizieren und auf Fehler zu überprüfen. Coverage Master winAMS enthält neben dem eigentlichen Simulator einen Prozessorsimulator für diverse MPUs (Micro Processor Unit) sowie das User Interface SSTManager. Zudem wird ein Cross-Compiler bzw. ein Integrated Development Environment (IDE) benötigt.

Weil unter CM die zu testende Software auf einem MPU-Simulator ausgeführt wird, ist das Erstellen einer speziellen Testapplikation nicht nötig. Die Verwendung von Objektdateien ist als geeignetes Verfahren zum Test sicherheitsrelevanter Produkte anzusehen.

Die ISO 26262 verlangt nicht nur, dass die Softwarekomponente alle spezifizierten Funktionen korrekt ausführt. Sie darf zudem keine unerwünschten Funktionen enthalten. Der Zweck eines Komponententests besteht daher nicht nur im Ausmerzen von Programmfehlern - die ließen sich in der Tat auch in der Integrationsphase der Software eliminieren. Vielmehr geht es darum, vor der Integration von Hardware und Software die Korrektheit der Software zu verifizieren.

Zudem verlangt die ISO 26262, für den Test erforderliche Modifikationen an der Software zu dokumentieren und die Änderungen ebenfalls zu verifizieren. CM ermöglicht den Test ohne jede Modifikation; auch externe Interrupts der Zielumgebung und Pointer Arrays als Testdaten können verwendet werden. Die Verwendung eines MPU-Simulators erlaubt es zudem, die Ausführung des Programmcodes detailliert zu überwachen.

Die Kopplung von CM mit CasePlayer2, einem Tool zur statischen Programmanalyse, erlaubt eine automatische Erzeugung von Testdaten für die Abdeckungsanalyse, was den Aufwand für das Testdesign weitgehend verringert. Neben diesem White-Box-Test unterstützt CM auch so genannte Black-Box-Tests, bei denen der Tester keinen Zugang zum Quellcode besitzt. Solche Tests dienen dazu, um die Übereinstimmung der Software mit den Anforderungen zu überprüfen.

Testausführung und Abdeckungserfassung

Im Vergleich mit Komponententests, bei denen der Testingenieur auf der IDE Testfälle manuell einrichten und vor dem Testablauf im Debugger Break Points setzen muss, lässt sich der Testablauf bei Verwendung der GAIO-Umgebung weitgehend automatisieren. Auf diese Weise werden Fehler vermieden, die sich bei manuellem Vorgehen in die Testkonfiguration einschleichen können. Testfunktionen, Variablennamen und Testdaten lassen sich zur erneuten Verwendung abspeichern.

CM unterstützt zwei Arten der Testausführung: automatisches Testen und schrittweise Ausführung des Codes. Während Ersteres besonders bei Regressionstests und der gleichzeitigen Ausführung mehrfacher Tests von Vorteil ist, wird die schrittweise Ausführung vor allem zum Debuggen von Programmcode verwendet.

Bei der Entwicklung von CM wurde besonderer Wert auf die Fähigkeit der Software zur Abdeckungserfassung gelegt. Typischerweise nutzen Test-Tools hierfür speziell entwickelten Coverage-Messcode, der in das Programm eingebaut wird. So lässt sich ermitteln, welche Code-Segmente während des Tests zur Ausführung gelangen.

CM verfolgt einen anderen Ansatz: Es erfasst die vom Compiler erzeugten Debug-Informationen, die die Verbindung zwischen dem Quellcode und dem ausgeführten Assemblercode herstellen. So lassen sich Coverage-Abdeckungen direkt aus dem Objektcode des zu testenden Programms gewinnen. Die Resultate lassen sich grafisch darstellen.

In der Praxis korreliert der Assemblercode aber nicht vollständig mit dem Quellcode, besonders wenn auf Compiler-Ebene Optimierungen vorgenommen wurden. Solche Optimierungen können dazu führen, dass Teile des Quellcodes bei der Assemblierung weggelassen werden. CM erlaubt es, Quellcode und korrespondierenden Assemblercode gemeinsam anzuzeigen, sodass die Entwickler dieses Verhalten kontrollieren können.

Darüber hinaus ist es möglich, die Abdeckung unabhängig vom Assembler auf der Ebene des Quellcodes zu messen. Dazu ist eine separate Objektdatei mit eingefügtem Programmcode zur Abdeckungserfassung erforderlich. Dieser Schritt ist anzuwenden, wenn komplexe Entscheidungsbäume durchlaufen und modifiziert werden. Bei der Abdeckungsmessung mittels instrumentierten Codes schreibt die ISO 26262 den Nachweis vor, dass der instrumentierte Code die Testergebnisse nicht beeinflusst.

Dieser Nachweis kann durch die Wiederholung des Tests unter Ausschluss des instrumentierten Codes erbracht werden. CM vergleicht automatisch die Ergebnisse der Testdurchläufe mit und ohne instrumentierten Code und zeigt das Ergebnis an. Der Testingenieur sieht damit sofort, ob die Instrumentierung die Testergebnisse verfälscht hat. Die Testergebnisse gelten als Nachweis für eine Verifikation und Validierung im Sinne einer Qualitätskontrolle.

Validierter Programmcode gemäß der Norm ISO 26262

Bild 3: Plädoyer für die Testautomatisierung. Der hohe Personalaufwand und die Spielräume für menschliche Fehler bei manuellen Tests sprechen für einen hohen Automatisierungsgrad.
Bild 3: Plädoyer für die Testautomatisierung. Der hohe Personalaufwand und die Spielräume für menschliche Fehler bei manuellen Tests sprechen für einen hohen Automatisierungsgrad.
(Bild: GAIO)

Führen die Abdeckungstests zu unbefriedigenden Ergebnissen, werden eine Fehlersuche und eine Revision der Test Cases erforderlich. Falls eine bestimmte Struktur keine Abdeckung aufweist, benötigt der Tester eine Information über die fehlerhafte Stelle im Quellcode. CM zeigt an, welchen Programmzeilen der Fehler zuzuordnen ist.

Aus der beschriebenen Vorgehensweise wird ersichtlich, dass der Einsatz eines solchen Tools nicht nur den Zeitaufwand für den Komponententest im Vergleich zu herkömmlichen Verfahren deutlich verringert, sondern auch eine Reihe inhärenter Fehlerquellen vermeidet, die mit der üblichen händischen Vorgehensweise einhergehen. In der Konsequenz erleichtert es damit die Erstellung sicheren Programmcodes und die Erfüllung der Anforderungen gemäß ISO 26262.

* Dipl.-Ing. Reinhold Schmid ist Geschäftsführer der Embedded Tools GmbH.

(ID:46496060)