Fehlerkorrektur beim Kunden kommt zu spät

"Qualitätssicherung ist wichtiger als Termintreue

01.03.1991

"Gute Programmierer brauchen keine Qualitätssicherung" - ein verbreitetes Vorurteil, mit dem Wolfgang Huber* aufräumen will. Das Testen von Programmen sei ein Hauptproblem der Softwareentwicklung und dürfe nicht als das schwächste Glied erst am Schluß der Entwicklungskette stehen. Probleme entstehen laut Huber bereits in den frühen Entwicklungsstadien: in Pflichtenheft und Entwurf.

Im heutigen Software-Entwicklungszyklus nimmt die Lebensdauer einzelner Releases unter dem zunehmendem Konkurrenzdruck ständig ab. Will ein Softwarehersteller trotzdem langfristig erfolgreich sein, so muß er einer zielgerichteten Qualitätssicherung erste Priorität einräumen. Diese Notwendigkeit wird in der Literatur durch folgendes Zitat untermauert: "The bitterness of poor quality lingers long after the sweetness of meeting schedules" (C. Weagle). Zu deutsch: "Die Erbitterung über schlechte Qualität bleibt noch lange, nachdem die Befriedigung über das Einhalten von Terminen verklungen ist."

Aufgrund mangelnder Sachkenntnis wird der Aufwand für Einführung und Durchführung von Maßnahmen zur Qualitätssicherung oft überschätzt. Da es sich aus Sicht vieler Entwickler um eine Disziplin handelt, die man im Idealfall gar nicht nötig hat, wird sie gerne als unrentabel abgestempelt. In der Praxis zeigt sich jedoch, daß Qualitätssicherung um so rentabler ist, je früher sie ansetzt.

"Laut einer Statistik der amerikanischen Firmen IBM, TRW und GTE kostet es mindestens fünfmal soviel, einen Code-Fehler nach der Integration eines Softwaresystems zu beheben, als bei der Codierung" (Harry Sneed). Dieses Verhältnis verschlechtert sich exponentiell, wenn man Fehler im Entwurf oder bereits in der Spezifikation betrachtet. Am teuersten wird die Sache dann, wenn Fehler erst beim Kunden entdeckt werden. Dies ist ein deutliches Zeichen dafür, daß im Entwicklungsprozeß zu wenig getestet wurde.

Verschiedene Erfahrungsberichte in der Literatur zeigen, daß die Fehler zu etwa je einem Drittel auf Spezifikation, Entwurf und Codierung entfallen. Trotzdem sind bei einigen Softwareherstellern Tests lediglich zur Abnahme eines fertigen Produkts üblich. Solche Tests kommen auf jeden Fall zu spät. Oberstes Ziel der Qualitätssicherung muß die Früherkennung von Fehlern sein, damit unnötige Kosten vermieden werden können. Dabei gilt das "Prinzip einer sinnvollen Prüfplanung für alle Phasen des Phasenmodells" wie es von der Deutschen Gesellschaft für Qualität e.V. und der Nachrichtentechnischen Gesellschaft im VDE empfohlen wird.

Wie sieht ein praxisgerechtes "Test-Drehbuch" aus? Grundsätzlich sind zwei Fälle zu unterscheiden: der Modul- oder Programmtest und der System-, Integrations- oder Abnahmetest (sogenanntes "High-Order-Testing").

Beim Programmtest wird darüber hinaus zwischen statischer (das Programm wird lediglich "auf dem Papier" betrachtet) und dynamischer Analyse (das Programm wird zur Laufzeit, betrachtet) unterschieden. Hier soll nur die dynamische Programmanalyse im Mittelpunkt Ziehen, Methoden und Werkzeuge für die statische Analyse sind aus der Literatur hinreichend bekannt (siehe Sneed, Endres, Myers).

Der Modul- und Programmtest wird in der Regel vom Entwickler selbst als "White-Box-Test" durchgeführt. Das High-Order-Testing dagegen erfolgt durch eine unabhängige Stelle, die am Entwicklungsprozeß nicht direkt beteiligt ist. Beim Abnahmetest sollte dies der Auftraggeber sein, der bei Standardsoftware in der Regel in der Herstellerfirma selbst angesiedelt ist (Systemanalyse oder Marketing). Das High-Order-Testing wird meistens als "Black-Box-Test" durchgeführt.

Beim White-Box-Test gilt ein bekanntes Gesetz, das jeder SW-Entwickler in seiner Ausbildung mindestens einmal gelernt haben sollte: Jeder Ablaufzweig eines Moduls muß in jeder erdenklichen Kombination und

mit möglichen Grenzwerten (gültig und ungültig) mindestens einmal durchlaufen werden. Eine grundsätzliche Eigenschaft eines White-Box-Test ist, daß der jeweilige Testplaner ganz genau weiß, wie das Programm intern gestaltet ist und deshalb auch entscheiden kann, ob beim Test alle Zweige durchlaufen werden.

Obwohl die Anzahl möglicher Eingabewerte in der Regel extrem hoch ist, kann beim White-Box-Test schon mit wenigen Werten eine zuverlässige Aussage über die Fehlerfreiheit gemacht werden, da es immer Klassen von Eingabewerten gibt (Äquivalenzklassen), innerhalb derer sich ein Modul stets gleich verhält. Auf diese Weise wird hauptsächlich die Programmlogik geprüft, wobei - gemessen am Entwurf - ein vollständiger Programmtest möglich ist.

Damit kann aber noch lange nicht sichergestellt werden, daß ein Modul Ablaufzweige für jeden in der Praxis vorkommenden Fall aufweist. Die absolute Fehlerfreiheit eines Programms läßt sich nicht garantieren.

In der Praxis wird beim Modultest häufig der Entwurf mißachtet, obwohl er die Determinante für die Testplanung ist. Der Entwickler ist zum Zeitpunkt der Codierung in der Regel derart mit der Materie vertraut, daß er dazu neigt, "aus dem Kopf" zu codieren. Beim Modultest wird dann mit dem Ziel getestet, die Fehlerfreiheit des Endprodukts zu zeigen.

Als Entwickler ist man natürlich von der Korrektheit des Programms überzeugt - ein Grund dafür, daß niemals destruktiv getestet wird. Ziel des Testens muß jedoch sein, Fehler zu finden, und zwar in diesem Fall solche, die am Entwurf zu messen sind. Programme, die unter Vernachlässigung des Entwurfs getestet werden, funktionieren immer, denn sonst hätte der Entwickler sie nicht so gestaltet, wie sie sind.

Ein weiterer Fehler bei der Testplanung ist die ausschließliche Verwendung gültiger Eingabewerte. Wer seine Programme nur mit gültigen Werten testet, erhält fehlerfreie Programme, die bei zulässigen Eingaben keine falschen Resultate liefern. Erstrebenswert sind aber fehlertolerante Programme, die auch bei Falscheingaben oder unzulässigen Betriebsbedingungen wie Gerätefehlern ihren Leistungsumfang ganz oder teilweise aufrechterhalten.

Bei Tests mit ungültigen Eingaben wird man sehr häufig feststellen, daß zu wenig "Intelligenz" in die Fehlerbehandlung gesteckt wurde. Der Testplan sollte also auf jeden Fall einige bewußte Falscheingaben vorsehen.

Reihe von Hilfsmitteln

Für die Testplanung gibt es eine Reihe von Hilfsmitteln, die beim strukturierten Entwurf üblich sind:

1. Nassi-Shneiderman-Diagramme: Struktogramme, die den Programmablauf grafisch verdeutlichen. Mit diesem Hilfsmittel können leicht Klassen von Testfällen gebildet werden, indem die Möglichen Ablaufzweige in Form verschiedener Graphen eingezeichnet werden (Vergleiche Abbildung ).

2. IPO-Diagramme ("Input-Process-Output"- Tabellen): Hierarchie- oder Flußdiagramme, die Eingabe- und Ausgabewerte über die dazwischenliegende Verarbeitung einander zuordnen. Dabei werden nicht nur Übergabewerte berücksichtigt, sondern auch globale und lokale Variablen einschließlich deren Initialisierung (Vergleiche Abbildung 2 auf Seite 16).

3. Ein Pseudo-Code zur Verdeutlichung der Programmlogik für einzelne Ablaufzweige auf einer rein verbalen Ebene. Das folgende Beispiel zeigt Pseudo-Code für das oben genannte Modul:

MODUL gerade_ungerade (Eingabewert: a ganzzahlig)

IF a gültig THEN

IF a gerade THEN

setze x auf 1

ELSE

setze x auf 0

ENDIF

ELSE

setze x auf -1

ENDIF

RÜCKGABE (Rückgabewert: x ganzzahlig)

4. Zustandsgraphen (Petri-Netze): Sie verdeutlichen die Abläufe bei parallelen Prozessen.

Im Gegensatz zu Nassi-Shneiderman-Diagrammen sind diese nicht strukturiert, da bei parallelen Prozessen der (nicht strukturierbare) Zufall eine Rolle spielt (Siehe Gewald/Haake/ Pfladler).

Klassisches Beispiel für Zustandsgraphen ist das Zustandsdiagramm für interaktive Prozesse in einem Multitasking-System (Siehe Abbildung 3 auf Seite 16).

Hier wird deutlich, daß der Aufwand für die Erstellung eines Testplans beim Modultest um so geringer ist "je höher die Qualität der Spezifikation und des Entwurfs ist.

Beim Black-Box-Test sieht der Testbeauftragte mir die Eingaben und Ausgaben eines Programms. Er weiß nichts über interne Abläufe und Strukturen. Getestet wird hier ganz konkret auf der Ebene der Produktspezifikation. Die Testdaten werden alleine aus der Spezifikation abgeleitet.

Durch den Test soll gezeigt werden, ob ein DV-System die geforderten Aufgaben korrekt erfüllt oder nicht.

Ein Test, dessen Ziel darin liegt, alle Fehler in einem DV-System zu finden, muß konsequenterweise Testfälle für alle möglichen Eingaben und Eingabekombinationen enthalten, da der Test-Mitarbeiter hier keine zuverlässigen Angaben über Klassen von Eingabewerten machen kann. Er kennt nämlich die Programmlogik nicht! Zudem kann der Testbeauftragte nur aus der Anwendungssicht heraus beurteilen, welche Werte gültig oder ungültig sind.

Dadurch werden niemals alle Statements in einem Programm abgedeckt, womit auch keine völlige Fehlerfreiheit garantiert werden kann. Das einzige Ziel, das zu erreichen ist, heißt, mit möglichst wenig Testfällen viele Fehler zu finden.

Für die Testplanung gibt es hier eine Reihe von Vorgaben, die als Bestandteil von Pflichtenheften üblich sind:

1. Zweckbestimmung: Welches Ziel verfolgt das Programm, welche Probleme werden damit gelöst, welchen Nutzen bringt das Programm

2. Leistungsbeschreibung: Welche Daten oder Klassen von Daten werden in welchem Zustand verarbeitet, welche Funktionen stehen aus Anwender nicht zur Verfügung, wie sieht die Benutzer-Oberfläche aus (Datenträger, Masken, Felder, Tastaturfunktionen, Fehlermeldungen)?

3. Beschreibung der Umgebungsbedingungen: Annahmen über die Hardware und Software, mit der das Programm arbeitet, mögliche Konfigurationen und Störfaktoren.

4. Beschreibung der Eigenschaften: Performance und Zuverlässigkeit, Fehlertoleranz.

5. Definition der Abnahmebedingungen: Eingangs- und Ausgangskriterien für den Abnahmetest.

Die Produktspezifikation sollte in jedem Fall so detailliert sein, daß sie als Testplan beim High-Order-Testing verwendet werden kann.

Der einzige Weg zu einer fehlerfreien, qualitativ hochwertigen Software besteht in ausführlichen Tests. Bevor man jedoch damit beginnt, sollte ein Testplan-Review durchgeführt werden. Nicht jeder Fehler muß ein Programmfehler sein, auch der Testplan kann Fehler enthalten. Zeit und Kosten können durch den gezielten Einsatz von Testwerkzeugen reduziert werden.

Im Bereich der Codierung und des Modultests spielen Editoren, Masken- und Datenbankgeneratoren, Syntax-Checker, Compiler und Debugger eine wesentliche Rolle. Für den komplexen Bereich des High-Order-Testing lohnt sich eine Qualitätssicherung nur dann, wenn sie computergestützt mit Werkzeugen, wie einem Terminal-Simulator, einem Umgebungsrahmen-Generator, einem Performance-Analysator und einem Testergebnis-Validator durchgeführt wird.

Ein Terminal-Simulator erlaubt die Aufzeichnung und Wiedergabe von Tastenfolgen ("automatischer Benutzer"). Dadurch werden auch Fehler, die rein "zufällig" durch Falscheingaben provoziert wurden, reproduzierbar. Voraussetzung für die Vergleichbarkeit von Tests ist eine einheitliche Testumgebung, das heißt, es müssen vor Testbeginn stets die gleichen Dateien und Dateiverzeichnisse vorhanden sein. Dafür kann der Umgebungsrahmen-Generator sorgen.

Mit dem Performance-Analysator sind Zeitmessungen möglich, die Aussagen über eine mögliche Optimierung einzelner Programmteile erlauben. Der Testergebnis-Validator schließlich läßt eine Beurteilung des Testerfolges zu, indem Soll-Werte automatisch mit den Ist-Werten verglichen werden.

"Ein kurzfristiger Rationalisierungseffekt wird sich durch Anwendung von Testwerkzeugen in der Regel nicht nachweisen lassen, da die Testarbeit gründlicher geplant und vorbereitet und der Umgang mit den

Tools meist erst erlernt werden muß. Längerfristig zahlen sich die damit verbundenen Mühen und Investitionskosten jedoch durch bessere Ergebnisse aufgrund einer höheren Testqualität aus" (Schmied/Winkler).

Der Einsatz solcher Werkzeuge hilft vermeiden, daß Testfälle nur einmal verwendet werden, obwohl sie für die weitere Entwicklung wieder berücksichtigt werden müßten. In vielen Fällen entstehen neue Testfälle nämlich spontan während der Testdurchführung. Solche Tests sind nur bei konsequenter Aufzeichnung wiederverwendbar.

Aufbau einer Textbibliothek möglich

Wer Testwerkzeuge einsetzt, sollte sich darüber im klaren sein, daß die klassische, intuitive Testdurchführung nicht sehr sinnvoll ist. Ideal ist die Zergliederung der Erfassungsfolgen in mehrere eigenständige Testfälle. Auf diese Weise kann eine Testbibliothek aufgebaut werden, deren Wert bei ständiger Pflege von Release zu Release wächst.

Grundsätzlich sollten aufgetretene Fehler kein Anlaß für einen Abbruch des Tests sein. Ein Abbruch ist nur dann sinnvoll, wenn extrem viele Fehler auftauchen, die den Entwurf oder die Codierung vollständig in Frage stellen. Nach der Fehlerkorrektur muß ein Regressionstest durchgeführt werden, bei dem sichergestellt wird, daß die Korrektur keine Nebeneffekte in anderen Programmteilen zur Folge hat. Wenn alle Testfälle aufgezeichnet wurden, kann für einen vollständigen Regressionstest garantiert werden.

Grundlage für den Testplan sind Spezifikation und Entwurf. Der Testplan definiert einzelne Testfälle unter Bezugnahme auf Spezifikation und Entwurf. Dabei beschreibt er nur, was in welchem Zeitrahmen zu tun ist und welche Eingaben oder Klassen von Eingaben zu verwenden sind. Das Verhalten des Programms ist durch die Spezifikation vorgegeben. Der Testplan nennt außerdem die Namen derjenigen Mitarbeiter, die den Test planen, durchfuhren und aufgetretene Fehler bereinigen.

In diesem Sinne ist der Testplan eine konkrete Arbeitsanweisung für den Testbeauftragten. Angaben über Resultate, Fehlermeldungen oder sonstige Reaktionen, die vom Programm erwartet werden, werden im Testplan nur dann gemacht, wenn die Spezifikation an dieser Stelle unvollständig ist. Der Testplan ist die destruktive Erweiterung der Spezifikation, denn beim Testen wird erwartet, daß Fehler gefunden werden.

Alle Testfälle müssen vom Testenden anhand einer Checkliste abgehakt und eventuell kommentiert beziehungsweise bewertet werden. Der Erfolg eines Tests ist daran zu messen, wieviele Fehler gefunden wurden. Unnötige Kosten für die Qualitätssicherung entstehen also nur dort, wo Programme unzureichend spezifiziert sind und womöglich intuitiv entwickelt werden. Wenn Spezifikation und Entwurf bereits fehlen oder unvollständig sind, bleibt die Frage nach dem Testplan unbeantwortet: Was soll eigentlich getestet werden?

Literatur: Boehm, B. W. et al: "Some experience with automated aids to the design of large-scale reliable software", Proceedings Int. Conf. on Reliable Software, Los Angeles, 1975

Deutsche Gesellschaft für Qualität e. V. und nachrichtentechnische Gesellschaft im VDE (Hrsg.): ,Software-Qualitätssicherung - Aufgaben, Möglichkeiten, Lösungen", Verlag Beuth, 1. Auflage, Berlin, 1986

Endres, Albert: "Analyse und Verifikation von Programmen. Systematische Verfahren und Untersuchungen zur Erstellung fehlerfreier Software" Verlag R. Oldenbourg. 1. Auflage, München, 1977

Gewald, Klaus, Gisela Haake und Werner Pfladler: "Software Engineering Grundlagen und Technik rationeller Programmentwicklung", 4. verbesserte Auflage, Verlag R. Oldenbourg, München. 1985

Hughes, Joan K. und Jay I. Michtom: "Strukturierte Software-Herstellung Anleitung für Programmierer und Manager, Verlag R. Oldenbourg, München, 1980

Myers, Glenford J.: "Methodisches Testen von Programmen Verlag R. Oldenbourg, 3. Auflage, München, 1989 Schmied. Walter-Stefan und Hermann Winkler: Software-Qualität - Ausgewählte Methoden und Werkzeuge der Softwareprüfung", Siemens AG, München-Perlach, 1990

Sneed, Harry M.: "Software-Qualitätssicherung für, kommerzielle Anwendungssysteme", Verlagsgesellschaft Rudolf Müller, Köln-Braunsfeld, 1983

Taylorix AG(Hrsg.): Taylorix Toptest - Werkzeug für automatisierte Qualitätssicherung - Benutzerhandbuch", 1. Auflage, Stuttgart, 1990

Weagle, C.: "Visit to a programming Center", THINK, Oktober/November, 1974, Seite 31 (Copyright 1974 by International Business Machines Corporation)