Seien Sie am 30. April dabei: Vorstellung von Parasoft C/C++test CT für kontinuierliche Tests und Compliance-Exzellenz | Registrierung

So erhalten Sie eine 100% ige strukturelle Code-Abdeckung sicherheitskritischer Systeme

Kopfbild von Ricardo Camacho, Director of Safety & Security Compliance
7. März 2023
7 min lesen

Das Erreichen einer strukturellen Codeabdeckung von Systemen ist eines der entscheidenden Dinge, die jeder Softwareentwickler und Qualitätsingenieur wissen sollte. Lesen Sie weiter, um die strukturelle Codeabdeckung zu verstehen und warum sie für das Testen von Software entscheidend ist.

Viele Softwareentwicklungs- und Verifizierungsingenieure verstehen nicht wirklich, warum es wichtig ist, eine strukturelle Abdeckung zu erhalten. Viele tun es einfach, weil es durch den Funktionsstandard ihrer Branche vorgeschrieben ist, und nehmen es nicht ernst.

Sicherheitskritische Systeme wie ADAS können Passagiere ohne Fahrer transportieren, Autopiloten ermöglichen, Menschen über unseren Himmel zu fliegen, und Patienten mit medizinischen Geräten am Leben erhalten. Menschenleben hängen von diesen Systemen ab. Es ist wichtig, erhalten strukturelle Codeabdeckung. Lassen Sie uns untersuchen, was strukturelle Abdeckung ist, und weitere Gründe, warum sie wichtig ist.

Was ist strukturelle Abdeckung?

Kurz gesagt, strukturelle Abdeckung ist die Identifizierung von Code, der ausgeführt und protokolliert wurde, um festzustellen, ob das System angemessen getestet wurde. Die Gründlichkeit der Abdeckung in sicherheitskritischen Systemen hängt von der Sicherheitsintegritätsstufe (SIL), der ASIL in der Automobilindustrie und der Entwicklungssicherheitsstufe (DAL) ab, die üblicherweise in der Avionik verwendet werden.

Aus Gründen der Gründlichkeit beziehe ich mich auf die Strukturelemente im Code. In eingebetteten Systemen werden diese normalerweise in Code-Anweisungen, Verzweigungen und geänderte Bedingungsentscheidungen unterteilt, und Sie können auch einen Drilldown auf ein viel feineres Maß an Granularität durchführen, z. B. den Objektcode oder die Assemblersprache.

Möglicherweise hören oder lesen Sie andere Arten von Abdeckungsmetriken wie Funktion, Aufruf, Schleife, Bedingung, Sprung, Entscheidung usw. Für eingebettete sicherheitskritische Systeme müssen Sie derzeit lediglich Anweisungen, Verzweigungen, MC / DC und Objektcode kennen. Die anderen genannten Typen sind eine Teilmenge und werden daher angesprochen.

Derzeit gibt es eine Tendenz zur Einführung von Multiple Condition Coverage (MCC), die gründlicher ist als MC / DC. MCC erfordert eine viel größere Anzahl von Testfällen - 2 nach der Anzahl der Bedingungen.

Die Formel: 2C

Da MCC nicht offiziell von den Prozessstandards der Industrie empfohlen oder vorgeschrieben wird ISO 26262 , DO-178, IEC 62304, IEC 61508 or EN 50128Ich werde es in diesem Blog-Beitrag nicht behandeln.

Kontoauszug und Branchenabdeckung

Die Abdeckung von Anweisungen ist am einfachsten und repräsentiert jede Codezeile in einem Programm. Code-Anweisungen können jedoch unterschiedlich komplex sein. Beispielsweise repräsentiert eine Verzweigungsanweisung eine wenn dann sonst Bedingung im Code. Aussagen wie Fall oder Schalter werden als Zweig interpretiert. Wenn Sie jedoch eine Abdeckung für Zweige erhalten möchten, bedeutet dies, dass die Ausführung sowohl des wahren als auch des falschen Entscheidungspfads abgedeckt werden muss.

Flussdiagramm mit einem blauen Kreis an der oberen Bedingung wahr auf der linken Seite zeigt auf A, Bedingung falsch auf der rechten Seite zeigt auf B. Eine Linie verbindet A mit B, die auf einen anderen dunkelblauen Kreis zeigt, der in einem größeren blauen Kreis eingeschlossen ist.
Zweigflussdiagramm

Wenn höhere Sicherheitsniveaus von Belang sind, kann eine modifizierte Zustandsentscheidungsabdeckung (MC / DC) erforderlich sein. Die Komplexität von Zweigen kann zunehmen, wenn eine Entscheidung mehrere Bedingungen enthält und jede Bedingung unabhängig getestet werden muss.

Für Deckungskriterien bedeutet dies, dass gezeigt wurde, dass jede Bedingung in der Entscheidung das Ergebnis dieser Entscheidung unabhängig beeinflusst. Eine Wahrheitstabelle kann verwendet werden, um diese Analyse wie unten gezeigt durchzuführen.

Außerdem hat jede Bedingung in einer Entscheidung im Programm alle möglichen Ergebnisse mindestens einmal getroffen, und jede Entscheidung im Programm hat alle möglichen Ergebnisse mindestens einmal getroffen.

Im folgenden Beispiel mit 4 Bedingungsanweisungen gibt es 16 mögliche Testfälle. MC / DC benötigt für dieses Beispiel nur 5. Nehmen Sie die Anzahl der Bedingungen und addieren Sie 1.

Die Formel: (C + 1)

Tabelle mit Spaltenüberschriften Testfall n Grad, C1, C2, C3, C4 und Entscheidung / Ergebnis oben. Unter der Überschrift Testfall n Grad befinden sich die Zeilen 1-16. T oder F füllt den Rest der Zellen in der Tabelle.
MC / DC-Entscheidungswahrheitstabelle für "If (((a == 0) || (b <5)) && ((c> 7) || (d == 0))" Erklärung

Objektcode-Abdeckung

Für die strengsten sicherheitskritischen Anwendungen, wie beispielsweise in der Avionik, schreibt der Prozessstandard DO-178B / C Level A die Abdeckung des Objektcodes vor. Dies liegt an der Tatsache, dass ein Compiler oder Linker zusätzlichen Code generiert, der nicht direkt auf Quellcode-Anweisungen zurückgeführt werden kann. Daher muss eine Abdeckung auf Baugruppenebene durchgeführt werden.

Stellen Sie sich die Genauigkeit und die Arbeitskosten vor, die mit der Ausführung dieser Aufgabe verbunden sind. Glücklicherweise gibt es Parasoft ASMTools, eine automatisierte Lösung zum Erhalten der Objektcode-Abdeckung.

Screenshot der Codeabdeckung des Parasoft ASMTools-Assemblersprachencodes mit einer Liste der Tests und dem Prozentsatz der Abdeckung links. Rechts ist der Code. Einige sind grün hervorgehoben, andere rosa, eine Linie gelb.
Parasoft ASMTools Assembler-Code-Abdeckung

Code-Abdeckung erhalten

Die Codeabdeckung wird häufig durch die Instrumentierung des Codes identifiziert. Instrumentiert bezieht sich darauf, dass der Benutzercode mit zusätzlichem Code verziert wird, um während der Ausführung festzustellen, ob diese Anweisung, dieser Zweig oder diese MC / CD ausgeführt wurde.

Basierend auf dem eingebetteten Ziel oder Gerät können die Abdeckungsdaten im Dateisystem gespeichert, in den Speicher geschrieben oder über verschiedene Kommunikationskanäle wie die serielle Schnittstelle, die TCP / IP-Schnittstelle, USB und sogar JTAG gesendet werden.

Teilinstrumentierung

Beachten Sie, dass die Code-Instrumentierung zu einem Aufblähen des Codes führt und diese Zunahme der Codegröße die Fähigkeit beeinträchtigen kann, den Code zum Testen auf Ihre speicherbeschränkte Zielhardware zu laden.

Die Problemumgehung besteht darin, einen Teil des Codes 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.

Basierend auf Ihren Zielbeschränkungen haben Sie hoffentlich nicht zu viele instrumentierte Partitionen, um sie zu durchlaufen. Es kann sehr zeitaufwändig und kostspielig sein, dieselben Tests immer wieder wiederholen zu müssen. Um es schnell zu erwähnen, kann es auch zu schlechten Timing- und Leistungseffekten kommen, die durch die Instrumentierung verursacht werden können.

Erhalten der Codeabdeckung für eingebettete sicherheitskritische Systeme

Lassen Sie uns untersuchen, wie Unternehmen Codeabdeckung für ihre eingebetteten sicherheitskritischen Systeme erhalten.

Für Anforderungen an die Codeabdeckung, wie z. B. eine vorgeschriebene 100% -Struktur, Zweigstellen- und MC / DC-Abdeckung oder eine optionale und persönlich gewünschte 80% -Abdeckung, gibt es verschiedene Testmethoden, mit denen Sie Ihre Ziele erreichen können. Die gebräuchlichsten Methoden:

  • Systemtests
  • Unit-Test
  • Manuelle Prüfung

Das Kombinieren der Abdeckungsmetriken aus diesen verschiedenen Praktiken ist typisch. Aber wie genau wird die Codeabdeckung identifiziert?

Abdeckung durch Systemtests

Das Erhalten der Codeabdeckung durch Systemtests ist eine hervorragende Methode, um festzustellen, ob genügend Tests durchgeführt wurden. Der Ansatz besteht darin, alle Ihre Systemtests auszuführen und dann zu untersuchen, welche Teile des Codes nicht ausgeführt wurden.

Der nicht ausgeführte Code impliziert, dass möglicherweise neue Testfälle erforderlich sind, um den unberührten Code auszuführen, in dem möglicherweise ein Fehler lauert, und hilft bei der Beantwortung der Frage, ob ich genügend Tests durchgeführt habe.

Wenn ich aufgetreten bin Codeabdeckung Während des Systemtests beträgt die durchschnittliche resultierende Metrik 60% Abdeckung. Ein Großteil des zu 40% nicht ausgeführten Codes ist auf defensiven Code in Ihrer Anwendung zurückzuführen.

Was ich unter defensiv verstehe, ist Code, der nur ausgeführt wird, wenn das System in einen Fehler oder einen problematischen Zustand eintritt, der möglicherweise schwer zu erzeugen ist. Es kann Wochen, Monate oder Jahre dauern, bis Bedingungen wie Speicherverlust, Beschädigung oder andere Fehler aufgrund von Hardwarefehlern auftreten.

Es gibt auch defensiven Code, der von Ihren Codierungsrichtlinien vorgeschrieben wird und den Systemtests niemals ausführen können. Aus diesen Gründen können Sie durch Systemtests keine 100% ige Abdeckung des Strukturcodes erreichen. Sie müssen andere Testmethoden wie manuelle Tests und / oder Komponententests anwenden, um 100% zu erreichen.

Beachten Sie, dass Prozessstandards das Zusammenführen von Abdeckungsmetriken ermöglichen, die aus verschiedenen Testmethoden erhalten wurden.

Abdeckung durch Unit-Tests

Wie bereits erwähnt, Unit-Tests können als ergänzender Ansatz zum Systemtest verwendet werden bei der Erlangung einer 100%igen Abdeckung. Das Erlangen von Codeabdeckung durch Unit-Tests ist eine der beliebtesten Methoden, die verwendet wird, aber es zeigt nicht, ob Sie das System ausreichend getestet haben, da der Fokus auf der Unit-Ebene (Funktion/Prozedur) liegt.

Ziel ist es, eine Reihe von Unit-Testfällen zu erstellen, die die gesamte Einheit bei den erforderlichen Anforderungen zur Einhaltung der Abdeckung (Anweisung, Zweigstelle und MC / DC) trainieren, um eine 100% ige Abdeckung für diese einzelne Einheit zu erreichen. Dies wird für jede Einheit wiederholt, bis die gesamte Codebasis abgedeckt ist. Konzentrieren Sie sich jedoch nicht nur auf die Codeabdeckung, um das Beste aus Unit-Tests herauszuholen. Dies kann im Allgemeinen durch Testfälle mit Sonnentagsszenarien erreicht werden.

Trainieren Sie das Gerät wirklich durch sonnige und regnerische Tagesszenarien, um Robustheit, Sicherheit und niedrige Werte zu gewährleisten Rückverfolgbarkeit der Anforderungen. Lassen Sie die Codeabdeckung ein Nebenprodukt Ihrer Testfälle sein und füllen Sie sie bei Bedarf aus.

Um die Codeabdeckung durch Komponententests zu beschleunigen, stehen in konfigurierbare und automatisierte Funktionen zur Testfallgenerierung zur Verfügung Parasoft C / C ++ test. 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. Innerhalb von Minuten erhalten Sie eine erhebliche Codeabdeckung.

Wie beim Systemtest ist es jedoch aufgrund der Verwendung von defensivem Code oder formaler Sprachsemantik schwierig, eine 100% ige Codeabdeckung zu erzielen. Auf der granularen Ebene einer Einheit kann der Verteidigungscode in Form von a vorliegen Standard Aussage in a wechseln. Wenn jeder mögliche Fall in einem wechseln erfasst wird, verlässt dies die Standard Aussage nicht erreichbar. Im folgenden Beispiel wird die Rückkehr 0; wird nie ausgeführt, weil die while (1) ist unendlich.

Screenshot einer nicht erreichbaren Rückgabe 0; Erklärung
Nicht erreichbar Rückkehr 0; Erklärung

Wie erhält man also eine 100% ige Deckung für diese Sonderfälle?

Antwort: Manuelle Methoden müssen bereitgestellt werden.

Der Benutzer kann die Anweisung mithilfe eines Debuggers kennzeichnen oder notieren, den Aufrufstapel ändern und die Anweisung ausführen Rückkehr 0; Erklärung. Beobachten Sie visuell die Ausführung und dokumentieren Sie mindestens den Dateinamen, die Codezeile und die Code-Anweisung, die jetzt als abgedeckt gelten.

Diese Abdeckung, die durch manuelle / visuelle Inspektion und Berichte durchgeführt wird, kann verwendet werden, um die durch Einheitentests erfasste Abdeckung zu ergänzen. Das Hinzufügen beider Abdeckungsberichte kann verwendet werden, um eine 100% ige Abdeckung des Strukturcodes nachzuweisen.

Umfassende Codeabdeckung: Gesamtabdeckung über Testpraktiken hinweg

Wenn eine Abdeckung durch Systemtests stattgefunden hat und aufgenommen werden soll, können alle drei Abdeckungsberichte (System, Einheit, Handbuch) verwendet werden, um eine 100% ige Abdeckung und Konformität anzuzeigen und nachzuweisen.

Screenshot des Parasoft Report Center-Dashboards mit Berichten zur Anwendungsabdeckung in Form von Tabellen, Grafikdiagrammen und Prozentkreisen
Parasoft DTP Beispiel für die Berichterstellung zur Dashboard-Codeabdeckung

Zusammenfassung

Strukturelle Codeabdeckung kann helfen, die Frage zu beantworten: Habe ich genug Tests durchgeführt?

Es kann auch eine Compliance-Anforderung sein, die Sie erfüllen müssen. Das Ziel der Codeabdeckung ist ein zusätzliches Mittel, um die Sicherheit und Zuverlässigkeit des Codes zu gewährleisten. Es zeigt den Beweis, dass Tests durchgeführt wurden. Durch diese Tests wurden Mängel festgestellt.

Ein häufiger Fehler, den die Codeabdeckung leicht identifizieren kann und der in den früheren Abschnitten nicht erwähnt wurde, ist das Aufdecken von totem Code. Toter Code ist Code, der in keiner Weise aufgerufen oder aufgerufen wird. Es ist Code, der wahrscheinlich aufgrund einer Änderung der Anforderungen zurückgelassen oder versehentlich vergessen wurde.

Die Abdeckung kann auch durch verschiedene Testmethoden (System, Einheit, Integration, Handbuch, API) erreicht werden. Die kumulative Abdeckung dieser Methoden kann kombiniert werden, um eine 100% ige Codeabdeckung nachzuweisen.

Es gibt auch verschiedene Abdeckungsebenen (Anweisung, Verzweigung, MC / DC und Objektcode), die Sie möglicherweise ausführen müssen, wenn die Kriterien auf Ihrer SIL-, ASIL- oder DAL-Ebene basieren. Glücklicherweise bietet Parasoft automatisierte Softwaretestlösungen und die Methoden, die Sie benötigen, um eine 100% ige Abdeckung des Strukturcodes zu erreichen.

Erfahren Sie, wie Sie Code-Analysetechniken für Ihr eingebettetes Projekt nutzen können. Schau das Video.

Mit dem Parasoft C / C + -Test erhalten Sie kritisches Feedback zur Vollständigkeit und Gründlichkeit Ihres Testprozesses.