Das Testen von Embedded-Systemen wird mit zunehmender Komplexität erheblich schwerer. Die Methode des Contract Based Design eröffnet eine neue Perspektive und sehr effektive Vorgehensweisen, wenn man sie erweitert und auf Tests anwendet.
Testen aus einer anderen Perspektive: Contract Based Testing erlaubt eine viel exaktere Spezifikation von Abläufen in einem System und hilft, versteckte Events oder Zustände aufzudecken und zu verfolgen.
Testen wird häufig reduziert auf das Entwickeln und Durchführen manueller oder automatisierter Testabläufe. Betrachten wir zunächst die wesentlichen Ziele des Testens:
Bewertung der Funktionalität und Qualität eines Systems
Erkenntnisgewinn zur Behebung oder Vermeidung von Fehlern
Wir erweitern den Begriff des Tests daher auf alle Methoden, welche diese beiden Ziele unterstützen. Dies können z.B. auch Reviews, formale Verifikation oder Laufzeitmonitoring sein.
Die Herausforderung
Um die Ziele zu erreichen, müssen vor allem drei Fragen beantwortet werden:
Wie spezifiziert man das geforderte oder verbotene Verhalten eindeutig und hinreichend vollständig?
Wie erzeugt man daraus Prüfungen, die mit hoher Wahrscheinlichkeit bereits während der Entwicklung fehlerhaftes Verhalten entdecken?
Wie findet man Fehler, die erst beim Einsatz des Systems auftreten, z.B. durch fehlerhafte Verwendung oder Umgebungsbedingungen?
In vielen Fällen kann man diese Fragen recht elegant durch den Einsatz von Contracts beantworten.
Klassische Contracts nach Bertrand Meyer
Design by Contract (DbC) wurde entwickelt und eingeführt durch Bertrand Meyer. DbC erlaubt die Definition formaler Verträge für Schnittstellen und Verhalten von Software-Komponenten. Pre- und Post-Conditions, Invarianten und Seiteneffekte definieren die Semantik von Funktionen. Sprachen wie Ada und Eiffel unterstützen die Definition und Validierung von Contracts.
Bild 1: Contracts in der Sprache C.
(Bild: www.protos.de)
Hier ein Beispiel für die Umsetzung eines sehr einfachen Contracts mit Pre- und Post-Conditions in der Sprache C mit Hilfe von Asserts. Diese Art von Contracts wird auf der Komponentenebene definiert, also für Schnittstellen von Funktionen, Klassen oder C-Modulen. Die daraus resultierenden Prüfungen können daher auch nur auf dieser Ebene erfolgen. Für Prüfungen zur Designzeit benötigt man die Unterstützung der Sprache (z.B. Ada und Eiffel). Integrations- und Systemtests für Embedded Systeme sind damit kaum möglich.
Bild 2: Test-Ebenen und Test-Zeitpunkt für klassische Contracts
(Bild: www.protos.de)
Contract-Erweiterungen
Wir benötigen Erweiterungen der Contracts, die es ermöglichen asynchrones, nebenläufiges Verhalten für alle Ebenen eines Systems formal zu beschreiben. Eine exzellente Methode hierfür sind Interface Statemachines. Reihenfolgen und zeitliches Verhalten (temporale Logik) von synchronen oder asynchronen Aufrufen können damit sehr exakt spezifiziert werden. Außerdem sind Statemachines eine Methode, die den meisten Embedded-Entwicklern bekannt ist.
Die Interface Statemachine definiert zu jedem Zeitpunkt, welche Aufrufe erlaubt sind. Jeder andere Aufruf ist verboten. Dies reduziert die Anzahl der erlaubten Aufrufreihenfolgen um Größenordnungen. Kann man die Einhaltung des spezifizierten Verhaltens testen oder zur Laufzeit überwachen, führt dies zu erheblich einfacheren Systemen, die wesentlich weniger Fehler enthalten.
Das folgende Beispiel (Bild 3) zeigt die Spezifikation aller erlaubten Aufrufe an einer einfachen Schnittstelle als Interface Statemachine. Nur auf Grund der C-API kann man z.B. folgende Fragen nicht beantworten:
Ist der Aufruf von function1 direkt nach initialize erlaubt?
Muss ich nach stop wieder initialize aufrufen?
Spezifiziert man die erlaubte Reihenfolge als Interface Statemachine, so kann man die Fragen schnell und eindeutig beantworten:
Nach initialize muss man zunächst start aufrufen. Danach ist der Aufruf von function1 erlaubt.
Nein nach stop muss nicht initialize aufgerufen werden. Es darf nur start aufgerufen werden.
Die Anzahl der erlaubten Aufrufreihenfolgen reduziert sich für den einmaligen Aufruf aller Funktionen von 120 auf 6, bei 3 Iterationen, bereits von ca. 10 hoch 12 auf 300.000.
Bild 3: Beispiel für Statemachine als Interface Contract
(Bild: www.protos.de)
Interface Contracts sind also eine äußerst effektive Möglichkeit, formal erlaubtes und verbotenes Verhalten an Schnittstellen auf allen Ebenen zu spezifizieren. Die zu testenden Zustände kann man damit meist um viele Größenordnungen reduzieren. Ein angenehmer Nebeneffekt ist die hervorragende und eindeutige Dokumentation der Schnittstellenabläufe.
Prüfung der Contracts
Die spezifizierten Contracts können zu drei verschiedenen Zeitpunkten überprüft werden:
Zur Designzeit (Zeitpunkt der Programmierung oder Modellierung)
Zur Testzeit (Zeitpunkt der Durchführung der Unit-, Integrations- und Systemtests)
Zur Laufzeit (System im Produktivbetrieb)
Am Beispiel des Open-Source-Werkzeuges eTrice und der Testsprache CaGe für miniHIL Systeme wird gezeigt, wie solche Prüfungen aussehen können.
Prüfung zur Designzeit (Formale Verifikation)
Im Rahmen des Forschungsprojektes Contract Based Modeling & Design (CBMD) wurde das Werkzeug eTrice und die Sprache ROOM (Real-Time Object-Oriented Modeling) um Contracts erweitert. Die Methoden werden bereits in der Praxis eingesetzt.
Im folgenden Beispiel wird die Schnittstellenspezifikation der Ports (fct und terminal) zwischen den Komponenten (Strukturmodell) um einen Contract (Interface Statemachine) erweitert.
Bild 4: Contract-Prüfung in eTrice zur Designzeit
(Bild: www.protos.de)
Die Aktoren enthalten jeweils ein Modell ihres Verhaltens als Implementierungs-Statemachine. Während der Modellierung werden die Implementierungs-Statemachines laufend gegen den Contract geprüft. Verstöße gegen den Contract werden im Modell angezeigt. Die Generierung der Implementierung aus dem Modell stellt sicher, dass das korrekte Verhalten des Modells auch im Code umgesetzt wird.
Stand: 08.12.2025
Es ist für uns eine Selbstverständlichkeit, dass wir verantwortungsvoll mit Ihren personenbezogenen Daten umgehen. Sofern wir personenbezogene Daten von Ihnen erheben, verarbeiten wir diese unter Beachtung der geltenden Datenschutzvorschriften. Detaillierte Informationen finden Sie in unserer Datenschutzerklärung.
Einwilligung in die Verwendung von Daten zu Werbezwecken
Ich bin damit einverstanden, dass die Vogel Communications Group GmbH & Co. KG, Max-Planckstr. 7-9, 97082 Würzburg einschließlich aller mit ihr im Sinne der §§ 15 ff. AktG verbundenen Unternehmen (im weiteren: Vogel Communications Group) meine E-Mail-Adresse für die Zusendung von redaktionellen Newslettern nutzt. Auflistungen der jeweils zugehörigen Unternehmen können hier abgerufen werden.
Der Newsletterinhalt erstreckt sich dabei auf Produkte und Dienstleistungen aller zuvor genannten Unternehmen, darunter beispielsweise Fachzeitschriften und Fachbücher, Veranstaltungen und Messen sowie veranstaltungsbezogene Produkte und Dienstleistungen, Print- und Digital-Mediaangebote und Services wie weitere (redaktionelle) Newsletter, Gewinnspiele, Lead-Kampagnen, Marktforschung im Online- und Offline-Bereich, fachspezifische Webportale und E-Learning-Angebote. Wenn auch meine persönliche Telefonnummer erhoben wurde, darf diese für die Unterbreitung von Angeboten der vorgenannten Produkte und Dienstleistungen der vorgenannten Unternehmen und Marktforschung genutzt werden.
Meine Einwilligung umfasst zudem die Verarbeitung meiner E-Mail-Adresse und Telefonnummer für den Datenabgleich zu Marketingzwecken mit ausgewählten Werbepartnern wie z.B. LinkedIN, Google und Meta. Hierfür darf die Vogel Communications Group die genannten Daten gehasht an Werbepartner übermitteln, die diese Daten dann nutzen, um feststellen zu können, ob ich ebenfalls Mitglied auf den besagten Werbepartnerportalen bin. Die Vogel Communications Group nutzt diese Funktion zu Zwecken des Retargeting (Upselling, Crossselling und Kundenbindung), der Generierung von sog. Lookalike Audiences zur Neukundengewinnung und als Ausschlussgrundlage für laufende Werbekampagnen. Weitere Informationen kann ich dem Abschnitt „Datenabgleich zu Marketingzwecken“ in der Datenschutzerklärung entnehmen.
Falls ich im Internet auf Portalen der Vogel Communications Group einschließlich deren mit ihr im Sinne der §§ 15 ff. AktG verbundenen Unternehmen geschützte Inhalte abrufe, muss ich mich mit weiteren Daten für den Zugang zu diesen Inhalten registrieren. Im Gegenzug für diesen gebührenlosen Zugang zu redaktionellen Inhalten dürfen meine Daten im Sinne dieser Einwilligung für die hier genannten Zwecke verwendet werden. Dies gilt nicht für den Datenabgleich zu Marketingzwecken.
Recht auf Widerruf
Mir ist bewusst, dass ich diese Einwilligung jederzeit für die Zukunft widerrufen kann. Durch meinen Widerruf wird die Rechtmäßigkeit der aufgrund meiner Einwilligung bis zum Widerruf erfolgten Verarbeitung nicht berührt. Um meinen Widerruf zu erklären, kann ich als eine Möglichkeit das unter https://contact.vogel.de abrufbare Kontaktformular nutzen. Sofern ich einzelne von mir abonnierte Newsletter nicht mehr erhalten möchte, kann ich darüber hinaus auch den am Ende eines Newsletters eingebundenen Abmeldelink anklicken. Weitere Informationen zu meinem Widerrufsrecht und dessen Ausübung sowie zu den Folgen meines Widerrufs finde ich in der Datenschutzerklärung, Abschnitt Redaktionelle Newsletter.
Der Hauptvorteil ist die frühe Erkennung und Behebung von Bugs und potenziellen Problemen. Durch die formale Verifikation werden viele Probleme entdeckt, die durch Tests sehr schwer zu finden sind. Ein Beispiel sind Race Conditions, die zu sporadisch auftretenden, unklaren und kaum reproduzierbaren Fehlersituationen führen.
Eine Einschränkung der formalen Verifikation ist, dass man ein formales Applikationsmodell benötigt, um es zu prüfen. Wird die Applikation nicht modelliert, sondern mit einer Programmiersprache wie C implementiert, so ist die formale Verifikation nur schwer zu realisieren.
Prüfung zur Laufzeit (Monitoring)
Ein weiteres Ergebnis des CBMD Projektes ist die Generierung von Contract Monitoren in eTrice/ROOM Modellen. Diese Monitore werden in die Kommunikationsverbindung zwischen den Komponenten oder zu anderen Systemen eingebaut und erlauben die Prüfung von Contracts zur Laufzeit. Hierfür sind folgende Teilfunktionen nötig:
Monitoring: Entdeckung des Fehlverhaltens zur Laufzeit
Filterung und Eindämmung: Aktion zur Verhinderung von Fehlverhalten, z.B. durch Verhinderung oder Korrektur des fehlerhaften Aufrufs an der Schnittstelle oder die Umschaltung in einen sicheren Zustand
Analyse der Ursache und Debugging: Logging eines Sequenzdigramms mit der Fehlerursache und dem exakten Ablauf rund um das Fehlverhalten
Bild 5: Contract-Prüfung in eTrice zur Laufzeit
(Bild: www.protos.de)
Im folgenden Beispiel hat der aus dem Contract generierte Monitor zur Laufzeit ein Fehlverhalten entdeckt. Im generierten Sequenzdiagramm sieht man den exakten Zeitpunkt, Verlauf und die Ursache. Die entstehenden Systeme sind sehr robust gegen Fehlverhalten an den Schnittstellen. Dies ist ein entscheidender Vorteil auch bei Systemen, die Safety- oder Security-Anforderungen haben.
Ein Vorteil des Laufzeit Monitorings ist, dass man auch Applikationen und Schnittstellen, die nicht modelliert wurden, sehr gut mit Monitoren verbessern kann.
Prüfung zur Testzeit (Test-Case-Generierung)
Zur Generierung von Test Cases sind die Interface Statemachines im Allgemeinen nicht sehr gut geeignet, da sie keine Aussagen über das Gesamtverhalten eines Systems under Test (SUT) machen.
State Transition Test als Contract zur Test-Case-Generierung
(Bild: www.protos.de)
Statt der Interface Statemachines verwenden wir in der Test Sprache CaGe daher State Transition Tests. Mit State Transition Tests kann man das erwartete Black Box Verhalten (Contract) eines SUT als State Transition Diagramm beschreiben. Daraus können kombinatorische Test Cases generiert werden, welche mit sehr hoher Abdeckung die erlaubten und verbotenen Pfade im SUT testen. Ebenso kann man damit die Datenkombinatorik z.B. für Aufruf- oder Konfigurationsparameter testen.
State Transition Testing ist eine effektive Methode um schnell und strukturiert zu hohen Testabdeckungen zu kommen. Für kleinere Probleme oder geringere Testabdeckungen kann man mit Stift und Papier Test Cases ableiten und die Tests manuell implementieren. Für größere Abdeckungen ist es sinnvoll Werkzeuge mit Test Case Generator zu verwenden.
Zusammenfassung
Erweiterte Contracts …
ermöglichen die formale Spezifikation von Schnittstellen nicht nur auf Komponenten-, sondern auch auf Integrations- und Systemebene
sind verwendbar für synchrone und asynchrone Systeme (Embedded Systeme)
erlauben die exakte Spezifikation von Abläufen und zeitlichen Bedingungen
können in allen Entwicklungsphasen zur Verifikation verwendet werden (Design - Test - Laufzeit)
ermöglichen für viele Bereiche eine sehr hohe Abdeckung
können für automatische Generierung von Testfällen und Monitoren verwendet werden
Thomas Schütz studierte Luft- und Raumfahrttechnik in München und gründete 1997 die PROTOS Software GmbH. Als Softwareprojektleiter oder Architekt konnte er seine Erfahrung in der Verbindung modellbasierter Ansätze mit den Anforderungen von Embedded Systemen in zahlreiche Projekte einbringen. Thomas Schütz berät Firmen beim Aufbau von domänenspezifischen Werkzeugketten und Testsystemen für Embedded Systeme und ist Projektleiter des Eclipse Projektes eTrice.