Die Auswirkungen von Softwarefehlern machen es notwendig an Software hohe Qualitätsansprüche zu stellen. Um den Qualitätsansprüchen gerecht zu werden, muss das Testen ein integraler Bestandteil der Softwareentwicklung sein.

Jedoch wird der Begriff „Testen“ oft falsch interpretiert, Sätze wie:

  • Testen ist der Prozess, der zeigen soll, dass keine Fehler existieren.
  • Testen soll zeigen, dass ein Programm korrekt arbeitet.

[Myers95] definiert das Testen vielleicht noch besser:

„Testen ist der Prozess, ein Programm mit der Absicht auszuführen, Fehler zu finden.“

Testen soll als zielgerichtete Tätigkeit zum Auffinden von Fehlern verstanden werden. Das Testen kann bis zu 50% der Projektzeit beanspruchen. Bei der Komplexität heutiger Systeme sogar manchmal auch mehr. Der Erfolg des Testens ist aber nicht nur aufgrund der psychologischen und menschlichen Faktoren oft nicht sichergestellt.
Zusätzlich ist zu beachten, dass selbst für sehr einfache Programme fast unendlich viele Testfälle existieren können, die in der Regel nur zu einem kleinen Teil durchgetestet werden können [Myers95]. Es bleibt also nur die Hoffnung, durch die vorhandenen Testfälle alle relevanten Fehler aufgefangen zu haben. Im nächsten Abschnitt werden einige Test-Prinzipien vorgestellt, die die Erfolgsquote des Testens verbessern.


Test-Prinzipien

  • Die Tests dienen zur Feststellung, ob ein Programm wie in der Spezifikation
    festgehalten funktioniert und nichts anderes tut.
  • Dokumentation der Testdurchführung: Eingangsdaten, erwartete Ergebnisse
    und die erhaltenen Daten müssen festgehalten werden.
  • Tests müssen reproduzierbar sein. Bei gleichen Eingangsdaten muss der Test
    auf die gleichen Ausgangsdaten kommen.
  • Ein Test muss geplant werden.
  • Da das Testen eine destruktive Aufgabe hat, sollten oder müssen Tester und
    Programmierer unterschiedliche Personen sein. Ein Programmierer, der sein
    eigenes Programm testet, findet prinzipiell weniger Fehler, da er versucht zu
    zeigen, dass sein Programm keine Fehler enthält. Fehler, die durch falsch verstandene
    Anforderungen entstehen, können nur durch außenstehende Personen
    entdeckt werden.
  • Fehler treten oft gehäuft auf. Daher sind Fehler vermehrt in Code-Abschnitten
    zu suchen, in denen schon viele Fehler aufgetreten sind.

Nach [Myers95] hat ein Testfall folgende Kriterien zu erfüllen:

  • Ein guter Testfall ist dadurch gekennzeichnet, dass er mit hoher Wahrscheinlichkeit
    einen bisher unbekannten Fehler zu entdecken imstande ist.
  • Ein erfolgreicher Testfall ist dadurch gekennzeichnet, dass er einen bisher unbekannten Fehler entdeckt.

Prüf- und Testmethoden

Es gibt verschiedene Möglichkeiten, die Zuverlässigkeit und Qualität von Programmen zu erhöhen. In Abbildung 1 sind diese Möglichkeiten in einer Übersicht dargestellt.

Die Prüfmethoden sind in zwei große Blöcke zu unterteilen:

Prüfmethoden
Abbildung 1: Klassifikation der Tests bzgl. der Prüfmethode nach [Liggesmeyer02]

Statische Prüfmethoden

Die statischen Prüfmethoden dienen zur Verifikation der Software. Verifikation bedeutet in diesem Zusammenhang die Überprüfung der Software auf Übereinstimmung mit der Spezifikation. Diese Methoden lassen sich nicht oder nur sehr schwer automatisieren. Zu diesen Verfahren zählt die Überprüfung der Software auf bestimmte Qualitätsmerkmale, wie die Aussagekraft von Methodenbezeichnern und Kommentaren. Die Analyse des Quellcodes findet ohne Ausführung der Software statt.

In sequentiellen Prozessmodellen findet die Testphase erst am Ende der Entwicklung statt. Aus diesem Grund wurden die statischen Prüfmethoden eingeführt, um schon früh kritische Fehler in der Software zu finden. Beispiele für statische Prüfmethoden sind die Fagan Inspektion und der Walkthrough, bei denen einige Testfälle erstellt werden und der Quellcode manuell nach Fehlern durchsucht wird. Dabei werden überwiegend Entwurfsfehler gefunden.

Dynamische Prüfmethoden

Im Vergleich zu den statischen Prüfmethoden werden die dynamischen zur Validierung der Software eingesetzt. Bei diesen Verfahren wird die Eignung der Software bezogen auf den Einsatzzweck untersucht. Wenn von Testen gesprochen wird, sind damit meistens die dynamischen Prüfmethoden gemeint, bei denen die Software zur Ausführung kommt.

Die dynamischen Verfahren besitzen eine weitere Unterteilung bzgl. der Prüftechnik:

  • Strukturorientiertes Testen bestimmt die Testfälle auf Basis des Quellcodes. Dabei wird zwischen kontrollflussorientierten Tests, die die Ablauflogiktesten, und datenflussorientierten Tests, die die Datenzugriffe kontrollieren, unterschieden.
  • Funktionsorientiertes Testen bestimmt die Testfälle auf Basis der Spezifikation.
    Es wird geprüft, ob die Software die Spezifikation erfüllt. Beim Modultest wird die Software gegen die Modulspezifikation getestet, beim Schnittstellentest gegen die Schnittstellenspezifikation und beim Abnahmetest gegen die Anforderungen des Kunden.
  • Diversifizierendes Testen hingegen testet verschiedene Versionen der Software. Dabei werden die Testergebnisse der verschiedenen Versionen miteinander verglichen. Ein Test gilt als erfolgreich, wenn die Ergebnisse des Tests bei verschiedenen Versionen identisch sind.

Eine aussagekräftigere Unterteilung der dynamischen Prüfmethoden lässt sich bzgl. des Informationsstandes machen. Dabei wird unterschieden, ob der Tester Kenntnis über den zugrunde liegenden Quellcodes besitzt (White-Box-Test) oder nicht (Black-Box-Test).

White-Box-Test

Bei den White-Box-Tests, auch Glass-Box-Tests genannt, steht dem Tester der Quellcode zur Verfügung. Es wird die interne Struktur des Programms getestet unter Berücksichtigung der Spezifikation für einen Soll-Ist-Vergleich. Bei den White-Box- Tests wird davon ausgegangen, dass einige Strukturelemente (Anweisungen, Ausdrücke) fehlerbehaftet sind, wodurch eine Überprüfung aller möglichen Pfade nötig wird. Jedoch kann nicht getestet werden, ob auch alle möglichen Pfade implementiert wurden, die in der Spezifikation aufgeführt sind. Aufgrund der guten Tool-Unterstützung ist eine Automatisierung der Tests möglich. Das strukturbasierte Testen fällt unter die Kategorie der White-Box-Tests.

Black-Box-Test

Bei den Black-Box-Tests steht dem Tester ausschließlich die Spezifikation zur Erstellung seiner Testfälle zur Verfügung. Der Quellcode ist in einem „schwarzer Kasten“ verborgen. Es sollte ein separates Test-Team eingesetzt werden, welches keine Kenntnis über den zugrunde liegenden Quellcode besitzt. Black-Box-Tests suchen nach Abweichungen des Programms zu den Vorgaben in der Spezifikation. Die Nachteile der Black-Box-Tests liegen im größeren organisatorischem Aufwand und den sozialen Aspekten, die durch das separate Test-Team entstehen. Alle funktionsorientierten Testverfahren fallen unter die Kategorie der Black-Box-Tests.

Letztendlich wird eine Kombination von Black-Box-Tests und White-Box-Tests eingesetzt: Black-Box-Tests werden mit White-Box-Tests erweitert, um die nachteiligen Auswirkungen auszugleichen. In der testgetriebene Softwareentwicklung hat sich der Begriff Grey-Box-Test gebildet. Der Grey-Box-Test wird vom Tester, wie ein White-Box-Test geschrieben, jedoch vor der eigentlichen Implementierung des Quellcodes, was ihn mit einem Black-Box-Test verbindet, da noch kaum Informationen über den vorliegenden Quellcode existieren. Die einzigen Informationen sind beispielsweise Klassennamen und Methodensignaturen.

Testfall-Generierung

Ökonomisch betrachtet ist es ein vollständiges Testen nicht möglich. Es muss eine wohlüberlegte Strategie angewandt werden, um die Teilmenge der denkbaren Testfälle so zu wählen, dass möglichst viele Fehler gefunden werden. Nach [Myers95] ist ein Testfall so zu wählen, dass er mit hoher Wahrscheinlichkeit einen bisher unbekannten Fehler entdeckt.

Dazu ist folgendes notwendig:

  • Genaue Kenntnis der Anforderungen an das Programm
  • Kenntnis über die Schnittstellen des Programms zu anderen Systemen
  • Dokumentation und Reproduzierbarkeit der Tests und nachfolgende Aufbereitung der Ergebnisse

Viele Black-Box-Tests lassen ein System schlechter aussehen als es ist und ein weniger gründlich getestetes System besser als es ist.

White-Box-Testverfahren

White-Box-Testverfahren erstellen die Tests auf Grundlage des Quellcodes. Ein Programm gilt als erfolgreich getestet, wenn durch die Tests bestimmte Überdeckungskriterien, z.B. ein fester Prozentsatz erfüllt werden.

Zu den White-Box-Testverfahren gehören:

  • Anweisungsüberdeckungstest
  • Zweigüberdeckungstest
  • Pfadüberdeckungstest
  • Bedingungsüberdeckungstest

Anweisungsüberdeckungstest (C0 − Test)

Der Anweisungsüberdeckungstest verlangt, dass alle Anweisungen des zu testenden Programms mindestens einmal ausgeführt werden. Es werden alle Knoten des Kontrollflussgraphen durch einen Test abgedeckt. Der Test besitzt laut [Balzert98] mit 18% die geringste Fehleridentifizierungsquote. Dies liegt an der fehlenden Berücksichtigung von Kontrollstrukturen und den Datenabhängigkeiten zwischen verschiedenen Programmteilen. Als eigenständiges Testverfahren ist der Anweisungsüberdeckungstest nicht ausreichend geeignet, findet aber Anwendung im Zweigüberdeckungstest.

Zweigüberdeckungstest (C1 − Test)

Beim Zweigüberdeckungstest werden sämtliche Zweige des Kontrollflussgraphen mindestens einmal durchlaufen. Der Nachteil besteht hier, dass Kombinationen von Zweigen nicht geprüft werden und mehrfache Schleifendurchläufe nicht ausreichend geprüft werden. Zusätzlich kann es Schwierigkeiten bereiten, Tests mit den passenden Daten zu erstellen, um alle Zweige zu erreichen. Nach [Balzert98] liegt die
Fehleridentifizierungsquote bei 34%.

Pfadüberdeckungstest (C7 − Test)

Beim Pfadüberdeckungstest müssen sämtliche Pfade des Programms mindestens einmal durchlaufen werden. Problematisch wird dies bei Schleifen mit unbekannter Wiederholungszahl (while-Schleife), da die Anzahl der Pfade ins unendliche ansteigen kann. Aufgrund dessen spielt der Pfadüberdeckungstest in der Praxis keine bedeutende Rolle.

Bedingungsüberdeckungstest (C3A − undC3B/C3C − Test)

Der einfache Bedingungsüberdeckungstest oder auch C3A − Test testet die Entscheidungsstrukturen des Programms. Es wird verlangt, dass Testfälle existieren, in denen einmal eine Teilentscheidung den Wert „true“ und im anderen Fall den Wert „false“ annimmt. Nicht berücksichtigt werden geschachtelte Bedingungen; ist bei einer „oder“-Verknüpfungen der erste Vergleich wahr und bei einer „und“-Verknüpfung der erste Wert falsch, findet keine Überprüfung des zweiten Vergleichs statt. Somit können Fehler im zweiten Ausdruck nicht gefunden werden.
Deshalb fordert der Mehrfach-Bedingungsüberdeckungstest (C3B/C3C−Test), dass auch alle zusammengesetzten Entscheidungen gegen wahr und falsch geprüft werden. Der Nachteil besteht in der hohen Anzahl an Testfällen: Bei n Teilentscheidungen entstehen 2n-Testfälle.

Black-Box-Testverfahren

Black-Box-Testverfahren erstellen die Testfälle mit Hilfe der Spezifikation.
Zu den Black-Box-Testverfahren gehören:

  • Bildung von Äquivalenzklassen
  • Grenzwertanalyse
  • Ursache-Wirkungs-Graph
  • Fehlererwartung (error guessing)
  • Fehlererwartung (error guessing)

Bildung von Äquivalenzklassen

Die Definitionsbereiche der Eingabegrößen und die Wertebereiche der Ausgabegrößen werden in Äquivalenzklassen zerlegt. Es wird angenommen, dass das Programm auf einen Repräsentanten einer Klasse gleich reagiert wie für alle anderen Werte der Klasse. Daher muss für jede Äquivalenzklasse nur ein Test geschrieben werden.
Sind zum Beispiel alle Zahlen von 1 bis 9 gültige Eingabegrößen, so ergeben sich drei Äquivalenzklassen:

  • 1 <= x <= 9 (gültige Eingabe)
  • x < 1 (ungültige Eingabe)
  • 9 < x (ungültige Eingabe)

Für einen Test muss aus jeder Klasse ein Vertreter gewählt werden.

Grenzwertanalyse

Ein Spezialfall der Bildung der Äquivalenzklassen ist die Grenzwertanalyse. Er entstand aus der Beobachtung, dass besonders viele Fehler an den Grenzen der Äquivalenzklassen auftreten. Deshalb sind die Vertreter der Äquivalenzklassen am Rande der Klasse zu wählen. Aus obigem Beispiel würden sich z.B. folgende Testwerte anbieten:

  • x = 1 und x = 9
  • x = 0
  • x = 10

Ein Nachteil der Bildung von Äquivalenzklassen und der Grenzwertanalyse ist die Nichtberücksichtigung der eventuellen Abhängigkeiten von Eingabegrößen. So mag die Eingabe eines Namens und einer Telefonnummer korrekt sein, aber die Überprüfung, ob die Telefonnummer dieser Person gehört, entfällt.

Ursache-Wirkungs-Graph (nach [Myers95])

Um den Nachteil der beiden vorigen Verfahren zu eliminieren, gibt es den Ursache-Wirkungs-Graph. Ein Ursache-Wirkungs-Graph ist eine formale Sprache, in die eine Spezifikation überführt wird. Als Vorkenntnisse sind nur die Operatoren der Boolschen Ausdrücke notwendig.
Zuerst wird die Spezifikation in kleine Teile zerlegt, um den Ursache-Wirkungs-Graph überschaubar zu halten. Anschließend werden die Ursachen und Wirkungen der Spezifikation festgelegt. Dabei ist eine Ursache eine Eingabebedingung oder eine Äquivalenzklasse von Eingabebedingungen, während die Wirkung eine Ausgangsbedingung ist. Werden in der Spezifikation Ursachen oder Wirkungen beschreibende Phrasen gefunden, werden diese markiert. Dann werden die markierten Stellen der Spezifikation analysiert und in einen boolschen Graphen umgewandelt, der Ursachen und Wirkungen verbindet. Der Graph wird danach in eine Entscheidungstabelle umgesetzt.
Aus dieser Entscheidungstabelle entstehen dann die Testfälle.
Der Ursache-Wirkungs-Graph ist dabei auch ein gutes Mittel, Zweideutigkeiten und Unvollständiges in der Spezifikation zu entdecken.

Fehlererwartung („error guessing“)

Die Erfahrung und Intuition eines Testers ist durch nichts zu ersetzen. Aufgrund langjähriger Erfahrung kennt der Programmierer schon viele Fehlerquellen und weiß, wie fehlerträchtige Implementierungen zu vermeiden sind. Sind Tester und Programmierer verschiedene Personen, dann versucht der Tester nachzuvollziehen, welche Überlegungen der Programmierer aus den Vorgaben angestellt hat und was der Programmierer übersehen, nicht berücksichtigt oder falsch interpretiert haben kann.

Zufallstest

Programmierer/Tester neigen dazu, Testfälle zu entwerfen, deren Testdaten mit geringerer Wahrscheinlichkeit Fehler im Programm aufdecken. Der Zufallstest kann dem entgegenwirken. Besonders als Ergänzung von Testfällen, die aus der Bildung von Äquivalenzklassen hervorgehen, erfüllt der Zufallstest einen sinnvollen Zweck.
Die Testdaten werden zufällig aus einer fest vorgegebenen Äquivalenzklasse erstellt. Ein weiteres Beispiel für einen Zufallstests ist die Fehlersuche in einem 2-dimensionalen Eingaberaum, der als 2-dimensionalen Fläche betrachtet werden kann, in der gewisse (unbekannte) Fehlereingaben liegen. Der Zufallstest teilt die Fläche zufällig in vier kleinere Flächen auf und untersucht die größte Fläche nach Fehlern. Enthält die Fläche keine Fehler, dan wird die nächst kleinere Fläche auf Fehler überprüft. Wird ein Fehler gefunden, wird die Fläche wieder zufällig weiter in vier kleinere Flächen aufgeteilt und erneut wie oben überprüft. Dies wird fortgesetzt, bis die Position des Fehlers genau bestimmt ist.
Allein gesehen ist der Zufallstest aber ein zu schwaches Testverfahren.

Der Modultest (Unit-Test)

Da das Testen eines umfangreichen Systems unüberschaubar und kompliziert werden kann, wird das System in Module aufgeteilt und einzeln getestet. Ein Modul steht häufig für eine Prozedur oder Funktion des Programms. Bei objektorientierten Projekten kann ein Modul sogar eine ganze Klasse darstellen. Durch die Aufteilung können Fehler besser lokalisiert werden, funktional unabhängige Module parallel getestet und kombinatorische Schwierigkeiten besser verarbeitet werden. Modultests sind heutzutage auch als Komponententests bekannt. Die Modultests entstehen aus den Black-Box- und White-Box-Testverfahren, die in den vorigen Abschnitten vorgestellt wurden.

Der Integrationstest

Wurden die einzelnen Komponenten getestet, müssen sie ins Gesamtsystem integriert werden. Die Integrationstests sorgen für das fehlerfreie Zusammenspiel der einzelnen Module im Gesamtsystem. Manchmal ist es nicht möglich, ein Modul oder System in seiner späteren Umgebung zu testen. Oder das Zusammenspiel einzelner Module muss simuliert werden, da ein benötigtes Modul noch nicht existiert. Diese Tests müssen entweder später durchgeführt werden, wenn das fehlende Modul implementiert wurde oder es werden Stubs2 und Testtreiber3 eingesetzt. Stubs oder Testtreiber werden in Kapitel 5 genauer beschrieben. Bei der Integration der Module wird zwischen inkrementellem und nichtinkrementellen Testen unterschieden.

Nichtinkrementelles Testen

Beim nichtinkrementelle Testen wird jedes Modul unabhängig von den anderen Modulen getestet, aufrufende Module sind durch Testtreiber zu ersetzen, aufgerufene Module werden durch Stubs simuliert. Wurden alle Module getestet, werden sie in einer „großen“ Integration (Big-Bang-Integration) zum Programm zusammengefügt.

Inkrementelles Testen

Beim inkrementellen Testen wird mit den Modulen der oberen bzw. unteren Ebene begonnen, die als Einzelmodule getestet werden – ebenso wie beim nichtinkrementellen Verfahren. Danach werden die Module der nächsten Ebene nicht einzeln getestet, sondern zuvor mit denen der vorhergehenden Ebene verbunden. Diese Integration weiterer Module zu den bereits getesteten wird solange fortgeführt, bis auch das
letzte Modul getestet wurde.
Das inkrementelle Testen bietet zwei Möglichkeiten neue Module ins Gesamtsystem einzubinden:

  • Bottom-Up-Integration
  • Top-Down-Integration

Bottom-Up-Integration

Die Programmierung beginnt bei den Klassen, die von keiner anderen Klasse abhängig sind. Anschließend können die Klassen implementiert und integriert werden, die auf diesen Klassen aufbauen.

Test
Abbildung 2: Klassendiagramm zur Top-Down-/Bottom-Up-Integration [Link02]

Klassen höherer Ebenen werden durch Testtreiber ersetzt. Bezogen auf die Abbildung ergibt sich beispielsweise D-B-C-A als mögliche Entwicklungsreihenfolge. Im Prinzip ist die Reihenfolge der Entwicklung auf gleicher Ebene unbedeutend; jedoch sollten kritische Module bevorzugt integriert werden, da hier systembetreffende Änderungen am wahrscheinlichsten sind. Ein Vorteil der Bottom-Up-Integration ist, dass die Erzeugung von Testtreibern leichter ist als die Erstellung von Stubs, wie sie bei der Top-Down-Methode benötigt werden. Der Bottom-Up-Ansatz versagt jedoch bei Klassen, die voneinander abhängig sind. Diese Klassen müssen dann en bloc entwickelt werden.

Top-Down-Integration

Bei der Top-Down-Integration ist die Entwicklungsreihenfolge genau umgekehrt: Es wird mit Klasse A begonnen, Klasse B und C werden durch Stubs repräsentiert. Nach dem Test der Klasse A wird mit der Implementierung der Klasse B begonnen und der entsprechende Stub entfernt. Durch die Top-Down-Integration erhält man recht schnell ein Rahmenprogramm, das das gewünschte fertige Programm in großen Teilen simuliert. Denkfehler sind leichter zu entdecken, und dem Kunden kann schon früh ein Programm vorgeführt werden.
Als Nachteil erweisen sich Veränderungen, die sich in unteren Ebenen ergeben und schwerwiegende Auswirkungen auf höhere Ebenen haben. Schon getestete Klassen höherer Ebenen müssen unter Umständen verändert und nochmals getestet werden.

Nach [Myers95] ist das inkrementelle Verfahren dem nichtinkrementellen Verfahren
vorzuziehen:

  • Nichtinkrementelles Testen erfordert einen höheren Aufwand (Stubs und Treiber werden benötigt).
  • Programmfehler werden durch nicht passende Schnittstellen eher entdeckt.
  • Die Fehlerfindung ist bei Schnittstellen einfacher; meistens ist das zuletzt eingefügte Modul für den Fehler verantwortlich.

Nichtinkrementelles Testen bietet hingegen eine kürzere Maschinenlaufzeit, da die Treiber und Stubs kaum Rechenzeit benötigen. Zudem kann ein Entwicklungsteam die einzelnen Module parallel implementieren und testen.

Der Systemtest

Der Systemtest hat das Gesamtsystem als Ziel und ist der abschließende Test, um die gewünschte Funktionalität des Programms sicherzustellen. Als Grundlage für den Systemtest dienen die vom Kunden definierten Anforderungen. Der Systemtest besteht aus mehreren Schritten:

  • Funktionstest
  • Leistungstest
  • Benutzbarkeitstest
  • Interoperabilitätstest
  • Installationstest
  • Abnahmetest
  • Regressionstest

Funktionstest

Im Funktionstest wird versucht, Unstimmigkeiten zwischen dem System und der Spezifikation festzustellen. Es muss überprüft werden, ob die geforderten Funktionen wie vorgesehen realisiert wurden. Hauptaufgabe des Funktionstest ist die Korrektheit und Genauigkeit der Implementierung zu gewährleisten.

Leistungstest

Der Leistungstest besteht aus dem Volumentest, dem Zeittest und dem Stresstest. Ziel des Volumentests ist die Aufdeckung unnormalen Verhaltens der Programm-Funktionen bei großen Datenmengen. Der Zeittest kontrolliert die Einhaltung der zeitlichen Grenzen (Performance-Test). Der Stresstest soll das System unter Ausnahmesituationen analysieren. Dabei versucht der Crashtest, das System zum Absturz zu bringen, während der Lasttest das System hohen Anforderungen aussetzt und bewusst die Grenzen der Software übersteigt.

Benutzbarkeitstest

Der Benutzbarkeitstest soll die Benutzerfreundlichkeit des Programms sicherstellen. Werden Fehlermeldungen für den Benutzer verständlich dargestellt? Ist die Benutzeroberfläche gut strukturiert?

Sicherheitstest

Ziel des Sicherheitstest ist die Aufspürung von Sicherheitslöchern im Programm. Dazu zählt z.B. die Kontrolle der Verschlüsselung von Passwörtern.

Interoperabilitätstest

Heutige Software muss die Fähigkeit besitzen, mit „fremder“ Software kommunizieren zu können. Der Interoperabilitätstest testet das kausale und kommunikative Zusammenwirken der beteiligten Systeme.

Installationstest

Entspricht die Entwicklungsmaschine nicht der Zielmaschine, muss gewährleistet werden, dass die Installationsroutine unter verschiedenen Systemumgebungen korrekt funktioniert.

Abnahmetest

Der Abnahmetest erfolgt in zwei Schritten: In der Werksabnahme wird das System vom Entwickler-Team anhand den Anforderungen des Kunden abgenommen. In der Kundenabnahme wird das System in seiner endgültigen Umgebung eingesetzt und vom Kunden selbst getestet. Bei beiden Abnahmen wird gegen die Produktdefinition geprüft, dabei kommen oben genannten Tests wie der Funktionstest, der Leistungstest und der Benutzbarkeitstest zum Einsatz.

Regressionstest

Alle Testverfahren sollten darauf ausgelegt sein, bereits durchgeführte Tests erneut ausführen zu können. Dadurch kann die Fehlersuche im System nach einer Fehlerkorrektur, Umstrukturierungsmaßnahmen oder für den Abnahmetest durchgeführt werden. Behobene Fehler, die erneut auftauchen, können dadurch sofort entdeckt werden.

Der Testprozess

Um die Effizienz des Testprozess zu gewährleisten bedarf es nach [SpLi03] einer Aufteilung des Testprozesses in mehrere Teilaufgaben:

  • Testplanung
  • Testspezifikation
  • Testdurchführung
  • Testprotokollierung
  • Testauswertung
  • Testwiederholung
  • Testbeendigung

Testplanung

In der Phase der Testplanung wird die allgemeine Vorgehensweise festgelegt, z. B. wie Testfälle ermittelt werden. Des Weiteren gilt es die vorhandenen Ressourcen (Personal, Zeit, Hardware, Tools, . . . ) sinnvoll und effizient einzusetzen, da ein vollständiges Testen der Software meistens nicht möglich ist (Prioritäten setzen). Wichtige Systemteile müssen frühzeitig durch kritische Tests auf ihre Zuverlässigkeit geprüft werden, da gegen Projektende die Tests oft aus Zeitmangel als erstes gestrichen werden. Es muss außerdem geklärt werden, auf welche Weise der Testprozess in den Entwicklungsprozess integriert werden kann.

Testspezifikation

Die Testspezifikation dient der genauen Beschreibung der Testfälle. Testfälle werden prinzipiell in zwei Kategorien unterschieden:

  • Logische Testfälle
  • Konkrete Testfälle

Die konkreten Testfälle besitzen tatsächliche Eingabewerte und stellen die verwendete Auswahl an Testfällen dar, während die logischen Testfälle Beschreibungen von Testfallmengen sind, die das gleiche Resultat erwarten lassen. Testfälle enthalten nicht nur Testdaten, sondern auch Vorbedingungen, die der Test einhalten muss. Zusätzlich muss ein erwartetes Ergebnis des Tests angegeben werden, um einen Soll-Ist-Vergleich durchführen zu können.

Nach [SpLi03] werden Testfälle auch folgend unterschieden:

  • Testfälle, die das spezifizierte Verhalten des Testobjekts validieren. Dazu gehört auch der Negativtest, der die spezifizierte Behandlung von Ausnahme- und Fehlersituationen testet.
  • Testfälle, die das nicht-spezifizierte Ausnahmeverhalten des Testobjekts überprüfen. Hierunter fallen alle Tests, die entweder die Vorbedingung verletzen und/oder ungültige Eingabewerte verwenden.

In der Testspezifikation werden auch Angaben über die benötigte Testinfrastruktur gemacht, die erforderlich ist, um die Testfälle auf dem zu testenden System ablaufen zu lassen.

Testdurchführung

Sind alle Vorbereitungen beendet worden, muss geprüft werden, ob sich die Testobjekte in der Testumgebung ausführen lassen. Anschließend kann mit der Durchführung der Testfälle begonnen werden.

Testprotokollierung

Die Protokollierung der Testdurchführung gilt dem späteren Nachweis, ob die in der Testplanung festgelegte Teststrategie im erforderlichen Maße umgesetzt wurde. Weiterhin ist das Testprotokoll auch als Kommunikationsmittel einsetzbar, um z.B. dem Auftraggeber den Fortschritt der Testarbeiten belegen zu können.
Ein Testprotokoll muss folgendes enthalten ([SpLi03]):

  • Welche Systemteile wurden getestet?
  • Wann wurden die Teile getestet?
  • Von wem wurden die Teile getestet?
  • Wie intensiv wurden die Teile getestet?
  • Welche Ergebnisse lieferten die Tests?

Die Protokollierung hat zusätzlich die Aufgabe der Archivierung der Testware, um eine Wiederholung der Tests zu ermöglichen.

Testauswertung

In der Testauswertung sind aufgetretene Abweichungen vom Soll-Ist-Verhalten dahingehend zu überprüfen, ob der Fehler tatsächlich von der zu testenden Software entstanden ist oder andere Faktoren verantwortlich sind. Solche Faktoren sind z.B. ([SpLi03]):

  • Ungenaue oder fehlerhafte Testspezifikation
  • Fehlerhafte Testinfrastruktur
  • Fehlerhafte Testfälle

Es entstehen sog. Testzyklen, d.h. Fehlerfindung und Fehlerkorrektur werden abwechselnd durchgeführt, bis sämtliche Testfälle erfolgreich durchlaufen werden. Da außerdem nicht ausgeschlossen ist, dass durch die Korrektur weitere Defekte in die Software eingebracht worden sind, ist gegebenenfalls darüber nachzudenken, zusätzliche Testfälle zu entwerfen. In so einem Fall muss dann die Testspezifikation erweitert und zusätzliche Testfälle aufgenommen werden.

Testwiederholung

Vorhandene Tests haben einen besonderen Vorteil: Bei Refaktorisierungen am Quellcode können die schon existierenden Tests ohne großen Aufwand ausgeführt werden. In diesem Fall werden diese Tests zu Regressionstests.
Werden die Regressionstests zu 100% erfolgreich durchlaufen und wurden alle gewünschten Änderungen umgesetzt, befindet sich das System im erwarteten Zustand. Werden die Regressionstests nicht erfolgreich durchlaufen, dann zeigen die fehlgeschlagenen Tests an, an welcher Stelle noch Änderungen vorgenommen werden müssen.

Testbeendigung

Ein komplexes Programm kann nicht völlig fehlerfrei gehalten werden und ein vollständiges Testen ist auch nicht möglich. Das Testen wird letztlich dann beendet, wenn ein vorher festgelegtes Testendekriterium erfüllt ist. Abbildung 3 zeigt den optimalen Qualitätsgrad, der, wenn er erreicht wird, die minimalsten Gesamtkosten aus Testkosten und Fehlerfolgekosten zur Folge hat.

Abbildung 3: Optimaler Qualitätsgrad [PolKoSp02]

Kann der optimale Qualitätsgrad in der Testplanung ungefähr geschätzt werden, ist daraus ein Testendekriterium ableitbar. Ein solches Testendekriterium kann über z. B. über Testmetriken erfolgen, wie ein fester Prozentsatz bei Überdeckungsverfahren (siehe White-Box-Testverfahren) oder einer Fehlerfindungsrate bei deren Unterschreitung das Testen beendet wird.

Testautomatisierung

Ein schnelleres und besseres Testen kann durch die Automatisierung des Testprozesses erfolgen (siehe Abbildung 4). Die Erstellung automatischer Tests ist kurzfristig zeitintensiver als manuell erzeugte Tests; doch bei öfterer Wiederholung eines Tests ist schon ein Zeitgewinn feststellbar.

Test
Abbildung 4: Automatisiertes Testen vs. Manuelles Testen [PolKoSp02]

Die Automatisierung erfolgt mit Hilfe von Test-Tools. Test-Tools dienen jedoch nur zur Unterstützung des Testprozesses. Sie kommen also erst zum Einsatz, wenn daraus ein positiver Nutzen gezogen werden kann.

Vorteile der Testautomatisierung sind ([PolKoSp02]):

  • langfristig weniger Zeitaufwand
  • kürzere Durchlaufzeiten
  • höhere Testintensität
  • größere Flexibilität beim Testen
  • umfassenderes und schnelleres Feedback
  • bessere Motivation des Testpersonals

Die Automatisierung des Testprozesses ist nicht nur auf die Testdurchführung beschränkt:

  • Testplanung: Nicht automatisierbar.
  • Testspezifikation: Die Testspezifikation ist nur bei Zufallstests automatisierbar. Die Generierung der Testdaten für die Zufallstests kann automatisiert stattfinden.
  • Testdurchführung, Testwiederholung: Die Ausführung der Tests kann automatisiert vorgenommen werden. Jedoch ist darauf zu achten, dass sich die Testumgebung immer im gleichen Grundzustand befindet, um bei einer Testwiederholung zum gleichen Ergebnis zu kommen.
  • Testprotokollierung, Testauswertung: Die Protokollierung kann während der Testdurchführung in Log-Files oder ähnlichen Strukturen stattfinden. Die Auswertung wird vom eingesetzten Test-Tool (beispielsweise JUnit) vorgenommen. Dabei hat eine automatisierte Testauswertung die Aufgabe den Erfolg oder Misserfolg eines Tests darzustellen.

Quellen:

[Balzert98] Helmut Balzert: Lehrbuch der Software-Technik. Software-Management,
Software-Qualitätssicherung, Unternehmensmodellierung. Akademischer Verlag
GmbH, Heidelberg, 1998

[Liggesmeyer02] Peter Liggesmeyer: Software-Qualität: Testen, Analysieren und Verifizieren
von Software. Spektrum Akademischer Verlag, 2002

[Link02] Johannes Link, Peter Fröhlich: Unit Tests mit Java. dpunkt.verlag, 2002

[Myers95] Glenford J. Myers: Methodisches Testen von Programmen. 5. Auflage,
Oldenburg Verlag, 1995

[PolKoSp02] Martin Pol, Tim Koomen, Andreas Spillner: Management und Optimierung
des Testprozesses. dpunkt.verlag, 2002

[SpLi03] Andreas Spillner, Tilo Linz: Basiswissen Softwaretest: Aus- und Weiterbildung
zum Certified Tester. dpunkt.verlag, 2003

  Eine Antwort zu “Theorie der Softwaretests”

  1. Auf welcher Seite im Buch „Management und Optimierung des Testprozesses“ finde ich die Abbildung 4: Automatisiertes Testen vs. Manuelles Testen [PolKoSp02]?

 Antworten

   
Impressum Suffusion theme by Sayontan Sinha