Software-Qualität durch automatisierten Funktionstest
|< back
 
2002-04-19

von Frank Büchner

Testen ist ein fester Bestandteil des Entwicklungsprozesses von Embedded Software und die Notwendigkeit von Tests zur Erlangung von Software-Qualität ist unbestritten. Trotzdem gibt es speziell im Bereich der dynamischen Unit-Tests nur wenige Werkzeuge, die dem Software-Entwickler bei dieser meist ungeliebten Tätigkeit helfen.

Vorgehen in der Praxis
Der dynamische Funktionstest von Embedded Software wird meist manuell und interaktiv durchgeführt. Dazu lädt man das zu testende Programm in einen Simulator oder in das tatsächliche Zielsystem, etwa mit Hilfe eines JTAG-Debuggers oder eines In-Circuit-Emulators, der sowohl mit als auch ohne Zielsystem eingesetzt werden kann.

Manueller Test
Beim manuellen Test wird das Programm schrittweise ausgeführt und man beobachtet, ob es sich wie erwartet verhält. Will man den Test mit anderen Werten durchführen, kann man den Debugger benutzen, um vor Aufruf der Funktion die Werte im Speicher des Zielsystems wie gewünscht zu setzen. Oft werden zusätzliche, speziell für den Test geschriebene Programmteile implementiert, um bestimmte Eingaben für die Funktion zur Verfügung zu stellen. Nimmt man die Tests manuell vor, ist dies mühselig und auch fehleranfällig, denn der (menschliche) Tester kann Fehlverhalten übersehen. Vor allem stehen bei manuellen Tests die Eingabe-Werte und das Resultat für spätere Wiederholungen der Tests meist nicht mehr zur Verfügung.

Eigene Testdatenverwaltung
Komfortable Debugger erlauben, die Eingabewerte aus einer Datei zu entnehmen. Meist lässt sich das Ergebnis der Funktion durch den Debugger mit Werten aus dieser Datei vergleichen und so ist zu erkennen, ob der Test einen Fehler ergab oder nicht. Aber egal wie komfortabel der Debugger ist, aufwendig ist diese Vorgehensweise in jedem Fall. Im Prinzip muss eine Datenbank mit Eingabe- und Ergebniswerten erstellt werden, wobei die Anzahl, Reihenfolge und vor allem der Typ der Werte zu berücksichtigen ist. Festzulegen ist auch der Zugriff des Debuggers auf die Datenbank, die Ermittlung des Testergebnisses, das Erstellen einer Testauswertung, die Reproduzierung von Tests etc. Dies führt am Ende zu einer eigenen Testumgebung.

Proprietäre Testumgebung
Eine solche Testumgebung ist meist speziell für die zu testende Funktion erstellt und somit wenig flexibel. Das ist nachteilig, wenn sich Anzahl, Reihenfolge oder Typ der Parameter ändern. Oft ist die Anpassung und Erweiterung der Testumgebung für eine Funktion ebenso aufwendig wie das Ändern der Funktion selbst. Auf eine Testumgebung, welche möglichst komfortabel die Wiederholung aller Tests ermöglicht, kann man aber kaum verzichten, denn wird an der Implementierung etwas geändert, muss erneut getestet werden, und zwar strenggenommen alle Funktionen mit allen Testfällen. Diese Wiederholungen werden Regressionstests genannt und sind mit manuellem, interaktiven Testen aus Aufwandsgründen kaum möglich.

Der aktuelle Stand
In der Praxis gibt es firmeninterne, proprietäre Testumgebungen, die für alle angesprochenen Probleme Lösungen vorsehen. Die Güte und Flexibilität dieser Testumgebungen variiert mit dem Aufwand, der für sie aufgebracht wird. Dass bei der Entwicklung von Embedded Software keine standardisierten Lösungen verwendet werden, hat einen einfachen Grund: Erstaunlicherweise gibt es nur sehr wenige kommerziell verfügbare Werkzeuge, deren Funktionalität auf die angesprochenen Probleme zielt.

Abhilfe durch Tessy
Tessy ist ein kommerziell verfügbares Werkzeug zum automatisierten dynamischen Unit-Test von in C geschriebener Software für eingebettete Systeme. Um den Test mit Tessy zu beginnen, wählt man einfach das Software-Modul aus, das die zu testende Unit, in diesem Fall eine C-Funktion, enthält. Tessy analysiert dieses Modul und listet alle C-Funktionen auf, die sich in ihm befinden. Der Anwender wählt aus, welche Funktion getestet werden soll.

Schnittstellenanalyse
Tessy analysiert den Quellcode der zu testenden Funktion und bestimmt, welche Variablen der Funktionsschnittstelle Eingabe und welche Ausgabe (Ergebnis) bzw. beides sind. Anzahl, Typ und Passierrichtung (Input, Output, InOut) der Variablen der Funktionsschnittstelle wird durch den in Tessy enthaltenen Test Interface Editor (TIE) graphisch dargestellt und kann – sofern notwendig - durch den Anwender geändert oder ergänzt werden.


Bild 1: Im Test Interface Editor (TIE) werden Anzahl, Typ und Passierrichtung der Schnittstellenvariablen dargestellt

Tessy erstellt nun automatisch zusätzlichen Quellcode, den sogenannten Testtreiber, der die zu testende Funktion aufruft, sowie gegebenenfalls Platzhalter für Funktionen oder externe Variable, für die es noch keine Implementierung gibt. Dann erzeugt Tessy aus dem Startup-Code für den betreffenden Mikrocontroller, dem Testtreiber, den optionalen Platzhaltern und der zu testenden Funktion die Testapplikation. Dabei wird üblicherweise ein Cross-Compiler für das betreffende Zielsystem eingesetzt.

Testdatenerfassung
Nun werden in Tessy die Eingabewerte und die erwarteten Resultate der Testfälle definiert, wobei der in Tessy integrierte Testdateneditor (TDE) benutzt wird. Der TDE stellt die Schnittstelle der zu testenden Funktion graphisch dar und erlaubt, auch komplexe Schnittstellenelemente wie Strukturen bis auf die elementaren Datentypen aufzublättern. Die Testdateneingabe ist eine wesentliche Aufgabe und wird deshalb vom TDE besonders komfortabel unterstützt. Der TDE dient auch zur Angabe der Soll-Ergebnisse eines Testfalls. Transparent für den Benutzer werden die eingegebenen Werte in einer Datenbank abgelegt.


Bild 2: Mit dem Test Data Editor (TDE) werden die Ein- und Ausgabewerte der Testfälle spezifiziert

Testdurchführung
Zur Testdurchführung lädt Tessy die Testapplikation über einen Debugger in ein Testsystem, etwa einen In-Circuit-Emulator. Der Test bezieht also den realen Mikrocontroller ein und prüft auch den verwendeten Cross-Compiler. Tessy führt alle gewünschten Testfälle der Reihe nach auf dem Testsystem durch, wobei für jeden Testfall geprüft wird, ob das tatsächliche Ergebnis dem erwarteten Ergebnis entspricht. Die Testwerte werden jeweils aus der Datenbank entnommen und sind nicht in der Testapplikation enthalten, die Größe der Testapplikation ist also unabhängig von der Anzahl der Testfälle. Somit ist die Anzahl der Testfälle prinzipiell unbegrenzt und Tessy kann für 8-bit-Mikrocontroller mit begrenztem Speicher eingesetzt werden.

 

Testauswertung
Tessy erstellt Reports unterschiedlichen Detaillierungsgrads über Durchführung und Ergebnisse der Testfälle.


Bild 3: Testauswertung - Testfälle mit unerwartetem Ergebnis sind rot markiert

Fehlersuche im Testobjekt
Hat die Ausführung eines Testfalls mit einem bestimmten Satz von Eingabewerten nicht das erwartete Resultat erbracht, so muss natürlich die Ursache ermittelt werden. Die enge Integration von Tessy mit Debuggern wie HiTOP von Hitex ermöglicht, den betreffenden Testfall durch Tessy wiederholen zu lassen, wobei Tessy einen Haltepunkt am Eintrittspunkt in die zu testende Funktion setzt. Somit führt die Testfallausführung bequem zum Übergang in den Debugger, und zwar an den Beginn der zu testenden Funktion, aufgerufen mit den Daten, die das unerwartete Resultat ergeben. Dies gestattet unmittelbar, mit der Fehlersuche zu beginnen. Ist das Problem gefunden, kann mit dem in Tessy integrierten Editor die Quelle der zu testenden Funktion korrigiert werden und alle Tests lassen sich leicht mit dem geänderten Testobjekt wiederholen.

Regressionstest mit Tessy
Regressionstests sind Wiederholungen von bereits erfolgreich absolvierten Testfällen und dienen dem Nachweis, dass Änderungen und Erweiterungen des Programms nicht zu unbeabsichtigten Auswirkungen führen. Automatische Regressionstest sind besonders nützlich nach Optimierung der Software oder bei Verwendung einer neuen Compilerversion. Tessy enthält eine Batch-Funktion zur Durchführung von umfangreichen Regressionstests ohne Interaktion durch den Benutzer.

Testfälle anpassen
Durch Weiterentwicklung des Anwendungsprogramms kann es vorkommen, dass sich Testfälle nicht mehr ausführen lassen, weil sich die Schnittstelle der zu testenden Funktion geändert hat, etwa durch einen zusätzlichen Parameter. Bei eigenerstellten Testumgebungen ist dann meist hoher Anpassungsaufwand nötig, Tessy jedoch erledigt die Anpassung komfortabel und weitgehend automatisch.

Testdaten weiterverwenden
Die komfortable, möglichst umfangreiche Weiterverwendbarkeit von existierenden Testdaten auch bei geänderter Schnittstelle ist Voraussetzung, dass sich Testfälle aktualisieren lassen und somit jederzeit wiederholbar sind. Testwiederholungen bedeuten Regressionstests, und die wiederum sind ein wesentliches Mittel zur Sicherung von Software-Qualität. Erst mit Regressionstests wird es möglich, Software im Hinblick auf Code-Größe, Performance, Wartbarkeit und Wiederverwendbarkeit zu optimieren, weil Regressionstests sicherstellen, dass die eigentliche Funktionalität unverändert bleibt.

Testabdeckungsanalyse mit Tessy
Die Testabdeckungsanalyse gibt an, in welchem Umfang die durchgeführten Tests die zu testende Software erfasst haben. Wird hier eine bestimmte Prozentzahl nicht erreicht, waren die Tests nicht ausreichend oder es liegt eine sonstige Abnormalität vor, wie etwa "toter Code".

Mit Tessy können die Pfade ermittelt werden, die während der Tests durchlaufen wurden. Tessy setzt die Zahl der durchlaufenen Pfade in Beziehung zur Zahl aller möglichen Pfade, dies ergibt dann die Pfad-Abdeckung (path coverage), auch C1 Coverage genannt. Tessy gibt an, bei welchem Testfall welcher Pfad durchlaufen wurde: Ist die Pfadabdeckung nicht ausreichend, kann man leicht erkennen, welche Pfade nicht getestet wurden.

Testplanung mit CTE
Der Classification Tree Editor CTE ist Bestandteil von Tessy und wird zur Testfallspezifikation anhand der Klassifikationsbaummethode eingesetzt. Die Klassifikationsbaummethode ist ein systematischer Weg zur Ermittlung einer Menge von redundanzarmen, fehlersensitiven Testfällen und führt von der Problemspezifikation zu Testfallspezifikationen. Dabei wird der sogenannte Klassifikationsbaum erstellt.

Die Anwendung der Klassifikationsbaummethode fördert das Nachdenken über Spezifikation und Testfälle. Dabei gewinnt man Klarheit über Fragen wie

Der CTE ist ein syntaxgesteuerter graphischer Editor für die Erstellung des Klassifikationsbaums und der darauf basierenden Ermittlung von Testfallspezifikationen. Der CTE verwaltet Testfallspezifikationen, Testfälle, Testfallanmerkungen etc. und kann diese Information auch anderen Werkzeugen, natürlich in erster Linie Tessy, zur Verfügung stellen.


Bild 4: Der Klassifikationsbaumeditor dient zum Zeichnen des Klassifikationsbaums und zur Testfallspezifikation

Fazit
Tessy erleichtert also wesentlich das Testen von Programmen und ersetzt weitestgehend proprietäre Testumgebungen. Zu Testbeginn erzeugt Tessy noch fehlende Komponenten wie Testtreiber oder Platzhalterfunktionen. Durch die Testdatenverwaltung mit Tessy bleiben alle Testdaten für spätere Tests erhalten. Die Integration von Tessy mit Debuggern erlaubt effiziente Fehlersuche bei unerwarteten Ausgabewerten. Bei der Weiterentwicklung des Programms werden mit Tessy auch die Tests weiterentwickelt und angepasst. Somit ist Tessy besonders für Regressionstest geeignet.

Die Testfallplanung zu Beginn der Entwicklung korrespondiert mit der Testabdeckungsanalyse beim Abschluss der Tests.

Tessy und CTE sind bei Hitex erhältlich.

Der Autor
Frank Büchner hat an der Universität Karlsruhe (TU) Informatik studiert. Seit Abschluss seines Studiums ist er nun über ein Dutzend Jahre im Bereich der eingebetteten Systeme tätig. Er ist bei Hitex Development Tools, Karlsruhe, als Product Manager für Software beschäftigt.