Logo für GIGAOM 365x70

Sehen Sie, welche API-Testlösung im GigaOm Radar Report am besten abgeschnitten hat. Holen Sie sich Ihren kostenlosen Analystenbericht >>

DO-178C-Softwarekonformität für die Luft- und Raumfahrt sowie Verteidigung

Strukturelle Codeabdeckung

Sammeln und analysieren Codeabdeckungsmetriken ist ein wichtiger Aspekt der sicherheitskritischen Softwareentwicklung. Die Codeabdeckung misst die Fertigstellung von Testfällen und ausgeführten Tests. Sie liefert den Nachweis, dass die Verifizierung abgeschlossen ist, zumindest wie im Softwaredesign angegeben. Zu den Zielen der Testabdeckungsanalyse gehört das Erreichen der folgenden Testabdeckungsziele:

Blauer Kreis mit einem weißen Häkchen-Symbol in der Mitte.

Anforderungen auf hohem Niveau

Blauer Kreis mit einem weißen Häkchen-Symbol in der Mitte.

Niedrige Anforderungen

Blauer Kreis mit einem weißen Häkchen-Symbol in der Mitte.

Softwarestruktur nach den passenden Abdeckungskriterien

Blauer Kreis mit einem weißen Häkchen-Symbol in der Mitte.

Softwarestruktur, sowohl Datenkopplung als auch Steuerungskopplung

Symbol in einem blauen Kreis, das den weißen Umriss einer Richtlinien-Checkliste zeigt.

Abschnitt 6.4.4.1

Abschnitt 178 von DO-6.4.4.1C behandelt die Testabdeckungsanalyse der Anforderungen, die bestimmt, wie gut die Funktionstests die Implementierung der Anforderungen überprüft haben. Es wird erwartet, dass während dieser Tests Codeabdeckungsanalysen gesammelt werden und die verbleibenden Lücken in der Codeabdeckung durch weitere Tests geschlossen werden.

Symbol in einem blauen Kreis, das den weißen Umriss einer Richtlinien-Checkliste zeigt.

Abschnitt 6.4.4.2

Abschnitt 6.4.4.2 erfordert eine Analyse, um zu bestimmen, was von der Codeabdeckung übrig bleibt, einschließlich der Schnittstellen zwischen Komponenten. Abschnitt 6.4.4.3 beschreibt die Anforderungen zum Beheben etwaiger Lücken in der Abdeckung, einschließlich der Identifizierung von irrelevantem, totem und deaktiviertem Code.

Wie sich dies auf die Art und den Umfang der Abdeckung auswirkt, ist etwas auslegungsbedürftig. Bei der Entwicklung von Software für Flugzeuge liegt es jedoch in der Verantwortung des Herstellers, die Codeabdeckung zu planen, den Plan einzuhalten, zu dokumentieren und abzuschließen.

Arten der Codeabdeckung

Im Folgenden sind die verschiedenen Arten der Codeabdeckung aufgeführt.

Aussagedeckung

Die Anweisungsabdeckung erfordert, dass jede Programmanweisung mindestens einmal ausgeführt wird. Die Branch- und MC/DC-Abdeckung umfasst die Anweisungsabdeckung.

Zweigstellenabdeckung

Durch die Zweigabdeckung wird sichergestellt, dass jeder Entscheidungszweig (If-Then-Else-Konstrukte) ausgeführt wird.

Modifizierte Bedingungs-/Entscheidungsabdeckung (MC/DC)

Modifizierte Bedingungs-/Entscheidungsabdeckung (MC/DC) erfordert die umfassendste Codeabdeckung, um sicherzustellen, dass Testfälle jeden Entscheidungszweig und alle möglichen Eingabekombinationen ausführen, die das Ergebnis der Entscheidungslogik beeinflussen. Bei komplexer Logik kann die Anzahl der Testfälle explodieren, daher werden die modifizierten Bedingungsbeschränkungen verwendet, um Testfälle auf diejenigen zu beschränken, die zu Änderungen eigenständiger logischer Ausdrücke führen.

Ausführbarer Code/Objektcode

Ausführbarer/Objektcode ist erforderlich, wenn das Software-Level-Kriterium A ist. Dies liegt daran, dass ein Compiler oder Linker zusätzlichen Assemblercode generiert, der nicht direkt auf Quellcodeanweisungen zurückgeführt werden kann. Daher muss eine Abdeckung auf Objektebene durchgeführt werden.

Erweitert Tools zur Automatisierung von Unit-Tests, wie Parasoft C/C++test, bieten all diese Code Coverage-Metriken und mehr. C/C++test CT automatisiert diese Datenerfassung auch bei Host- und Zieltests und sammelt im Laufe der Zeit den Test Coverage-Verlauf. Dieser Code Coverage-Verlauf kann Unit-, Integrations- und Systemtests umfassen, um sicherzustellen, dass die Abdeckung auf allen Testebenen vollständig und nachvollziehbar ist.

Foto, das eine Nahaufnahme des Cockpits eines Space Shuttle zeigt.

Abdeckung durch Systemtests

Die Ermittlung der Codeabdeckung durch Systemtests ist eine hervorragende Methode, um festzustellen, ob ausreichend Tests durchgeführt wurden. Der Ansatz besteht darin, alle Systemtests auszuführen und dann zu untersuchen, welche Teile des Codes nicht getestet wurden.

Der nicht ausgeführte Code weist darauf hin, dass möglicherweise neue Testfälle erforderlich sind, um den unberührten Code zu testen, in dem sich möglicherweise ein Defekt verbirgt. Dies trägt dazu bei, die Frage zu beantworten: Habe ich genügend Tests durchgeführt?

Wenn Teams Systemtests durchführen, liegt die durchschnittliche resultierende Metrik bei 60 % Abdeckung. Ein Großteil der 40 % nicht ausgeführten Codes ist auf defensiven Code in Ihrer Anwendung zurückzuführen. Defensiver Code wird nur ausgeführt, wenn das System einen Fehler auslöst oder in einen problematischen Zustand gerät, der möglicherweise schwer zu erzeugen ist. Es kann Wochen, Monate oder Jahre dauern, bis Zustände wie Speicherverlust oder andere Arten von Fehlern auftreten, die durch Hardwarefehler verursacht werden.

Es gibt auch defensiven Code, der von Ihren Codierungsrichtlinien vorgeschrieben ist und den Sie mit Systemtestfällen niemals ausführen können. Aus diesen Gründen können Sie mit Systemtests keine 100 % strukturelle Codeabdeckung erreichen. Sie müssen andere Testmethoden wie manuelle und/oder Unit-Tests anwenden, um 100 % zu erreichen.

Abdeckung durch Unit-Tests

Wie bereits erwähnt, können Unit-Tests als ergänzender Ansatz zu Systemtests verwendet werden, um eine 100-prozentige Abdeckung zu erreichen. Das Erreichen der Code-Abdeckung durch Unit-Tests ist eine der gängigeren Methoden, zeigt jedoch nicht, ob Sie das System ausreichend getestet haben, da der Fokus auf der Unit-Ebene (Funktion/Prozedur) liegt.

Das Ziel besteht hier darin, eine Reihe von Unit-Testfällen zu erstellen, die die gesamte Einheit mit der erforderlichen Abdeckung (Anweisung, Zweig und MC/DC) testen, um eine 100-prozentige Abdeckung für diese einzelne Einheit zu erreichen. Dies wird für jede Einheit wiederholt, bis die gesamte Codebasis abgedeckt ist. Um jedoch das Beste aus Unit-Tests herauszuholen, sollten Sie sich nicht nur auf die Codeabdeckung konzentrieren. Dies kann im Allgemeinen durch Testfälle für praxisnahe Szenarien erreicht werden.

Testen Sie das Gerät gründlich in allen möglichen Szenarien, um Robustheit, Sicherheit und die Rückverfolgbarkeit von Anforderungen auf niedriger Ebene sicherzustellen. Lassen Sie die Codeabdeckung ein Nebenprodukt Ihrer Testfälle sein und ergänzen Sie die Abdeckung, wo nötig.

Um die Codeabdeckung durch Unittests zu beschleunigen, stehen in Parasoft C/C++test konfigurierbare und automatisierte Testfallgenerierungsfunktionen zur Verfügung. Testfälle können automatisch generiert werden, um die Verwendung von Nullzeigern, Min-Mid-Max-Bereichen, Grenzwerten und vielem mehr zu testen. Diese Automatisierung kann Sie weit bringen. In wenigen Minuten erhalten Sie eine beträchtliche Codeabdeckung.

Screenshot des Codes für eine nicht erreichbare return 0;-Anweisung
Nicht erreichbar return 0; Anweisung

Darüber hinaus erweitert C/C++test CT Entwicklungs-Workflows mit Code Coverage durch die Integration mit proprietären Unit-Test-Frameworks und IDEs. Integrieren Sie Code Coverage-Zeilen, Anweisungen, einfache Bedingungen, Entscheidungen, Verzweigungen, Funktionen, Aufrufe und MC/DC eng mit proprietären Unit-Test-Frameworks wie GoogleTest und CppUnit und IDEs wie VS Code.

Wie beim Systemtest ist es jedoch aufgrund der Verwendung von defensivem Code oder formaler Sprachsemantik schwierig, eine 100%ige Codeabdeckung zu erreichen. Auf der granularen Ebene einer Einheit kann defensiver Code in Form einer Standardanweisung in einem Switch auftreten. Wenn jeder mögliche Fall in einem Switch erfasst wird, ist die Standardanweisung unerreichbar. Im folgenden Beispiel wird return 0; nie ausgeführt, da while (1) unendlich ist.

Wie erreicht man für diese Sonderfälle eine 100%ige Abdeckung?

Antwort: Einsatz manueller Methoden.

Folge diesen Schritten.

  1. Kennzeichnen oder notieren Sie die Anweisung mithilfe eines Debuggers als abgedeckt.
  2. Ändern Sie den Aufrufstapel und führen Sie die Anweisung „return 0;“ aus.
  3. Beobachten Sie die Ausführung visuell und dokumentieren Sie mindestens den Dateinamen, die Codezeile und die Codeanweisung, die nun als abgedeckt gelten.

Diese Abdeckung, die durch manuelle/visuelle Inspektion und Berichte erreicht wird, kann verwendet werden, um die durch Unit-Tests erfasste Abdeckung zu ergänzen. Die Ergänzung beider Abdeckungsberichte kann verwendet werden, um 100% strukturelle Codeabdeckung nachweisen.

Das Ziel der Code-Abdeckung ist ein zusätzliches Mittel zur Gewährleistung der Sicherheit und Zuverlässigkeit des Codes.

Code-Instrumentierung

Die Codeabdeckung wird meistens dadurch ermittelt, dass der Code instrumentiert wird. Instrumentiert bedeutet, dass der Benutzercode mit zusätzlichem Code versehen wird, um während der Ausführung festzustellen, ob diese Anweisung, dieser Zweig oder MC/CD ausgeführt wurde.

Basierend auf dem Ziel oder dem zu testenden System können die Abdeckungsdaten im Dateisystem gespeichert, in den Speicher geschrieben oder über verschiedene Kommunikationskanäle wie den seriellen Anschluss, den TCP/IP-Anschluss, USB und sogar JTAG gesendet werden.

Teilinstrumentierung

Beachten Sie, dass die Code-Instrumentierung zu aufgeblähtem Code führt. Die Zunahme der Codegröße kann sich auf die Fähigkeit auswirken, den Code zum Testen auf speicherbeschränkte Zielhardware zu laden.

Die Problemumgehung besteht darin, einen Teil des Codes wie folgt zu instrumentieren:

  1. Führen Sie Ihre Tests aus und erfassen Sie die Abdeckung.
  2. Instrumentieren Sie den anderen Teil des Codes.
  3. Führen Sie Ihre Tests erneut aus.
  4. Erfassen Sie die Abdeckung.
  5. Führen Sie die Abdeckung aus der vorherigen Testausführung zusammen.

Abdeckungsberater

Parasoft C/C++test schließt Abdeckungslücken in Testsuiten. Parasoft hat herausgefunden, wie man mithilfe erweiterter statischer Codeanalyse (Daten- und Kontrollflussanalyse) Werte für die Eingabeparameter findet, die zum Ausführen bestimmter Zeilen nicht abgedeckten Codes erforderlich sind.

In komplexem Code gibt es immer diese schwer fassbaren Codeanweisungen, für die es äußerst schwierig ist, eine Abdeckung zu erhalten. Es ist wahrscheinlich, dass es mehrere Eingabewerte mit verschiedenen Permutationen und möglichen Pfaden gibt, deren Entschlüsselung verwirrend und zeitaufwändig ist. Aber nur eine Kombination kann Ihnen die Abdeckung verschaffen, die Sie benötigen. Parasoft macht es einfach, eine Abdeckung dieser schwer erreichbaren Codezeilen zu erhalten.

Wenn Sie die Codezeile auswählen, die Sie abdecken möchten, teilt Ihnen der Coverage Advisor mit, welche Eingabewerte, globalen Variablen und externen Aufrufe Sie benötigen, um den Code zu stimulieren und eine Abdeckung zu erreichen.

Screenshot des Parasoft C/C++test Coverage Advisor.
Rufen Sie Coverage Advisor auf, indem Sie mit der rechten Maustaste auf die Codezeile klicken.
Screenshot, der zwei Testfalllösungen zeigt, die vom Coverage Advisor im C/C++test bereitgestellt werden.
Zwei Testfalllösungen bereitgestellt von Coverage Advisor.

Die Abbildung rechts zeigt einen Analysebericht, der dem Benutzer eine Lösung bietet. Das Feld „Voraussetzungen“ drückt Folgendes aus:

  • Der Bereich und die Eingabewerte für mainSensorSignal und coSensorSignal
  • Die erwarteten Ergebnisse der externen Anrufe

Beim Erstellen des Unit-Testfalls mit diesen festgelegten Parameterwerten und Stubs für externe Aufrufe erhalten Sie die Abdeckung der ausgewählten Zeile sowie der zusätzlichen Zeilen, die im Feld „Erwartete Abdeckung“ angegeben sind.


Objektcode-Abdeckung

Screenshot von Parasoft ASMTool für Assembly/Object Code Coverage
Parasoft ASMTool für Assembly-/Objektcode-Abdeckung

Für die strengsten sicherheitskritischen Anwendungen ist DO-178C Level A, Objektcodeabdeckung erforderlich. Daher muss eine Abdeckung auf Assembly-Ebene durchgeführt werden. Stellen Sie sich den Aufwand und die Arbeitskosten vor, die diese Aufgabe mit sich bringt. Glücklicherweise bietet Parasoft ASMTools eine automatisierte Lösung zum Erreichen der Objektcodeabdeckung.

Dunkelblaues Banner mit dem Bild eines Mannes, der in einem Serverraum mit einer Frau spricht, die ein Tablet in der Hand hält.
Bild eines Mannes und einer Frau mit einem Tablet in der Hand, die in einem Serverraum diskutieren.

Verbessern Sie Ihre Softwaretests mit Parasoft-Lösungen.