"Testen ist eine Art der pragmatischen Verifikation, die für alle Programmierer verbindlich zu sein hat"

Wie das Vertrauen in Programme erhöht werden kann

16.09.1983

Axel Stöhr ist Mitarbeiter des Rheinnisch- Westfälischen TÜVs in Essen.

Der Software- Entwicklungsprozeß verläuft in vier Phasen. Diesen werden Prüfungsverfahren zugeordnet. Dabei wird beschrieben, was und wie geprüft wird. Diese Verfahren können schon im Entwicklungsprozeß als konstruktive Komponenten einer Qualitätssicherung betrachtet werden. Eine Eignungsprüfung von Software muß feststellen, in welchem Maße diese Verfahren angewendet wurden und bei Bedarf einzelne Verfahren erneuert oder zusätzlich durchzuführen sind. Ziel ist es, die Software einer Qualitätskontrolle zu unterwerfen und damit bei der Produktion von Software den gleichen Stand der Technik zu erreichen wie in den übrigen technischen Produktionsbereichen.

Durch das Vordringen von frei programmierbaren Steuerungen in der Prozeßautomatisierung wird die Software solcher Systeme als mögliche Versagenskomponente eines technischen Gesamtsystems gesehen. Daher richtet sich das Augenmerk auf die Software. Es gilt, Software als ein technisches Produkt anzusehen und besonderen Qualitätskontrollen zuzuführen. Hierzu wollen wir uns im folgenden auf kleinere Programme beschränken, implementiert auf kleinen Rechneranlagen, etwa im Bereich der Mikroprozessoranwendungen. Diese Programme werden in aller Regel von einem einzigen Programmierer erstellt. Damit ist der Programmierer im Sinne der technischen Produktion eine vollständige Softwarefabrik: Er nimmt Kundenwünsche auf, setzt sie um in einen Programmentwurf, programmiert, implementiert und führt eine eigene Qualitätskontrolle durch. Dadurch wächst die Gefahr eines Fehlverhaltens des Programmes. Welche Maßnahmen können nun ergriffen werden, die Qualität von Software kontrollierbar und damit prüfbar zu machen?

Die Antwort auf diese Frage heißt: Den Entwicklungsprozeß von Software in Klassen ähnlicher Tätigkeiten aufzuteilen, diese Tätigkeiten soweit wie möglich zu systematisieren und zu dokumentieren und die Tätigkeiten einer der Systematik entsprechenden Prüfung zu unterziehen. Eine allgemein anerkannte Gliederung findet sich im Bild 1.

Schon in diesen vier Phasen der Softwareentwicklung müssen vom Programmierer konstruktive Maßnahmen zur Steigerung der Qualität der Software ergriffen werden. Der Prüfer der Software hat die Maßnahmen zu kontrollieren und im Bedarfsfall, eigene analytische Qualitätskontrollen durchzuführen. Im folgenden werden wir auf die Tätigkeiten des Prüfers weiter eingehen.

Wie eben schon erwähnt, hat die Software ja im wesentlichen vier Phasen der Entwicklung. Die im weiteren Verlauf aufgeführten Prüfungen innerhalb der Phasen und zwischen den Phasen können und sollen durch den Softwareentwickler durchgeführt und dokumentiert werden. Fehlende Dokumente können durch nichts ersetzt werden und müssen bei einer Qualitätskontrolle entweder nachgefordert oder selbst erstellt werden.

Der genannte Prüfprozeß innerhalb der vier Phasen und an deren Schnittstellen heißt Validierung und ist im Bild 2 dargestellt.

Zu jeder dieser vier Validierungsphasen muß in der Dokumentation festgehalten werden,

- wie die Korrektheit und die Konsistenz der Strukturen, Daten und Funktionen geprüft wurden,

- welche Testdaten und Testabläufe festgelegt wurden.

Diese Dokumente vereinfachen eine Softwareprüfung und reduzieren die Anzahl der Fehler in jedem Entwicklungsschritt.

Die Absicht eines Prüfers kann es nur sein, seine Tätigkeit so korrekt wie möglich durchzuführen. Somit ist das sicherste Verfahren der Feststellung der Richtigkeit eines Programms der mathematische Beweis. Diese Art des Beweisens wird auch formale Verifikation genannt. In den letzten Jahren wurden große Fortschritte im Bereich dieser Techniken gemacht, die auf formaler Semantik und mathematischer Beweistechnik beruhen. Dieses setzt jedoch formale Entwürfe, qualifizierte Fachleute und automatische Werkzeuge voraus. All das ist zur Zeit bei den Softwareproduzenten kaum verfügbar- und für einzelne Teilgebiete nur mit hohen Kosten zu realisieren. Daher wendet man sich mehr der Programmablaufanalyse zu. Dabei wird die Software aktiviert mit ausgewählten Daten und nach Bedarf der interne Ablauf und die erzielten Ergebnisse analysiert.

Dieses Verfahren heißt Testen. Testen ist eine Art der pragmatischen Verifikation, die für alle Programmierer verbindlich zu sein hat. Wird auf der Basis des Pflichtenheftes getestet, das heißt ohne Kenntnis des Entwurfs und der Konstruktion, so heißt dies "Black- Box"- Testen. Die Techniken sind hierbei im Hinblick auf ihre Güte schlecht meßbar und bestehen aus:

- Intuition,

- manueller Nachrechnung,

- Vergleich mit alternativen Programmen,

- manueller oder automatischer Simulation.

Anforderungen

Will man mehr in die Richtung der formalen Verifikation gehen, dann muß die Dokumentation des Entwurfs und der Konstruktion mit in das Testen einbezogen werden und die Fehlerfreiheit des Programms für jedes spezifizierte Datenelement nachgewiesen werden. In der Regel ist dies ein unlösbares Problem. Daher wird man auf die Fehlerfreiheit verzichten müssen und mittels des sogenannten "White- Box "- Testes eine Maximierung des Vertrauens in das Programm zu erreichen versuchen. Welche Kriterien müssen solche Testdaten erfüllen?

- Es müssen die wichtigsten oder auch alle Funktionen des Programms mindestens einmal ausgelöst werden (Black- Box).

- Es müssen alle Einzelbefehle eines Programmes mindestens einmal angesprochen werden (White- Box.)

- Alle "relevanten" Pfade müssen mindestens einmal durchlaufen werden (White- Box).

Entsprechend der Reihenfolge der Regeln vergrößert sich der Testaufwand und das Vertrauen in das Programm. Der Prüfer muß anhand der Testdokumentation die Tests nachvollziehen und sie gegebenenfalls wiederholen oder ergänzen können.

Allgemein bekannt, aber trotzdem immer wiederholenswert ist die Tatsache, daß sich eine sorgfältige und exakte Analyse des Programms gleich bei Beginn der Programmentwicklung auszahlt. Die Beseitigung von Fehlern aus der Anfangsphase nach Inbetriebnahme des Programmes kostet- wie im Bild 3 dargestellt- etwa das 50- bis 100fache eines Fehlers aus der Konstruktionsphase.

Bild 4 enthält einen Überblick der notwendigen Dokumente in dieser Phase. Der Programmierer muß entsprechend Punkt 5, Bild 4 aus Dokument 1 bis 4 einen groben Testplan herleiten und Dokumentieren; innerhalb der Eingabedatenmenge können Klassen von Daten gebildet werden, die von dem Programm gleichbehandelt werden. Weiterhin können Randwerte innerhalb der Klassen festgelegt werden. Gleiches gilt für die Ausgabedaten. Damit kann bei einem Funktionstest festgestellt werden, ob die zulässigen Eingaben der vorhergesagten Ausgaben treffen. Diese Dokumente stellen sicher, daß die Anforderungen testbar sind. Nicht testbare Anforderungen sind keine sinnvollen Anforderungen und führen zu einem fehlerhaften Programm. Die Testmengen festzulegen, ist aber nur ein Teil der Verifikation in der Anforderungsphase. Eine Analyse der Widerspruchsfreiheit und Vollständigkeit der Anforderungen sollte auch durchgeführt werden. Hier helfen die Inspektoren( Walk through). Diese bestehen im wesentlichen aus Einschaltung problemfremder Kollegen, denen anhand der vorgelegten Anforderungen das Projekt erläutert wird. In der Literatur gibt es ausführliche Beschreibungen dieser Inspektionen. Wichtig ist nur, daß auch diese Aktivitäten dokumentiert werden.

Entwurf

Auch für den Entwurf gilt ähnliches wie für die Anforderung. Hier soll der Programmierer klar und deutlich dokumentieren, wie das Programm die Anforderung bewältigen wird. Dazu gibt es verschiedene Entwurfstechniken. Unabhängig davon, welche Technik benutzt wurde, müssen die im Bild 5 angegebenen Dokumente vorhanden sein. Aus diesen Unterlagen kann folgendes verifiziert werden:

- Der Entwurf kann an der Anforderung geprüft werden. Alle Funktionen und Daten der Anforderung müssen in dem Entwurf vorhanden sein. Durch Schreibtischsimulation kann geprüft werden, ob de Testeingabedaten die Ausgabedatenmenge treffen. Dieses dient dem Nachweis von Vollständigkeit und Konsistenz.

- Die Funktionen, Algorithmen und Module können mit Handrechnung oder Schreibtischüberlegung auf Richtigkeit geprüft werden. Die Schnittstellen der Module können auf Richtigkeit des Datentransfers in bezug auf die Form, das Format und die externen Einheiten geprüft werden.

- Die Testdaten können danach geprüft werden, ob externe Werte oder besondere Ausnahmen enthalten sind. Sind Beispielsweise Felder mit variabler Länge vereinbart, so sollte das Feld mit minimaler und maximaler Anzahl von Elementen in den Testdaten vorhanden sein.

Aus diesen Punkten ist ersichtlich, daß der Weg von der Anforderungsphase zu dem Programm nicht direkt führen darf. Eine ausreichende und sorgfältige Planung und Entwicklung in den ersten beiden Phasen kostet Zeit, aber verbessert am Ende die Qualität des Programms erheblich. Andererseits zahlt sich diese Investition auch aus, da Fehler im Programm, die in diesen Phasen entstehen, nur mit großen Kosten später beseitigt werden können.

Hinzu kommt, daß nicht nur an die Kosten der Fehlerbeseitigung, sondern auch an die Folgekosten oder die Regreßansprüche bei fehlerhafter Funktion des Programms gedacht werden muß.

Die Konstruktions- oder Kodierphase ist das, an was die meisten Leute denken, wenn sie vom Programmieren sprechen. Leider gehören zur Zeit auch noch die meisten Programmierer dazu. Wie wir jedoch bei der Beschreibung der vorangegangenen Phase gesehen haben, muß, mehr oder weniger rein mechanisch, das Quellenprogramm mit guten Programmiersprachkenntnissen aus dem Entwurf erzeugt werden. Der größte Teil wurde in der Architektur und der Statik getan; in der Konstruktion kommt das Handwerkszeug zu Wort. Die Dokumente der Konstruktionsphase sind dem Bild 6 zu entnehmen.

Diese Dokumente müssen nachgeprüft und gegebenenfalls vervollständigt werden. Gewisse Teile können inzwischen schon mit automatischen Hilfsmitteln erzeugt werden. Der nicht automatisierte Teil verlangt jedoch ebenso viel Kreativität wie die Entwurfsphase. Zum Schluß muß jedoch betont werden, daß sich der Umfang des Prüfens und Testens nach Folgen und auch Folgekosten eines Fehlers richten muß.

Betrieb und Wartung

Betrachtet man die Kostenverteilung von Software über die gesamte Entwicklungsphase, so liegen nach den neuesten Zahlen rund 70 Prozent der Kosten in der Wartung. Warum wird dann so viel über Anforderung, Entwurf und Konstruktion

gesprochen? Die Antwort liegt auf der Hand: In kaum einem Bereich der Technik könnte ein solch wartungsintensives Produkt verkauft werden. Somit müssen alle Anstrengungen unternommen werden, den Aufwand der Wartung zu verkleinern, um damit die Kosten zu senken.

Grundsätzlich müssen Wartungen und damit Änderungen eines Programms auf Konsequenzen in den übrigen Phasen untersucht und entsprechend dokumentiert sein.

In den vorangegangenen Beschreibungen wurde ein Konzept vorgestellt, wie ein geprüftes und prüfbares Programm entwickelt und dokumentiert werden muß. Dabei sind die Aspekte von großen Programmsystemen nicht berücksichtigt, sondern mehr Wert auf den Fall gelegt worden, bei dem der Programmierer verantwortlich für alle Phasen ist. Es sollte klar werden, daß der Programmierer außer der Aufgabe, ein Produkt zu erzeugen, auch noch den Nachweis der Zuverlässigkeit des Produktes führen muß. Dies beginnt schon in der frühesten Phase und muß einen zwischenzeitlichen Abschluß bei der Inbetriebnahme des Programms haben. Dieses sollte auch im übrigen bei der Beauftragung eines Programmierers Vertragsbestandteil sein, um gegenseitige Regreßansprüche bei Versagen oder Wartung geltend machen zu können. Diese Vorgehensweise macht ein Programm nachvollziehbar und dient Auftraggeber, Auftragnehmer und nicht zuletzt der Qualität des Produkts. Dies ist nicht eine Glaubensfrage, sondern entspricht dem derzeitigen Stand der Technik in allen anderen Produktionsbereichen.

Will man von Software- Engineering sprechen, so muß man sich diesem Stand anpassen.