Modulare Design-basierte Testmethoden für eingebettete Software
2026-02-21 10:57:30··#1
Zusammenfassung: Dieser Artikel analysiert die Eigenschaften eingebetteter Software und gibt einen Überblick über traditionelle Softwaretestmethoden. Basierend auf diesen Eigenschaften werden ein vierstufiger Testprozess und ein Integrationstestmodell vorgeschlagen und anhand der Entwicklung eines CNC-Systems analysiert. Schlüsselwörter: Eingebettet; Modular. Eingebettete Systeme sind zu einem wesentlichen Bestandteil der industriellen Modernisierung und der Entwicklung intelligenter Systeme geworden, und eingebettete Produkte finden in verschiedenen Branchen Anwendung. Eingebettete Systeme zeichnen sich durch einen hohen Spezialisierungsgrad und eine relativ geringe Systemvererbung aus. Um die Systemstabilität zu gewährleisten, ist das Softwaretesten zu einem entscheidenden Aspekt der Entwicklung eingebetteter Systeme geworden. Aufgrund der inhärenten Eigenschaften eingebetteter Software lassen sich traditionelle Softwaretesttheorien nicht direkt auf das Testen eingebetteter Software anwenden; daher ist die Forschung im Bereich des Testens eingebetteter Software von großer Bedeutung. 1. Grundlagen 1.1 Modulares Design Software-Design basiert auf bestimmten Methoden. Angesichts zunehmend komplexer Softwareentwicklungsaufgaben wurden verschiedene Software-Designmodelle vorgeschlagen. Ausgehend von den Benutzerbedürfnissen und den vom System zu erfüllenden Funktionen wird große Software in relativ kleinere Module unterteilt. Um die Korrelation zwischen Modulen zu reduzieren, sind die logischen Strukturen zwischen Modulen relativ unabhängig, es gibt keine funktionsübergreifenden Aufrufe, und der Datentransfer erfolgt über globale Variablen. Dies ist die Grundidee des modularen Designs. Kern des modularen Designs ist die Unabhängigkeit der Module, insbesondere die funktionale und strukturelle Unabhängigkeit. Dadurch wird die Arbeitsteilung in der Softwareentwicklung erleichtert. Softwaretests sind ein zentrales Element der Softwareentwicklung. Das auf modularem Design basierende Softwaretestmodell ist einfach, und Fehlererkennung und -korrektur lassen sich leicht implementieren. Im Folgenden werden die Grundprinzipien des Softwaretests im modularen Softwaredesign anhand eines Softwaremodells mit einfacher Datenübertragung veranschaulicht. Die Funktion F(X-Y) ist die Schnittstellenfunktion zwischen Softwaremodul X und Softwaremodul Y. Sie dient dazu, die Daten von Modul X über das Terminal an Modul Y zu übermitteln. Tritt nach der Ausführung von Modul C ein Fehler auf, prüft die Datenschnittstellenfunktion F(B-C) zwischen Modul B und Modul C, ob die von Modul B ausgegebenen Daten fehlerhaft sind. Ist F(B-C) korrekt, liegt der Fehler in Modul C. Überträgt F(B-C) fehlerhafte Daten, wird geprüft, ob die von F(A-B) übertragenen Daten fehlerhaft sind. Ist dies der Fall, liegt der Fehler in Modul B. Durch die sequentielle Fehlerisolierung lässt sich das fehlerhafte Modul leicht lokalisieren. Dies ist das Grundprinzip des Softwaretests im modularen Design. 1.2 Eingebettete Systeme Die Entwicklung eingebetteter Systeme weist spezifische Merkmale auf. In der Regel beginnt die Hardwareentwicklung, die primär die Erstellung einer Bare-Metal-Plattform, die Portierung eines Echtzeitbetriebssystems nach Bedarf und die Entwicklung von Hardwaretreibern umfasst. Nach erfolgreichem Test der Hardwareplattform basieren Softwareentwicklung und -debugging auf dieser Plattform, die gleichzeitig als Test für die Hardwareplattform selbst dient. Der Entwicklungsprozess eines eingebetteten Systems lässt sich daher als ein Prozess der gegenseitigen Koordination, des Feedbacks und des Testens zwischen Software und Hardware beschreiben. Im Allgemeinen sind die Grenzen zwischen Treibern, Betriebssystemen und Anwendungen in eingebetteten Systemen fließend und können je nach Bedarf sogar verschwimmen. Dies liegt hauptsächlich an der Abhängigkeit der Software von der Hardware in eingebetteten Systemen. Diese Hardwareabhängigkeit erfordert, dass Softwaretests die tatsächliche Betriebsumgebung der zu testenden Software so genau wie möglich simulieren, um die Testzuverlässigkeit zu gewährleisten. Die unklaren Grenzen zwischen Programmen und Anwendungen erhöhen die Schwierigkeit des Testens. Anwendungstests können erst nach Bestätigung der Korrektheit der eingebetteten Systemplattform und der Low-Level-Programme durchgeführt werden. Zudem gestaltet sich die Fehlerlokalisierung während Systemtests schwieriger. Die Spezialisierung der Software ist ein weiteres Hauptmerkmal eingebetteter Software. Da das Design eingebetteter Software auf einer spezifischen Zielhardwareplattform basiert und auf eine festgelegte Aufgabe ausgerichtet ist, muss ihre Funktionalität nach dem Laden auf das Zielsystem vollständig definiert sein. Diese Eigenschaft führt zu einer geringen Vererbung eingebetteter Anwendungssoftware, was die Systemtestzeit verlängert und die Testkosten erhöht. Ein weiteres wichtiges Merkmal eingebetteter Software ist die Echtzeitfähigkeit. Dies erklärt sich aus der Perspektive der Softwareausführung: Die Ausführung eingebetteter Software muss bestimmte Zeitvorgaben erfüllen. In eingebetteten Systemen bestimmen die Komplexität des Algorithmus der Anwendungssoftware und die Aufgabenplanung des Betriebssystems die Zuweisung und den Verbrauch von Systemressourcen. Daher ist es beim Testen der Echtzeitfähigkeit des Systems notwendig, geeignete Testwerkzeuge einzusetzen, um die Komplexität des Anwendungsalgorithmus und die Aufgabenplanung des Betriebssystems zu analysieren und zu testen. Es ist offensichtlich, dass eingebettete Software im Vergleich zu traditioneller objektorientierter und prozeduraler Software eigene Merkmale aufweist. Die Erforschung von Tests eingebetteter Software auf Basis dieser Merkmale ist notwendig und sinnvoll. 1.3 Tests eingebetteter Software Softwaretests dienen der Sicherstellung der Qualität und Korrektheit von Softwarecode unter wirtschaftlichen und effizienten Gesichtspunkten. Sie sind ein wichtiger Bestandteil der Softwareentwicklung und ein zentrales Bindeglied zwischen Entwicklung und Anwendung. Eingebettete Software bildet hier keine Ausnahme. Softwaretests haben sich zunehmend zu einer ausgereiften Disziplin entwickelt. Frühere Forschungen befassten sich intensiv mit dem Testen objektorientierter und prozeduraler Nicht-Echtzeit-Software, und die meisten Methoden lassen sich auch auf Tests eingebetteter Software anwenden. Softwaretestmethoden können anhand verschiedener Metriken kategorisiert werden. Je nach Phase des Softwareentwicklungsprozesses lassen sich Modultests, Integrationstests und Systemtests unterteilen. Abhängig davon, ob der Zielcode ausgeführt werden muss, unterscheidet man zwischen dynamischen und statischen Tests; je nach Sichtbarkeit des Zielcodes zwischen White-Box-Tests (strukturelle Tests) und Black-Box-Tests (funktionale Tests). In der Softwaretestung sind die einzelnen Testmethoden nicht isoliert. Um die Testziele möglichst wirtschaftlich und effektiv zu erreichen, werden verschiedene Testmethoden häufig kombiniert. Beispielsweise können in der Unit-Testphase von Software Black-Box- und White-Box-Testverfahren für dynamische Tests eingesetzt werden. Es ist erwähnenswert, dass die Codeabdeckung in den letzten Jahren zunehmend zu einem einheitlichen Standard im Softwaretest geworden ist. Daher ist die Maximierung der Codeabdeckung im Softwaretest unabhängig vom verwendeten Testverfahren unerlässlich. Die Codeabdeckung im Softwaretest basiert auf White-Box-Testverfahren. Um die Codeabdeckung zu verbessern, müssen Tester die Struktur des Quellcodes verstehen und Zugriff auf die Programmdokumentation haben, um Testfälle zu entwerfen, die möglichst jede Anweisung in der internen Programmstruktur abdecken und somit die Codeabdeckung erhöhen. 2. Ein vierstufiger Testprozess für eingebettete Software basierend auf modularem Design: Um die Systemfunktionalität bei eingebetteten Systemen möglichst wirtschaftlich zu erreichen, wird ein Top-Down-Ansatz mit schichtweiser Prüfung gewählt. Im vierstufigen Testprozess können Fehler aus vorherigen Testphasen, die nach Abschluss der Tests dieser Phase gefunden werden, in eine Warteschlange gestellt und in dieser Testphase lokalisiert werden. Dies ist zwar keine absolut genaue Methode, maximiert aber die Zeitersparnis bei der Fehlerlokalisierung. 2.1 Systemplattformtest Dieser Abschnitt umfasst Hardware-Schaltungstests, Betriebssystem- und Treibertests usw. Hardware-Schaltungstests erfordern spezielle Testwerkzeuge. Darauf wird hier nicht weiter eingegangen. Betriebssystem- und Treibertests umfassen hauptsächlich die Prüfung der Aufgabenplanung, der Echtzeitfähigkeit und der Datenübertragungsrate der Kommunikationsschnittstellen. Nach Abschluss dieser Testphase sollte das System eine vollständige Embedded-Systemplattform darstellen, auf der Benutzer lediglich Anwendungen zur Ausführung spezifischer Aufgaben hinzufügen müssen. 2.2 Modultest Große Embedded-Softwaresysteme werden in mehrere relativ kleine Aufgabenmodule unterteilt, die von verschiedenen Programmierern parallel codiert werden. Nach der Codierung muss jedes Modul vor der Integration getestet werden. Da keine Unterstützung für den Datentransfer zwischen Datenmodulen besteht, wird diese Testphase auf dem Host-Rechner durchgeführt (der über umfangreiche Ressourcen und eine komfortable Debugging-Umgebung verfügt). Diese Phase umfasst hauptsächlich White-Box-Tests, bei denen jede Funktion, jede bedingte Verzweigung und jede Programmanweisung so gründlich wie möglich getestet wird, um die Testabdeckung des Codes zu verbessern. Da die Gesamtintegration nur dann notwendig ist, wenn die einzelnen Module korrekt funktionieren, müssen die Modultests gründlich und vollständig sein. In der Modultestphase werden Testfälle erstellt, die nicht nur den normalen Systembetrieb prüfen, sondern auch Grenzwerttests durchführen. Grenzwerttests umfassen die Prüfung der Maximal- und Minimalwerte einer Datenvariablen sowie die Durchführung von Grenzwerttests, d. h. die Eingabe von Datenvariablen, die nicht eingegeben werden sollten, um den Systembetrieb zu testen. Ein ideales eingebettetes System sollte nicht durch Benutzerinteraktionen abstürzen; dies ist eine grundlegende Anforderung an das Design eingebetteter Systeme. Daher sollten Systemabstürze unabhängig von der Testart als Testfehler behandelt werden. In der Modultestphase können große Module, basierend auf den Grundprinzipien der modularen Programmierung, entsprechend ihrer internen Kompaktheit in kleinere Module unterteilt werden. Innerhalb des Programms werden Schnittstellenfunktionen für den Datenaustausch zwischen den kleineren Modulen implementiert, um Fehler schnell zu lokalisieren. Die Verwendung dieses verschachtelten Modulansatzes für Softwaretests erfordert eine klare interne Modulstruktur und einfache Datenverbindungen. 2.3 Integrationstest: Nachdem jedes einzelne Softwaremodul erfolgreich getestet wurde, werden alle Module für den Integrationstest integriert. Diese Phase zielt primär darauf ab, Fehler in der Datenübertragung zwischen Modulen und in der logischen Struktur des Gesamtsystems zu identifizieren. Die Tests auf dem Host-Rechner nutzen eine Kombination aus Black-Box- und White-Box-Methoden, um die reale Betriebsumgebung so genau wie möglich zu simulieren. Dabei werden Funktionen ausgeblendet, die die Systemausführung nicht beeinflussen und deren Datenübertragung schwer zu simulieren ist. Die Integrationstests sind die Phase, in der die Vorteile des modularen Software-Designs voll zum Tragen kommen. Vor den Integrationstests müssen Programmierer Modulschnittstellenfunktionen basierend auf den Ein- und Ausgaben der Daten zwischen den Modulen erstellen. Dies erfordert die Koordination der für die verschiedenen Softwaremodule verantwortlichen Programmierer. Anschließend werden die Modulschnittstellenfunktionen in den Eingangspunkt des empfangenden Datenmoduls integriert. Wie die vorherige Analyse zeigt, lässt sich das fehlerhafte Softwaremodul bei Integrationstests von Softwaremodulen mit Single-Link-Datenübertragung leichter lokalisieren. Die Daten eines Softwaremoduls werden nicht zwangsläufig nur von einem anderen Modul bereitgestellt; das heißt, die Datenverbindung eines Softwaremoduls ist nicht notwendigerweise eine Single-Link-Verbindung. Während der Tests kann die Datenübertragung komplexer Verbindungsstrukturen zur Fehlerlokalisierung in Single-Link-Datenübertragungen unterteilt werden. Änderungen am Ausgabedaten-Softwaremodul können neue Fehler im Eingabedaten-Softwaremodul verursachen. Daher wird hier eine Assoziationsmatrix eingeführt, um Module zu identifizieren, die nach einer Änderung wichtige Tests erfordern. Angenommen, die modular aufgebaute Software des eingebetteten Systems besteht aus Softwaremodulen Ai (i = 1, 2, …, m, n), wobei m die Zeilennummer und n die Spaltennummer der Matrix darstellt. In der Assoziationsmatrix bedeutet Aij = 1, dass Aj Daten von Ai empfangen hat. Wird Ai also geändert und erneut getestet, muss auch Aj erneut getestet werden. Integrationstests, bei denen Programmdesigndokumente, Programmstruktur und Datenstruktur verfügbar sind, prüfen auf Fehler, die während der Integration der Softwaremodule auftreten. Während der Integrationstests werden Fehler anhand der Modulschnittstellenfunktionen lokalisiert und behoben. Die Assoziationsmatrix dient dazu, die erneut zu testenden Softwaremodule zu bestimmen. 2.4 Systemtest Nach Abschluss der Integrationstests wird die Host-Testumgebung verlassen und das System zur Anwendung im Feld auf den Zielrechner portiert. Aus Anwendersicht werden Black-Box-Tests durchgeführt, um jede spezifische Funktion zu überprüfen. Da der Tester keine Kenntnisse über Programminhalte und -ausführung besitzt, ist die Fehlerlokalisierung in dieser Testphase relativ schwierig. Während der Systemtestphase sollten unerwartete und destruktive Tests durchgeführt werden. Dies beinhaltet das Auslösen von Aktivitäten und destruktiven Aktionen, die im normalen Systembetrieb nicht auftreten sollten, um die Systemleistung weiter zu überprüfen. Der Code sollte nicht unmittelbar nach der Identifizierung eines Fehlers während des Systemtests geändert werden. Stattdessen sollte ein Testzyklus basierend auf der Häufigkeit des Fehlerauftretens festgelegt werden. Am Ende jedes Testzyklus sollte der Code geändert und der Test wiederholt werden. Andernfalls erhöht sich nicht nur der Arbeitsaufwand für die vollständigen Tests, sondern es verringert sich auch die Zuverlässigkeit der Tests. 2.5 Analyse der Testergebnisse Die Analyse der Testergebnisse kann Fehler lokalisieren, Programmierer bei der Codeänderung unterstützen und das getestete Programm sowie die Testrichtung aufzeigen. Die Analyse der Testergebnisse ist ein Prozess der Analyse, des Vergleichs und der Lokalisierung von Fehlern anhand von Testergebnissen und erwarteten Testergebnissen. Die Analyse der Testergebnisse ist der letzte Schritt eines Tests. Während der Analyse sollten die Unterschiede zwischen der Betriebsumgebung der Software und der tatsächlichen Betriebsumgebung sowie der Einfluss verschiedener externer Faktoren berücksichtigt werden. 2.6 Erstellung und Verwaltung von Testfällen Testfälle sind Dateien, die für das Zielprogramm entwickelt werden und Eingabeparameter sowie erwartete Ergebnisse enthalten. Abhängig von der Testumgebung und dem Zielprogramm können sie Dokumente in einem bestimmten Format sein oder auf einem spezifischen Eingabeverhalten (z. B. einem einzelnen Tastendruck) basieren. Testfälle sollten so erstellt werden, dass sie möglichst viele Wertebereiche abdecken und eine umfassende Testabdeckung des gesamten Programmcodes gewährleisten, während redundante, sich wiederholende und sinnlose Tests vermieden werden. In verschiedenen Phasen des Tests eingebetteter Software sollten unterschiedliche Testfälle erstellt werden. In der Systemplattform-Testphase sollten Testfälle für die Systemaufgabenplanung, die Echtzeitleistung und die Low-Level-Treiber erstellt werden. In der Modul-Testphase sollten Testfälle für spezifische Module erstellt werden. In der Integrations-Testphase sollten entsprechende Testfälle für Datentransfer- und Strukturierungsprobleme während der Systemintegration erstellt werden. In der System-Testphase sollten Testfälle für eine oder mehrere kombinierte Funktionen erstellt oder bereits auf ähnlichen Produkten validierte Testfälle verwendet werden. Testfälle sollten wiederverwendbar sein. Darüber hinaus gibt es in der Entwicklung umfangreicher Software viele Arten von Testfällen, die mit einer spezifischen Methode verwaltet werden müssen. Die Verwendung einer Datenbank zur Verwaltung von Testfällen ist eine gute Wahl. Testfälle können nach Testphase kategorisiert und anschließend durch Schlüsselwörter eindeutig identifiziert werden. Dies vereinfacht die Verwendung, Änderung und Speicherung von Testfällen; Testfälle können direkt über Abfragen abgerufen werden. 3. Softwaretests des CNC-Systems: Dieses CNC-System verwendet einen ARM7-Prozessor und ein μC/OS-Echtzeitbetriebssystem und ist somit ein typisches eingebettetes System. Aufgrund der Komplexität des CNC-Systems wurden die Aufgaben während der Entwicklung detailliert aufgeteilt und eine modulare Entwicklung gewählt. Während der Entwicklung wurden mehrere Module von verschiedenen Programmierern programmiert, die auch Modultests durchführten und Abdeckungstests mit White-Box-Testmethoden durchführten. Vor den abschließenden Integrationstests schrieben die Programmierer basierend auf der Korrelationsmatrix gemeinsam die Modulschnittstellenfunktionen F(A1-A2), F(A1-A4), F(A1-A5), F(A1-A6), F(F2-A3), F(A3-A4), F(A4-A5), F(F5-A6) und F(A6-A2). Die Analyse zeigt, dass die Testcodeabdeckung einiger Schlüsselmodule, wie beispielsweise des Dekodierungsmoduls und des Werkzeugkompensationsmoduls, über 90 % erreichte. 4. Fazit: Nach der Analyse der Eigenschaften eingebetteter Software und traditioneller Testmethoden schlägt diese Arbeit einen vierstufigen Testprozess und ein Integrationstestmodell vor. Diese Testmethode wird für die Prüfung von Steuerungen für Baumaschinen und die Entwicklung von CNC-Systemen eingesetzt. Die Effizienz und Zuverlässigkeit des Tests erfüllen die Anforderungen. Die in dieser Arbeit beschriebenen Methoden, wie die Fehlerlokalisierung bei der Datenübertragung über eine einzelne Verbindung, Modulschnittstellenfunktionen und Korrelationsmatrizen, können auch auf objektorientierte und eingebettete Softwaresysteme angewendet werden.