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 >>

Der unverzichtbare Leitfaden zu automatisierten Testprozessen für eingebettete Softwaresysteme

Ein wesentlicher Startpunkt für die Bereitstellung hochwertiger Echtzeit- Embedded Software systems integriert die statische Analyse in den Entwicklungsablauf. Mithilfe der statischen Analyse können Softwareentwickler die Zuverlässigkeit, Leistung und Sicherheit ihrer Software verbessern. Gleichzeitig können sie die Kosten und den Zeitaufwand reduzieren, die mit der Identifizierung und Behebung von Fehlern später im Entwicklungszyklus verbunden sind.

Die statische Analyse identifiziert Fehler im Code in einem frühen Stadium des Entwicklungsprozesses, lange bevor die Software auf der Zielhardware ausgeführt wird. Dazu gehört das Erkennen von Syntaxfehlern, Logikfehlern und potenziellen Laufzeitfehlern. Sicherheit ist auch bei eingebetteten Systemen von größter Bedeutung, insbesondere bei solchen, die Teil einer kritischen Infrastruktur oder von Geräten des Internets der Dinge (IoT) sind. Durch die statische Analyse können Schwachstellen wie Pufferüberläufe, Eingabevalidierungsfehler und andere Sicherheitslücken aufgedeckt werden, die von Angreifern ausgenutzt werden könnten.

Darüber hinaus sind sich die meisten Entwicklungsteams einig, dass Unit-Tests trotz des Aufwands und der Kosten auch für die Entwicklung eingebetteter Software unerlässlich sind. Unit-Tests helfen Entwicklern, den Code, den sie entwickeln, wirklich zu verstehen, und bieten eine solide Grundlage für ein Verifizierungs- und Validierungsprogramm, das zur Erfüllung der Sicherheitsziele eines Produkts erforderlich ist. Auf dieser Grundlage von Unit-Tests können Teams die agile Entwicklung beschleunigen und gleichzeitig das Risiko verringern, dass sich Fehler in spätere Phasen der Pipeline einschleichen.

Kontinuierliche Integrationspipeline für eine solide, moderne Entwicklungsgrundlage

Warum automatisiertes Testen?

Statische Analyse

Die Automatisierung der statischen Analyse im Softwareentwicklungs-Workflow bietet erhebliche Vorteile.

  • Integriert sich in Entwickler-IDEs und CI/CD-Pipelines. Die Integration statischer Analysen in den Build-Prozess der gesamten Entwicklungsorganisation ist eine bewährte Methode. Durch Automatisierung können Teams statische Analysen in die IDEs der Entwickler integrieren, um sie beim Schreiben des Codes schnell zu analysieren. Wenn Teams statische Analysen in CI/CD-Pipelines integrieren, wird der Code bei jeder Übermittlung von Codeänderungen automatisch analysiert.

Dadurch wird sichergestellt, dass Probleme sofort erkannt und behoben werden, sodass die Codequalität während des gesamten Entwicklungsprozesses erhalten bleibt, was für große Teams oder Projekte mit schnellen Entwicklungszyklen von entscheidender Bedeutung ist. Dadurch werden Codierungsstandards in der gesamten Codebasis durchgesetzt, wodurch menschliche Fehler und Voreingenommenheit bei Codeüberprüfungen vermieden werden. Dieser proaktive Ansatz gewährleistet auch die Sicherheit, indem potenzielle Schwachstellen identifiziert werden, die behoben werden müssen, bevor sie ausgenutzt werden können.

  • Stellt kontinuierliche Compliance sicher. Automatisierte statische Analyse gewährleistet die kontinuierliche Einhaltung relevanter Standards wie MISRA und CERT für Branchen für eingebettete Softwaretests wie Automobil, Medizintechnik und Luft- und Raumfahrt mit strengen gesetzlichen Anforderungen. Dies ist entscheidend für das Bestehen von Audits und Zertifizierungen, die eine statische Analyse erfordern.
  • Eliminiert sich wiederholende, alltägliche Aufgaben. Entwickler müssen keine sich wiederholenden und banalen Aufgaben wie die Überprüfung von Code und die Zuweisung identifizierter Codeverstöße zur Behebung ausführen. Parasoft wendet patentierte KI- und ML-Lösungen auf den statischen Analyse-Workflow an, um festgestellte Regelverstöße zu priorisieren und Abhilfemaßnahmen zu optimieren. Dadurch wird der Teamaufwand bei der Einführung statischer Analysen sofort reduziert. Entwickler können sich auf komplexere und kreativere Aspekte der Softwareentwicklung konzentrieren, was zu einer höheren Arbeitszufriedenheit und Produktivität führt.

Unit Tests

Während die statische Analyse wertvolle Einblicke in die Codequalität und potenzielle Probleme ohne Ausführung liefert, überprüft Unit-Tests das tatsächliche Verhalten und die Richtigkeit des Codes bei der Ausführung. Die gemeinsame Verwendung beider Techniken gewährleistet einen robusteren und zuverlässigeren Softwareentwicklungsprozess, da sie sich ergänzen und ein breiteres Spektrum potenzieller Probleme abdecken.

Trotz dieser Vorteile haben Entwicklungsteams jedoch oft Probleme, ausreichend Unit-Tests durchzuführen. Die Einschränkungen hinsichtlich der Testmenge sind auf mehrere Faktoren zurückzuführen, beispielsweise den Druck, schnell mehr Funktionalität bereitzustellen, und die Komplexität und der Zeitaufwand bei der Erstellung wertvoller Unit-Tests.

Entwickler nennen häufig die folgenden Gründe, die die Effizienz von Unit-Tests als zentrale Entwicklungspraxis einschränken.

  • Es ist schwierig, die Abhängigkeiten der zu testenden Einheit zu verstehen, zu initialisieren und/oder zu isolieren.
  • Die Bestimmung dessen, was validiert werden soll, und die Definition geeigneter Aussagen ist zeitaufwändig und erfordert häufig intelligentes Raten.
  • Dabei ist viel manuelle Codierung erforderlich, oft sogar mehr als zur Implementierung einer bestimmten Funktion oder Verbesserung erforderlich wäre.
  • Es ist einfach nicht so interessant. Entwickler wollen sich nicht wie Tester fühlen. Sie wollen ihre Zeit damit verbringen, mehr Funktionalität zu liefern.

Tools zur Automatisierung von Unit-Tests unterstützen allgemein eine Art Test-Framework, das die Harness-Infrastruktur bereitstellt, um Units isoliert auszuführen und gleichzeitig Abhängigkeiten über Stubs zu erfüllen. Dazu gehört die automatische Generierung von Test-Harnesses und den ausführbaren Komponenten, die für host- und zielbasierte Tests erforderlich sind.

Die Generierung und Verwaltung von Testdaten ist jedoch die größte Herausforderung bei Unit-Tests und Testgenerierung. Testfälle müssen eine ganze Reihe von Validierungsrollen abdecken, wie z. B. die Sicherstellung funktionaler Anforderungen, die Erkennung unvorhersehbaren Verhaltens und die Gewährleistung von Sicherheits- und Schutzanforderungen. Und das alles unter Einhaltung der Test-Coverage-Kriterien.

Die automatische Testgenerierung verringert die Ineffizienz von Unit-Tests, indem sie die Schwierigkeiten bei Initialisierung, Isolierung und Abhängigkeitsverwaltung beseitigt. Außerdem entfällt ein Großteil der erforderlichen manuellen Codierung und gleichzeitig wird die Verwaltung der Testdaten erleichtert, die zur Durchführung von Verifizierung und Validierung erforderlich sind.

Statische Analyse in eingebetteten Systemen

Die statische Codeanalyse bietet eine Vielzahl von Metriken, mit denen verschiedene Aspekte der Sicherheit, Zuverlässigkeit, Leistung und Wartbarkeit von eingebettetem Code bewertet werden können. Sie bieten jeweils wertvolle Informationen zu verschiedenen Aspekten der Integrität des Codes. Eine dieser Metriken ist die zyklomatische Komplexität, die die Anzahl linear unabhängiger Pfade durch den Quellcode eines Programms misst.

Eine höhere Komplexität bedeutet ein höheres Fehlerpotenzial und ist schwieriger zu lesen, zu warten und zu testen. Weitere Werte, die eine statische Analyse liefern kann und die selbst keine Qualitätsmaßstäbe sind, aber ein Gefühl für die Wartbarkeit vermitteln, sind:

  • Gesamtzahl der Codezeilen
  • Kommentardichte
  • Klassenkopplung oder -kohäsion
  • Funktionslänge

Interessante Metriken, die statische Analysen liefern können, aber im Allgemeinen nicht angewendet werden, sind Codeabdeckung und Leistungsmetriken. Obwohl die Codeabdeckung üblicherweise durch Unittests erfasst wird, kann die statische Analyse diese Metrik liefern und sogar toten Code finden. Die Leistungsmetrik wird gemessen, indem Code identifiziert wird, der zu Leistungsproblemen führen kann, wie z. B. ineffiziente Schleifen oder rekursive Aufrufe. Es gibt viele andere Metriken rund um Ressourcennutzung, Duplizierung, Nullzeiger und Division durch Null.

Durch die Nutzung dieser bereitgestellten Metriken hilft die statische Codeanalyse Entwicklern, potenzielle Probleme frühzeitig im Entwicklungszyklus zu erkennen, die Codequalität und Wartbarkeit zu verbessern und die Einhaltung von Codierungsstandards und Best Practices sicherzustellen.

Unit-Tests in eingebetteten Systemen

Die Softwareüberprüfung und -validierung ist ein wesentlicher Bestandteil der Entwicklung eingebetteter Software, und Tests sind eine wichtige Methode, um das korrekte Verhalten der Software nachzuweisen. Unit-Tests dienen der Überprüfung des Moduldesigns. Sie stellen sicher, dass jede Softwareeinheit das tut, was sie tun soll.

Darüber hinaus können Sicherheitsanforderungen erfordern, dass sich Softwareeinheiten nicht unerwartet verhalten und nicht anfällig für Manipulationen durch unerwartete Dateneingaben sind.

Im Hinblick auf das klassische V-Modell der Entwicklung ist die Durchführung von Unit-Tests eine Validierungspraxis, um sicherzustellen, dass das Moduldesign korrekt ist. Viele sicherheitsspezifische Entwicklungsstandards enthalten Richtlinien für das, was bei Unit-Tests getestet werden muss. Beispielsweise enthalten ISO 61502 und verwandte Standards spezifische Richtlinien für Tests gemäß Sicherheitsintegritätsstufen, wobei anforderungsbasierte Tests und Schnittstellentests für alle Stufen dringend empfohlen werden. Fehlereinfügungs- und Ressourcennutzungstests werden bei niedrigeren Integritätsstufen und bei den höchsten SIL-Stufen (Safety Integrity Levels) dringend empfohlen. Ebenso wird die Methode zum Ausführen von Testfällen mit empfohlenen Praktiken angegeben.

Testfalltreiber

Symbol in einem blauen Kreis, das einen weiß umrandeten Schraubenschlüssel in einem weiß umrandeten Zahnrad zeigt.

Analyse der Anforderungen 

Jede Anforderung führt mindestens zu einem einzelnen Unit-Testfall. Obwohl Testautomatisierungstools keine Tests direkt aus Anforderungen generieren, müssen sie die bidirektionale Rückverfolgbarkeit von Anforderungen zum Code und von Anforderungen zum Test unterstützen. Außerdem müssen sie Informationen zu Anforderungen, Tests und Codeabdeckung pflegen.

Symbol innerhalb eines blauen Kreises mit einem weißen kreisförmigen Pfeil, der mit einer gepunkteten Linie beginnt und durchgezogen wird.

Generierung und Analyse von Äquivalenzklassen

Testfälle müssen sicherstellen, dass sich Einheiten bei einer Reihe von Eingaben gleich verhalten und nicht nur ausgewählte Eingaben für jede Einheit. Testautomatisierungstools müssen die Generierung von Testfällen mithilfe von Datenquellen unterstützen, um eine große Bandbreite von Eingabewerten effizient nutzen zu können.

Blauer Kreis mit dem Symbol einer Lupe mit weißem Rand, die auf offene und geschlossene weiße Caretzeichen zoomt.

Analyse der Grenzwerte

Automatisch generierte Testfälle, wie etwa heuristische Werte und Grenzwerte, nutzen Datenquellen, um in Tests ein breites Spektrum an Eingabewerten nutzen zu können.

Symbol in einem blauen Kreis, das einen weiß umrandeten Kreis mit einem weißen Fragezeichen darin zeigt.

Fehler beim Schätzen 

Diese Methode verwendet den Funktionsstub-Mechanismus, um Fehlerbedingungen in die Ergebnisse der getesteten Codeflussanalyse einzufügen, und kann zum Schreiben zusätzlicher Tests verwendet werden.

Automatisierte Testausführung

Die Testautomatisierung bietet große Vorteile für eingebettete Software. Durch die Abkehr von Testsuiten, die viel manuelles Eingreifen erfordern, können Tests schneller, einfacher und häufiger durchgeführt werden. Durch die Auslagerung dieses manuellen Testaufwands wird Zeit für eine bessere Testabdeckung und andere Sicherheits- und Qualitätsziele frei. Eine wichtige Voraussetzung für die automatisierte Ausführung von Testsuiten ist die Möglichkeit, diese Tests sowohl in Host- als auch in Zielumgebungen auszuführen.

Eine Grafik, die den auf einem Laptop angezeigten Parasoft C/C++test zeigt, der Tests und die Kommunikation vom Host zu einem eingebetteten Ziel abbildet.
Eine umfassende Ansicht der Bereitstellung, Ausführung und Beobachtung von Tests vom Host bis zum eingebetteten Ziel.

Zielbasiertes Testen für eingebettete Systeme

Die Automatisierung von Tests für eingebettete Software ist aufgrund der Komplexität der Initiierung und Überwachung von Tests auf der Zielhardware eine größere Herausforderung. Ganz zu schweigen vom eingeschränkten Zugriff der Softwareteams auf die Zielhardware.

Die Automatisierung von Softwaretests ist unerlässlich, um eingebettete Tests vom Host-Entwicklungssystem bis zum Zielsystem durchgängig durchführen zu können. Das Testen eingebetteter Software ist besonders zeitaufwändig. Die Automatisierung der Regressionstestsuite ermöglicht erhebliche Zeit- und Kosteneinsparungen. Darüber hinaus sind Testergebnisse und die Erfassung von Codeabdeckungsdaten vom Zielsystem für die Validierung und die Einhaltung von Standards unerlässlich.

Die Rückverfolgbarkeit zwischen Testfällen, Testergebnissen, Quellcode und Anforderungen muss aufgezeichnet und aufrechterhalten werden. Daher ist die Datenerfassung bei der Testausführung von entscheidender Bedeutung.

Strukturelle Codeabdeckung

Das Sammeln und Analysieren von Code Coverage-Metriken ist ein wichtiger Aspekt der sicherheitskritischen Softwareentwicklung. Die Code Coverage misst den Abschluss von Testfällen und ausgeführten Tests. Sie liefert den Nachweis, dass die Validierung abgeschlossen ist, zumindest wie im Softwaredesign angegeben. Sie identifiziert auch toten Code. Dies ist Code, der logisch nie erreicht werden kann. Sie zeigt die Abwesenheit unbeabsichtigten Verhaltens. Code, der durch keinen Test abgedeckt ist, ist ein Risiko, da sein Verhalten und seine Funktionalität unbekannt sind.

Umfang und Ausmaß der Codeabdeckung hängen vom Sicherheitsintegritätslevel ab. Je höher das Integritätslevel, desto strenger muss vorgegangen werden, und damit auch die Anzahl und Komplexität der Testfälle. Unabhängig vom erforderlichen Abdeckungsgrad kann die Testabdeckung durch die automatisierte Generierung von Testfällen mit der Zeit erhöht werden.

Fortgeschrittene Tools zur Automatisierung von Unit-Tests sollten diese Code-Coverage-Metriken messen. Darüber hinaus ist es notwendig, dass diese Datensammlung bei Host- und Zieltests funktioniert und im Laufe der Zeit den Test-Coverage-Verlauf ansammelt. Dieser Code-Coverage-Verlauf kann Unit-, Integrations- und Systemtests umfassen, um sicherzustellen, dass die Abdeckung auf allen Testebenen vollständig und nachvollziehbar ist.

Arten der automatisierten Testfallgenerierung

Aus praktischen Gründen sollten automatisierte Tools Testfälle in vorhandenen, bekannten Formaten wie CppUnit generieren. Standardmäßig ist eine Testsuite pro Quell-/Headerdatei sinnvoll, aber Tools sollten bei Bedarf eine Testsuite pro Funktion oder eine Testsuite pro Quelldatei unterstützen.

Ein weiterer wichtiger Aspekt sind die automatischen Stub-Definitionen zum Ersetzen „gefährlicher“ Funktionen, darunter System-E/A-Routinen wie rmdir(), remove(), rename() usw. Darüber hinaus können Stubs automatisch für fehlende Funktions- und Variablendefinitionen generiert werden. Benutzerdefinierte Stubs können nach Bedarf hinzugefügt werden.

Anforderungsbasierte Testfallgenerierung

Obwohl Testautomatisierungstools keine Anforderungstests aus der Dokumentation ableiten können, können sie dazu beitragen, die Erstellung von Testfällen, Stubs und Mocks einfacher und effizienter zu gestalten. Darüber hinaus verbessert die Automatisierung das Testfalldatenmanagement erheblich und die Toolunterstützung für parametrisierte Tests reduziert auch den manuellen Aufwand.

Besonders wichtig ist die Rückverfolgbarkeit von Anforderungen über Code bis hin zu Tests und Testergebnissen. Die manuelle Verwaltung der Rückverfolgbarkeit ist nahezu unmöglich, und die Automatisierung macht die Rückverfolgbarkeit zur Realität.

Während die Anforderungen zerlegt werden, muss die Rückverfolgbarkeit während der gesamten Entwicklungsphasen aufrechterhalten werden, da sich die Kundenanforderungen in System-, High-Level- und Low-Level-Anforderungen zerlegen. Die Codierungs- oder Implementierungsphase realisiert die Low-Level-Anforderungen. Betrachten Sie das typische V-Diagramm von Software.

Grafik, die das V-Modell der Softwareentwicklung zur Erfüllung von Anforderungen, Systemdesign, Architekturdesign, Moduldesign und Codierung zeigt.
Das V-Modell der Systementwicklung mit Traceability-Overlay.

Jede Phase steuert die nachfolgende Phase. Die Workitems oder verfeinerten Anforderungen jeder Phase müssen wiederum die Anforderungen aus der vorherigen Phase erfüllen. Architekturanforderungen, die aus dem Systemdesign erstellt oder zerlegt wurden, müssen das Systemdesign/die Systemanforderungen erfüllen und so weiter.

Durch die Rückverfolgbarkeit wird nachgewiesen, dass jede Phase die Anforderungen der jeweiligen nachfolgenden Phase erfüllt.

Entwickler schreiben Code, der jede Anforderung implementiert oder realisiert. Für sicherheitskritische Anwendungen werden Links zur Rückverfolgbarkeit zu Testfällen und bis zum Code erstellt. Wenn sich also eine Kundenanforderung ändert oder entfernt wird, weiß das Team, welche Auswirkungen dies auf die gesamte Kette hat, bis hin zum Code und den Tests, die die Anforderungen validieren.

Industrienormen wie DO-178B/C, ISO 26262, IEC 62304, IEC 61508, EN 50128 und andere erfordern die Erstellung einer Rückverfolgbarkeitsmatrix zur Identifizierung etwaiger Lücken im Design und zur Überprüfung der Anforderungen. Dies hilft dabei, das ultimative Ziel zu erreichen, das richtige Produkt zu bauen. Darüber hinaus soll sichergestellt werden, dass das Produkt die Qualität und Sicherheit aufweist, um sicherzustellen, dass es das richtige Produkt bleibt.

Parasoft-Rückverfolgbarkeitsmatrix der Jama-Anforderungen an Tests und Code.

Code Coverage-basierte Testfallgenerierung

Die Erstellung produktiver Unit-Tests war schon immer eine Herausforderung. Die Einhaltung funktionaler Sicherheitsstandards erfordert qualitativ hochwertige Software, was wiederum den Bedarf an Test-Suites mit hohen Code-Coverage-Statistiken steigert. Teams benötigen Unit-Testfälle, die ihnen helfen, eine 100-prozentige Code-Coverage zu erreichen. Das ist leichter gesagt als getan. Die Analyse von Verzweigungen im Code und der Versuch, Gründe zu finden, warum bestimmte Codeabschnitte nicht abgedeckt sind, raubt den Entwicklungsteams weiterhin viel Zeit.

Tools zur Automatisierung von Unit-Tests können verwendet werden, um die Abdeckungslücken in Test-Suites zu schließen. Beispielsweise wird eine erweiterte statische Codeanalyse (Daten- und Kontrollflussanalyse) verwendet, um Werte für die Eingabeparameter zu finden, die zum Ausführen bestimmter Zeilen nicht abgedeckten Codes erforderlich sind.

Es ist auch nützlich, wenn Sie über automatisierte Tools verfügen, die nicht nur die Codeabdeckung messen, sondern auch verfolgen, wie viel geänderter Code durch Tests abgedeckt wird, da dies Aufschluss darüber geben kann, ob neben Änderungen im Produktionscode auch genügend Tests geschrieben werden. Sehen Sie sich den folgenden Beispielbericht zur Codeabdeckung an.

Parasoft-Rückverfolgbarkeitsmatrix der Jama-Anforderungen an Tests und Code.

Verwenden der Codeanalyse zum Erstellen abdeckungsbasierter Testfälle

In komplexem Code gibt es immer diese schwer fassbaren Codeanweisungen, deren Abdeckung äußerst schwierig ist. 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 bieten, die Sie benötigen. Durch die Kombination von Testautomatisierung und statischer Analyse können Sie diese schwer erreichbaren Codezeilen leicht abdecken. Ein Beispiel für mit Codeanalyse berechnete Testvoraussetzungen finden Sie im Coverage Advisor.

Screenshot des C/C++test Coverage Advisor, der erforderliche Abhängigkeiten, Voraussetzungen und die vollständige Abdeckung zeigt.
Generierung von Defekt-Testfällen

Eine weitere Testklasse sind solche, die erstellt werden, um einen Fehlerzustand in der zu testenden Einheit zu induzieren. Die Eingabeparameter in diesen Fällen liegen oft außerhalb der Grenzen und entsprechen genau den Randbedingungen für Datentypen, wie z. B. die Verwendung der höchsten 32-Bit-positiven und negativen Ganzzahlen für Testdaten. Andere Beispiele sind Fuzz-Tests, bei denen diese Randbedingungen mit zufälligen Daten gemischt werden, um einen Fehlerzustand zu erzeugen oder eine Sicherheitslücke auszulösen.

Diese Testfälle validieren nichtfunktionale Anforderungen, da sie außerhalb des Geltungsbereichs der Produktanforderungen liegen, sind jedoch für die Bestimmung von Leistung, Sicherheit, Zuverlässigkeit und anderen Produktqualitäten von entscheidender Bedeutung. Automatisierung ist unerlässlich, da diese Tests zahlreich sein können (Fuzz-Tests) und auf wiederholte Ausführung (Leistungstests) angewiesen sind, um Qualitätsprobleme zu erkennen. Die Generierung von Testfällen trägt dazu bei, den manuellen Aufwand zum Erstellen dieser Testsuites zu reduzieren.

Regressionstests

Im Rahmen der meisten Softwareentwicklungsprozesse werden nach Änderungen an der Software Regressionstests durchgeführt. Diese Tests ermitteln, ob die neuen Änderungen Auswirkungen auf den bestehenden Betrieb der Software hatten. Die Verwaltung und Ausführung von Regressionstests machen einen großen Teil des Aufwands und der Kosten beim Testen aus. Selbst bei automatisierter Testgenerierung ist die Testausführung, das Sammeln von Ergebnissen und das erneute Ausführen von Tests sehr zeitaufwändig. Regressionstests umfassen die Wartung von Testfällen, Verbesserungen der Codeabdeckung und Rückverfolgbarkeit.

Regressionstests sind notwendig, zeigen jedoch nur an, dass aktuelle Codeänderungen nicht zu fehlgeschlagenen Tests geführt haben. Es gibt keine Garantie dafür, dass diese Änderungen funktionieren. Darüber hinaus kann die Art der Änderungen, die Regressionstests erforderlich machen, über die aktuelle Anwendung hinausgehen und Änderungen an Hardware, Betriebssystem und Betriebsumgebung umfassen.

Tatsächlich müssen möglicherweise alle zuvor erstellten Testfälle ausgeführt werden, um sicherzustellen, dass keine Regressionen vorliegen und eine neue, zuverlässige Softwareversion erstellt wird. Dies ist von entscheidender Bedeutung, da auf jeder neuen Version eines Softwaresystems oder -subsystems aufgebaut oder diese weiterentwickelt wird. Wenn Sie keine solide Grundlage haben, kann das Ganze zusammenbrechen.

Um dies zu verhindern, ist es wichtig, Regressionstest-Baselines zu erstellen, die eine organisierte Sammlung von Tests darstellen und alle Ergebnisse automatisch überprüfen. Diese Tests werden regelmäßig automatisch ausgeführt, um zu überprüfen, ob Codeänderungen die in den Regressionstests erfasste Funktionalität ändern oder beeinträchtigen. Wenn Änderungen eingeführt werden, werden diese Testfälle das Team nicht auf das Problem aufmerksam machen. Bei nachfolgenden Tests meldet Parasoft C++test Aufgaben, wenn es Änderungen am im ersten Test erfassten Verhalten erkennt.

So entscheiden Sie, was getestet werden soll

Die größte Herausforderung bei Regressionstests besteht darin, zu bestimmen, welche Teile einer Anwendung getestet werden sollen. Es ist üblich, standardmäßig alle Regressionstests auszuführen, wenn Zweifel darüber bestehen, welche Auswirkungen die letzten Codeänderungen hatten – der Alles-oder-Nichts-Ansatz.

Bei großen Softwareprojekten wird dies zu einem riesigen Unterfangen und mindert die Produktivität des Teams. Diese Unfähigkeit, Tests zu fokussieren, behindert viele der Vorteile iterativer und kontinuierlicher Prozesse, was bei eingebetteter Software, bei der Testziele eine begrenzte Ressource sind, möglicherweise noch verstärkt wird.

Hier sind einige Aufgaben erforderlich.

  1. Identifizieren Sie, welche Tests erneut ausgeführt werden müssen.
  2. Konzentrieren Sie Ihre Testbemühungen (Unit-Tests, automatisierte Funktionstests und manuelle Tests) auf die Validierung der Funktionen und des zugehörigen Codes, die von den aktuellsten Änderungen betroffen sind.

Testwirkungsanalyse

Die Test Impact Analysis (TIA) verwendet während Testläufen und Codeänderungen zwischen Builds gesammelte Daten, um zu ermitteln, welche Dateien geändert wurden und welche spezifischen Tests diese Dateien berührt haben. Die Analyse-Engine von Parasoft kann das Delta zwischen zwei Builds analysieren und die Teilmenge der Regressionstests identifizieren, die ausgeführt werden müssen. Sie versteht auch die Abhängigkeiten von den geänderten Einheiten, um zu bestimmen, welche Auswirkungen die Änderungen auf andere Einheiten hatten.

Konzentrieren Sie sich auf das Risiko

Aufgrund der Komplexität heutiger Codebasen kann jede noch so harmlose Codeänderung die Anwendungsstabilität subtil beeinträchtigen und letztendlich das System „kaputt machen“. Diese unbeabsichtigten Folgen lassen sich durch manuelle Überprüfung nicht erkennen, daher sind Tests entscheidend, um das damit verbundene Risiko zu mindern. Solange nicht klar ist, was neu getestet werden muss, kann kein effizientes Testverfahren erreicht werden. Wenn in jedem Sprint oder jeder Iteration zu viel getestet wird, verringert sich die Effizienz der Testautomatisierung. Zu wenig zu testen ist keine Option.

Der beste Ansatz besteht darin, zu ermitteln, welche Tests erneut ausgeführt werden müssen, und die Testbemühungen (Unit-Tests, automatisierte Funktionstests und manuelle Tests) auf die Validierung der Funktionen und des zugehörigen Codes zu konzentrieren, die von den jüngsten Änderungen betroffen sind.

Dies wird mit TIA und Planungstests auf der Grundlage eines datengesteuerten Ansatzes namens „änderungsbasiertes Testen“ ermittelt.

TIA benötigt ein Repository mit bereits abgeschlossenen Tests, die bereits für jeden Build ausgeführt wurden, entweder als Teil eines vollautomatischen Testprozesses (z. B. eines CI-gesteuerten Build-Schritts) oder während des Testens der neuen Funktionalität. Diese Analyse bietet Einblicke, wo im Code die Änderungen aufgetreten sind, wie die vorhandenen Tests mit diesen Änderungen korrelieren und worauf sich die Testressourcen konzentrieren müssen. Nachfolgend sehen Sie ein Beispiel für eine TIA.

Von hier aus wird der Regressionstestplan erweitert, um fehlgeschlagene und unvollständige Testfälle mit höchster Priorität zu behandeln und die Empfehlungen für erneute Tests zu nutzen, um die Planung zusätzlicher automatisierter Läufe zu konzentrieren und manuelle Testbemühungen zu priorisieren.

Das Testen ist ein großer Engpass bei der Entwicklung eingebetteter Software. Am Ende des Release-Zyklus werden zu viele Mängel festgestellt, weil nicht ausreichend oder fehlgeleitet getestet wurde. Um optimale Ergebnisse zu erzielen, konzentrieren Sie Ihre Testbemühungen auf die Auswirkungen der vorgenommenen Änderungen, um die Effizienz der Testautomatisierung zu nutzen.

Vorteile der automatisierten Testgenerierung

Durch die automatische Generierung von Testfällen werden menschlicher Aufwand, Fehler und Langeweile beim Unit-Testing vermieden und die Entwicklung eingebetteter Software kommt auf verschiedene Weise zugute.

Symbol in einem blauen Kreis, das einen weißen, nach unten zeigenden Pfeil zeigt.

Reduziert die Arbeitskosten

Die Automatisierung von Unit-Tests an sich ist ein Produktivitätsschub für die Entwicklung eingebetteter Software, da manuelle Tests auf Zielhardware zeitaufwändig sind. Außerdem ist es schwierig, die Codeabdeckung und die Rückverfolgbarkeit der Anforderungen sicherzustellen. Die automatisierte Generierung von Testfällen steigert die Produktivität von Entwicklern und Testern weiter und eliminiert den manuellen Aufwand für die Erstellung und Wartung von Unit-Tests.

Symbol in einem blauen Kreis, das einen weiß umrandeten Blitz zeigt.

Verkürzt die Markteinführungszeit

Die Produktivitätssteigerungen durch Testautomatisierung sparen Geld und verkürzen die Zeit, die ein Softwareprodukt benötigt, um zum endgültigen Lieferprodukt zu gelangen. Eine höhere Abdeckung, häufigere und gründlichere Tests und eine vollständige Rückverfolgbarkeit der Anforderungen werden schneller erreicht als bei eher Ad-hoc-Techniken. Die Markteinführungszeit wird weiter verkürzt, wenn diese Praktiken mit Agile-Entwicklung, CI/CD und DevSecOps-Pipelines kombiniert werden. Darüber hinaus berichten Kunden von qualitativ hochwertigeren Produkten und entdecken weniger Fehler.

Symbol in einem blauen Kreis, das ein weiß umrandetes Compliance-Abzeichen zeigt.

Erfüllt die Normenkonformität

Um die Einhaltung von Industrienormen für Sicherheit und Schutz zu gewährleisten, ist der Einsatz von Automatisierung erforderlich. Ob Codierung, Entwicklung oder Tests: Automatisierung ist erforderlich, um den Prozess zu dokumentieren, die Rückverfolgbarkeit zu erfassen und eine angemessene Verifizierung und Validierung nachzuweisen.

Bei sicherheitskritischen Geräten ist die Validierung von entscheidender Bedeutung, da der Entwickler nachweisen muss, dass er nicht nur die Produktanforderungen erfüllt, sondern auch das von der Branche erwartete Maß an Sicherheit gewährleistet hat. Die Generierung von Unit-Tests ist ein wertvolles Tool, um die Abdeckung zu erhöhen, die Tests zur Erkennung möglicher Fehlerzustände auszuweiten und die Anforderungsvalidierung zu erfüllen.

Symbol in einem blauen Kreis, das ein weiß umrandetes Sicherheitsschild mit einem Häkchen in der Mitte zeigt.

Verbessert Qualität und Sicherheit

Eine verbesserte Codeabdeckung und bessere Tests für Sicherheit, Leistung und Zuverlässigkeit werden durch mehr Testfälle und die automatische Generierung von Testfällen erreicht. Dieses verbesserte Testverfahren wird durch Automatisierung mit höherer Produktivität und mehr Tests im gleichen Entwicklungszeitraum ermöglicht. Das Endergebnis ist verbesserte Sicherheit und Qualität. Softwareunternehmen entwickeln ihre Prozesse im Allgemeinen mit der Zeit weiter. Diese Verbesserungen erstrecken sich über mehr als nur ein Produkt und die Vorteile bleiben über den gesamten Produktlebenszyklus bestehen, der bei eingebetteten Geräten deutlich länger ist.

Zusammenfassung

Tests sind für die Entwicklung eingebetteter Software unerlässlich. Sie fördern das wahre Verständnis des entwickelten Codes und bilden eine solide Grundlage für ein Verifizierungs- und Validierungsprogramm, das zur Erfüllung der Sicherheitsziele eines Produkts erforderlich ist.

Die statische Analyse ist eine wichtige Technik in der Softwareentwicklung, bei der Quellcode untersucht wird, ohne ihn auszuführen, um potenzielle Probleme zu identifizieren und die allgemeine Codequalität zu verbessern. Wenn Teams sie von Anfang an verwenden, bietet die statische Analyse folgende Vorteile:

  • Bietet wertvolle Einblicke in Codekomplexität, Wartbarkeit, Sicherheitslücken und Einhaltung von Codierungsstandards.
  • Hilft, Fehler zu vermeiden.
  • Optimiert die Leistung.
  • Stellt die Einhaltung bewährter Methoden und gesetzlicher Anforderungen sicher.

Die Integration statischer Analysen in den Entwicklungsablauf führt zu einer robusteren und wartungsfreundlicheren Codebasis. Dies muss in Verbindung mit Unit-Tests erfolgen, um nicht als Produktivitätsbremse zu empfunden zu werden.

Die Einschränkungen der Testproduktivität sind auf mehrere Faktoren zurückzuführen, beispielsweise auf den Druck und die Zeit, die zur Bereitstellung erweiterter Funktionen erforderlich ist, sowie auf die Komplexität und den Zeitaufwand bei der Erstellung wertvoller Tests.

Die Generierung und Verwaltung von Testdaten ist bei weitem die größte Herausforderung beim Unit-Testing und bei der Testgenerierung. Testfälle sind besonders wichtig bei der sicherheitskritischen Softwareentwicklung, da sie funktionale Anforderungen sicherstellen und auf unvorhersehbares Verhalten sowie Sicherheits- und Schutzanforderungen testen müssen. Und das alles unter Einhaltung der Test-Coverage-Kriterien.

Die automatische Testgenerierung verringert die Ineffizienz von Unit-Tests, indem sie die Schwierigkeiten bei der Initialisierung und Isolierung sowie bei der Verwaltung von Abhängigkeiten beseitigt. Außerdem entfällt ein Großteil der erforderlichen manuellen Codierung und gleichzeitig wird die Verwaltung der Testdaten erleichtert, die zur Durchführung von Verifizierung und Validierung erforderlich sind. Dies verbessert Qualität und Sicherheit. Außerdem werden Testzeit, Kosten und Markteinführungszeit reduziert.

Rechteckiges Bannerbild mit überwiegend dunkelblauer Farbe und abgewinkelter Ecke in Standardblau. In der oberen rechten Ecke befindet sich eine Collage aus Parasoft-Produktsymbolen für DTP, C/C++test, CTP, Jtest, Selenic, Insure++, C/C++test CT, dotTEST, Virtualize und SOAtest.

Verbessern Sie Ihre Softwaretests mit Parasoft-Lösungen.