Software testen mit SIL Hand in Hand zu einem besseren Ergebnis

Oft sind die Entwicklung von Software und Hardware noch getrennt. Jedoch birgt das die Gefahr von fehlerhaftem Quellcode. Besser ist es, Soft- und Hardware zusammen zu entwickeln und zu testen.

Software in the Loop (SIL) stammt aus der modellbasierten Softwareentwicklung und bezeichnet ein Framework, das zwischen einer Software und der Simulation ihrer noch nicht einsatzfähigen Zielhardware vermittelt. Software in the Loop ist entweder zum Beschleunigen eines Projektes, zum Verbessern der Testabdeckung oder zum nachträglichen Einführen von automatisierten Tests in ein Legacy-Projekt (ein älteres, quasi ererbtes Projekt) einsetzbar. Hierbei kann SIL auf vielfältige Arten zum Einsatz kommen. Bei immer kürzeren Entwicklungszyklen und wachsenden Ansprüchen an Softwarequalität kann es ein sehr nützliches Tool zum Erreichen der Ziele sein. Außerdem kann SIL einen Mehrwert für Kunden und Softwareproduzenten schaffen. Der Beitrag skizziert Motivation und Prinzipien von System- und Integrationstests anhand des Ansatzes Software in the Loop und diskutiert dessen Vorteile sowie Grenzen.

Ein typischer Zielkonflikt in Embedded-Projekten sind die Abhängigkeiten zwischen Hard- und Softwareentwicklung. Zum Zeitpunkt ihres Programmierens ist Software aus unterschiedlichen Gründen oft nicht mit der realen Hardware zu testen: Entweder ist diese noch nicht fertig entwickelt, es ist bloß ein Prototyp vorhanden, es liegt ungetesteter Legacy Code vor oder Negativtests sind nötig, die die reale Hardware beschädigen würden. Die zum Quasistandard gewordene agile Produktentwicklung erfordert das häufige Testen kleiner Inkremente (Continuous Integration). Hiermit fließen während des Entwickelns gemachte Erfahrungen und neue Anforderungen direkt zurück.

Softwareentwickler benötigen sehr häufig noch nicht verfügbare Hardware, um ihre Software zu entwickeln und zu testen. Hardwareentwickler ihrerseits sind nach Fertigstellen der Hardware nicht mehr optimal ausgelastet, falls nicht bereits das nächste Projekt startet. Bei optimalem Projektablauf würden Softwareentwicklung und Tests gleichzeitig mit der Hardwareentwicklung starten. Während dem späteren Entwickeln gemachte Erfahrungen und neue Anforderungen können Entwickler direkt einpflegen und Probleme bei der Hardware verzögern nicht eins zu eins das Projekt. Zum Auflösen des Zielkonflikts kann SIL in einer simulierten Hardwareumgebung dienlich sein (Bild 1).

Mit Simulationen zum Erfolg

Als Ansatz kann der Entwickler die Umgebung mithilfe einer oder mehrerer Simulationen (Hardware Simulation, HS) ersetzen. Hierbei will man softwareseitige Abhängigkeiten von Input befriedigen, der im Realfall von der Hardware geliefert wird. Außerdem will man das Abfangen von Output der Software zu Testzwecken garantieren. Als Software in the Loop wird das Vorgehen bezeichnet, die gesamte Hardwareumgebung der zu entwickelnden Anwendung auf einem PC als Simulation abzubilden und alle Schnittstellen (Anwendung und Treiber) mit den Daten aus der Simulation zu versorgen. Die Anwendung wird also auf dem Entwicklungsrechner kompiliert und ausgeführt, nicht mit einem Cross-Compiler für das Zielsystem. Soweit nötig, wird die zukünftige Systemumgebung, zum Beispiel Hardware (hydraulische Pumpen oder eine Netzwerkschnittstelle), in die Simulation integriert.

Voraussetzung zur Umsetzung des SIL-Ansatzes ist eine bestimmte Schichtarchitektur, die unter anderem eine Hardwareabstraktion verwendet. Eine gründliche Analyse der Testzwecke ist erforderlich, um den nötigen Umfang und die Funktionsbreite der Hardwaresimulation zu bestimmen: Im einen Fall sind einfache Interaktionen zwischen Software und der HS ausreichend, während im anderen Fall kompliziertere Aktionen wie die Simulation eines Temperaturanstiegs erforderlich sind. Geschicktes Design des SIL-Frameworks ermöglicht es, die HS schließlich durch die reale Zielhardware zu ersetzen, ohne die Tests neu schreiben zu müssen.

Als logisches Gegenstück zu SIL gibt es überdies das Konzept der Hardware in the Loop (HIL). Dabei wird einer steuernden Hardware – die sich in der Entwicklung befindet – die später zu steuernde Softwareumgebung über einen Simulator vorgespielt. SIL und HIL werden nicht selten nebeneinander in Entwicklungen eines Gesamtsystems eingesetzt.

Frühzeitig Fehler minimieren

Im Kontext moderner Softwareentwicklung und vor allem sicherheitsrelevanter Anwendungen nimmt der Softwaretest eine immer wichtigere Rolle ein. System- und Integrationstests führen Prüfungen der Interaktion und des Zusammenspiels mehrerer Komponenten aus. Sie können lediglich in einer lauffähigen Umgebung stattfinden. Das können Unit-Tests nicht abdecken, für die oft lauffähige Hardware noch gar nicht vorliegt. SIL beseitigt die Restriktionen und macht die entwickelte Softwarelogik testbar – noch bevor Hardware verfügbar ist. So ist sie auf jedem Entwicklerrechner prüfbar. Demnach ist nicht für jeden Entwickler der Prototyp einer Hardware bereitzustellen, was in manchen Fällen aus diversen Gründen nicht möglich ist.

Während der Phase, in der noch kein Ausführen des Codes möglich ist – weil sich beispielsweise die SIL noch in der Aufbauphase befindet – sind die Tests zunächst klar auf Fehlerprävention fokussiert: Mit formellen und informellen Reviews von Anforderungsdokumentationen, Architekturmodellen und  Schnittstellenbeschreibungen etwa können Entwickler frühzeitig Fehler minimieren, die sich bevorzugt während des Integrationstests zeigen. Einerseits sind das inkompatible Schnittstellen in der Kommunikation zwischen Komponenten, andererseits übergreifende Funktionen, die sich erst aus dem Zusammenspiel mehrerer Komponenten ergeben. Sobald der Entwickler die Software in der SIL ausführen kann, verschiebt sich der Testfokus auf die Fehleraufdeckung – mit dem Ausführen von Testfällen auf dem Testobjekt.

Abfangen von SoftwareSchnittstellen

Was ist nun alles umzusetzen, um die Embedded-Software unabhängig von einer realen Hardware kompilieren und anschließend ausführen zu können?

Zunächst ist sicherzustellen, dass die Software eine Hardwareabstraktion nutzt (HAL, Bild 2). Wenn direkt auf Hardwareregister zugegriffen wird, wie bei älterer Microcontroller-Software üblich, ist sie soweit anzupassen, dass lediglich ein einziger Funktionsaufruf den Zugriff ausführt und somit abfängt (engl. Intercept). Das bedeutet, dass der Funktionsaufruf über eine Schnittstelle, die der realen Hardware gleicht, von einem Treiber empfangen wird. Zudem sind alle in Assembler-Sprache entwickelten Programmteile zu deaktivieren oder umzuschreiben, da sie üblicherweise auf der Host-Plattform nicht verfügbar sind.

Um ebenfalls die Software auf dem Host-System laufen zu lassen, sind gegebenenfalls weitere Systemanteile zu ersetzen. Falls die Embedded-Software kein öffentliches Betriebssystem nutzt, ist sie direkt ausführbar. Falls sie jedoch auf einem proprietären Betriebssystem aufsetzt, ist dessen Funktion nachzustellen. Weil der Host-Rechner in jedem Fall mit einem Betriebssystem ausgestattet ist, werden die Funktionen des Zielsystems auf Funktionen des Host-Systems abgebildet.

Abfangen von HardwareSchnittstellen

Ein Treiber stellt sich der Anwendung als Softwareschnittstelle für die Hardware dar, die abzufangen und mit Aufrufen an ein SIL-Framework zu ersetzen ist. Hierbei werden alle Anfragen der Anwendung an den Treiber umgesetzt und über eine Schnittstelle mit der Simulationsumgebung für die Hardware verknüpft. Sie erzeugt dieselben Reaktionen und gibt sie über die entsprechenden Treiberschnittstellen – etwa Interrupt-Callbacks, Funktionsrückgabewerte und so weiter – an die Anwendung zurück. Für die meisten Anwendungen ist ein Eingriff auf der untersten Treiberebene nicht nötig und deutlich zu aufwendig.

Bei Anwendungen mit Legacy-Code sind die bereits entwickelten Hardwaretreiber meist gründlich in der Praxis erprobt und sind nicht vorrangig zu testen. Hier lässt sich der Entwicklungsaufwand für die Simulation deutlich verringern, indem in der Anwendung vorhandene höhere Abstraktionsebenen, zum Beispiel für Peripherien, als Schnittstelle zum SIL-Framework genutzt werden. Meist sind es die Änderungen an der höheren Logik der Anwendung, die aufgrund ihrer Komplexität und unerwarteten Verhaltens testaufwendig und risikoreich für den Entwickler sind. Hier können die mit einer SIL eingeführten Regressionstests mehr Vertrauen ins Produkt und ein schnelleres Entwickeln mithilfe automatisierter Tests erzeugen.