Funktionale Sicherheit Software Testing mit CI/CD-Workflow
Anbieter zum Thema
Die Umsetzung eines kontinuierlichen Integrations- und Lieferworkflows (CI/CD) für die Entwicklung von embedded Software wird immer beliebter.

Oft unterliegen Embedded-Software-Projekte Beschränkungen, die bei der Anwendungsentwicklung nicht gegeben sind. Zusätzlich zu den physischen und rechnerischen Grenzen der Zielhardwareplattform gibt es auch Einschränkungen durch den Markt. In der Regel stellt der Markt für Embedded-Systeme besondere Anforderungen an Sicherheit und Datenschutz sowie extrem lange Lebenszyklen.
Produkte können jahrzehntelang auf dem Markt bleiben. Aufgrund der Notwendigkeit und Komplexität der Initiierung und Einhaltung von Tests auf embedded Targets ist die Automatisierung von Tests auf embedded Zielsystemen eine echte Herausforderung. Dazu kommt, dass Software-Teams in der Regel nur begrenzten Zugriff auf die Zielhardware haben.
Damit man embedded Software kontinuierlich vom Host-Entwicklungssystem bis zum Zielsystem testen kann, ist die Automatisierung von Softwaretests unerlässlich. Außerdem ist das Testen von embedded Software besonders zeitaufwändig. Durch die Automatisierung der Regressionstestsuite lassen sich erhebliche Zeit- und Kosteneinsparungen erzielen.
Grundlagen
Das Sammeln von Testergebnissen und Codeabdeckungsdaten aus dem Zielsystem ist je nach Bedarf für die Bewertung und die Konformität mit Standards unverzichtbar. Und die Datenerfassung ist bei der Testdurchführung entscheidend. Sie kann durch die Aufzeichnung und Pflege der Rückverfolgbarkeit zwischen Testfällen, Testergebnissen, Quellcode und Anforderungen erfolgen. Integrierte Testlösungen wie Parasoft C/C++test bieten ein Testpaket, das so optimiert ist, dass es nur minimalen zusätzlichen Overhead für den binären Footprint benötigt und in Form von anpassbarem Quellcode bereitgestellt wird, falls plattformspezifische Änderungen erforderlich sind.
Es gibt Lösungen, die spezielle Integrationen mit embedded IDEs und Debuggern bieten, um den Prozess der Ausführung von Testfällen reibungslos und automatisiert zu gestalten. Die Testlösung von Parasoft für die C/C++-Softwareentwicklung unterstützt das Erstellen von Regressionstest-Baselines als eine strukturierte Sammlung von Tests und verifiziert automatisch alle Ergebnisse. Durch die regelmäßige automatische Ausführung dieser Tests wird überprüft, ob Codeänderungen die in den Regressionstests erfasste Funktionalität verändern oder brechen.
Werden Änderungen eingeführt, schlagen diese Testfälle fehl, um das Team auf das Problem aufmerksam zu machen. Während der anschließenden Tests meldet Parasoft C++test Aufgaben, wenn es Änderungen an dem im ersten Test erfassten Verhalten feststellt.
Die Gleichwertigkeit der Fähigkeiten von Remote-Target-Ausführung und Host-basiertem Testen bedeutet, dass embedded Software-Teams von denselben Vorteilen der Automatisierung profitieren können wie bei jeder anderen Art der Anwendungsentwicklung.
Automatisierung ist wichtig, aber nicht ausreichend, um den Status quo zu erhalten. Zur Verbesserung der Software-Sicherheit und -Qualität sind mehr Tests innerhalb der CI/CD-Pipeline notwendig, ohne den Ablauf weiter zu verlangsamen.
Verbesserte Testautomatisierung zur Optimierung von CI/CD
Die größte Schwierigkeit für die Teams besteht darin, die Testeffizienz zu verbessern und gleichzeitig die Anforderungen an Sicherheit und Qualität zu erfüllen, ohne die Zeitpläne und Kosten zu beeinträchtigen. Selbst bei der einfachen Testautomatisierung (Testdurchführung mit Ergebnissen) müssen zwangsläufig Kompromisse eingegangen werden, um die Testzeit angemessen zu halten.
Die einfache Lösung besteht darin, die zu testenden Teile der Software mit Hilfe von Vermutungen auszuwählen, da vollständige Systemtestsuiten zu zeitaufwändig und teuer sind. Embedded Software-Teams müssen ihre Tests ausweiten und sich zugleich auf genau das konzentrieren, was erforderlich ist. Die Optimierung von Tests mit Hilfe intelligenter Testautomatisierung macht dem Rätselraten bei der Testerstellung und -ausführung ein Ende.
Im Allgemeinen ist die Codeabdeckung ein Maß dafür, wie viel vom Produktionscode ausgeführt wird, während die automatisierten Tests laufen. Durch die Ausführung einer Testreihe und die Betrachtung der Codeabdeckungsdaten erhält man einen allgemeinen Eindruck davon, wie viel von der Anwendung getestet wird.
Es gibt mehrere Arten der Codeabdeckung. Bei embedded Systemen muss man mit Anweisung, Verzweigung und MC/DC vertraut sein. Für die strengsten Anforderungen, wie bei sicherheitskritischer Software, kann eine Objektcodeverifizierung oder eine Assembler-Codeabdeckung erforderlich sein.
Erfassen und Analysieren von Codeabdeckungsmetriken
Die Codeabdeckung misst die Vollständigkeit von Testfällen und ausgeführten Tests. Sie liefert den Nachweis, dass die Validierung vollständig ist, zumindest so, wie es der Softwareentwurf vorsieht. Außerdem zeigt sie, dass es kein unbeabsichtigtes Verhalten gibt – Code, der von keinem Test abgedeckt wird, ist ein Risiko, da sein Verhalten und seine Funktionalität unbekannt sind. Umfang und Ausmaß der Codeabdeckung hängen von der Sicherheitsintegritätsstufe ab.
Hier sind Beispiele für empfohlene Arten der Codeabdeckung:
- Statement Coverage – Bei der Anweisungsabdeckung muss jede Programmanweisung mindestens einmal ausgeführt werden (die Verzweigungs- und MC/DC-Abdeckung umfasst die Anweisungsabdeckung).
- Branch Coverage – Das ist die Verzweigungsabdeckung, welche sicher stellt, dass jeder mögliche Entscheidungszweig (if-then-else-Konstruktionen) ausgeführt wird.
- Modified Condition/Decision Coverage (MC/DC) – Die modifizierte Bedingungs-/ Entscheidungsabdeckung benötigt die vollständigste Codeabdeckung, um sicherzustellen, dass die Testfälle jeden Entscheidungszweig und alle möglichen Kombinationen von Eingaben, die das Ergebnis der Entscheidungslogik beeinflussen, ausführen. Bei komplexer Logik kann die Anzahl der Testfälle sprunghaft ansteigen, so dass mithilfe der modifizierten Bedingungseinschränkungen die Testfälle auf diejenigen beschränkt werden, die zu einer Änderung eigenständiger logischer Ausdrücke führen. (Sehen Sie sich dieses Tutorial der NASA an.)
C/C++test automatisiert diese Datenerfassung bei Host- und Zieltests und kumuliert die Testabdeckungshistorie im Laufe der Zeit. Dieser Codeabdeckungsverlauf kann Unit-, Integrations- und Systemtests umfassen, um sicherzustellen, dass die Abdeckung auf allen Testebenen vollständig und nachvollziehbar ist.
Höhere Codeabdeckung mit automatisierter Unit-Testfallerstellung
Höhere Codeabdeckung
Das Erstellen von produktiven Unit-Tests war schon immer eine Herausforderung. Die Konformität mit funktionalen Sicherheitsstandards verlangt hochwertige Software, was den Bedarf an Testsuiten erhöht, die hohe Codeabdeckungsstatistiken beeinflussen und produzieren. Teams benötigen Unit-Testfälle, die helfen, ihre Abdeckungsziele zu erreichen, die auch außerhalb des Bereichs der sicherheitskritischen Software wichtig sind. Jeder Code, der nicht mindestens von einem Test abdeckt wird, wird ungetestet ausgeliefert!Die Analyse von Codeverzweigungen und die Suche nach Gründen, warum bestimmte Codeabschnitte nicht abgedeckt sind, rauben den Entwicklungsteams immer wieder Zeit.
Abdeckungslücken in Testsuiten lassen sich mithilfe eines 'Coverage Advisors' beheben. Diese Analyse berechnet die Vorbedingungen für Funktionsparameter, globale Variablen und externe Funktionsaufrufe, die für die Ausführung einer bestimmten Codezeile erforderlich sind. Der Coverage Advisor präsentiert eine Sammlung von Lösungen für die vom Benutzer ausgewählten Codezeilen. Die vorgeschlagenen Werte dienen der Erstellung neuer Unit-Testfälle.
Jede Abdeckungslösung umfasst:
- Erforderliche Abhängigkeiten. Das sind die Abhängigkeiten, die angepasst werden müssen, um die ausgewählte Zeile abzudecken. Dazu können Funktionsparameter, externe Funktionsaufrufe, globale Variablen, lokale Variablen und Klassenmitglieder gehören.
- Vorbedingungen. Bedingungen, die von den erforderlichen Abhängigkeiten erfüllt werden müssen, um die ausgewählte Zeile abzudecken. Klickt man auf eine Vorbedingung, navigiert man zu der entsprechenden Codezeile.
- Erwartete Abdeckung. Dabei handelt es sich um Codezeilen, die abgedeckt werden, wenn alle Vorbedingungen erfüllt sind.
Optimieren von Tests mit intelligenter Testausführung
Zum Beschleunigen des Testvorgangs in einer kontinuierlichen Pipeline ist eine intelligente Testausführung auf Build-Basis notwendig. Die von der Testauswirkungsanalyse bereitgestellten Daten sind der Schlüssel dazu, dass sich das Testen nur auf das unbedingt Notwendige beschränkt und nicht auf den üblichen Schrotflinten-Ansatz.
Die Testausführung in Parasoft C/C++test wird durch Plugins für CI-Systeme (Jenkins, TeamCity, Bamboo usw.) erweitert und bietet Funktionen, mit denen Software-Entwicklungsunternehmen Engpässe im Zusammenhang mit der Ausführung kontinuierlicher Builds reduzieren können. Die gleichen Funktionen stehen in IDE-Umgebungen mit speziellen Plugins zur Verfügung, die über eine REST-API auf ein zentralisiertes Abdeckungsbild zugreifen und bestimmen, welche Tests lokal in der IDE ausgeführt werden müssen, um den gesamten geänderten Code zu überprüfen.
Auf der Entwicklungsseite könnten Entwickler ihre Tests richtig strukturieren. Teams, die mit CI arbeiten, können sich auf nächtliche Builds verlassen, um alle Tests automatisch über Nacht auszuführen und am nächsten Tag ein Feedback zu erhalten – aber nur, wenn es möglich ist, die gesamte Anzahl der Tests in weniger als 12 Stunden auszuführen.
Traditionelle Software-Entwicklungsunternehmen folgen immer noch den Testpraktiken, die mit einer umgekehrten Pyramide dargestellt werden, die aus dem einen oder anderen Grund die Durchführung manueller Tests über automatisierte Tests stellt. Bei der intelligenten Testausführung kommt die Testauswirkungsanalyse zum Einsatz, um die Ausführung manueller Tests gegen Anwendungen und damit einhergehende, erfasste Codeabdeckungsinformationen zu verfolgen. Eine ähnliche Technologie wird für automatisierte Tests verwendet. Diese Analyse ermittelt, welche manuellen Tests ausgeführt werden müssen, um auf die geänderten Funktionen zuzugreifen, die mit jedem neuen Build geliefert werden. (mbf)
Dieser Beitrag stammt ursprünglich von unserem Partnerportal Embedded-Software-Engineering.de.
Ricardo Camacho ist Senior Technical Product Marketing Manager bei Parasoft.
(ID:49410820)