Dynamisches Software-Testverfahren
# Dynamisches Software-Testverfahren

Dynamische Software-Testverfahren sind bestimmte Prüfmethoden, um mit Softwaretests Fehler in der Software aufzudecken. Besonders sollen Programmfehler erkannt werden, die in Abhängigkeit von dynamischen Laufzeitparametern auftreten, wie variierende Eingabeparameter, Laufzeitumgebung oder Nutzer-Interaktion.

## Beschreibung

Während bei statischen Verfahren die zu testende Software nicht ausgeführt wird (Compilezeit), setzen dynamische Verfahren die Ausführbarkeit der Software voraus (Laufzeit). Grundprinzip der dynamischen Verfahren ist die kontrollierte Ausführung der zu testenden Software mit systematisch festgelegten Eingabedaten (Testfälle). Für jeden Testfall werden zu den Eingabedaten auch die erwarteten Ausgabedaten angegeben. Die vom Testlauf erzeugten Ausgabedaten werden mit den jeweils erwarteten Daten verglichen. Bei Abweichungen liegt ein Fehler vor.
Wesentliche Aufgabe der einzelnen Verfahren ist die Bestimmung geeigneter Testfälle für den Test der Software.
Die dynamischen Verfahren lassen sich wie folgt kategorisieren:

## Spezifikationsorientierte Verfahren

Spezifikationsorientierte bzw. Black-Box Verfahren (früher funktionsorientierte Testmethoden) werden zur Bestimmung von Testfällen benutzt, mit denen geprüft werden soll, inwieweit der Prüfling (auch Testling, Testobjekt oder Testgegenstand genannt) die vorgegebenen Spezifikationen erfüllt (Black Box). Man spricht auch davon, dass „gegen die Spezifikationen“ getestet wird. Je nach Testling und Testart sind die Spezifikationen dabei von unterschiedlicher Art. Beim Modultest wird z. B. gegen die Modulspezifikation getestet, beim Schnittstellentest gegen die Schnittstellenspezifikation und beim Abnahmetest gegen die fachlichen Anforderungen, wie sie etwa in einem Pflichtenheft niedergelegt sind.

### Äquivalenzklassenbildung

Bei der Äquivalenzklassenbildung werden die möglichen Werte der Eingaben (oder auch der Ausgaben) in Klassen eingeteilt, von denen vermutet werden kann, dass Fehler, die bei der Verarbeitung eines Wertes aus dieser Klasse auftreten, auch bei allen anderen Vertretern der Klasse auftreten. Wenn andererseits ein Vertreter der Klasse korrekt verarbeitet wird, wird vermutet, dass auch die Eingabe aller anderen Elemente der Klasse nicht zu Fehlern führt. Insofern können die Werte einer Klasse als (in dieser Hinsicht) äquivalent zueinander angesehen werden.
Auf Basis der Äquivalenzklassen werden die Testfälle gebildet. Zum Test der gültigen Äquivalenzklassen werden die Testdaten aus möglichst vielen gültigen Äquivalenzklassen erzeugt. Um die ungültigen Äquivalenzklassen zu testen, wird jeweils ein Testdatum aus einer ungültigen Äquivalenzklasse mit ausschließlich gültigen Testdaten aus den übrigen Äquivalenzklassen kombiniert.
Die Äquivalenzklassenbildung hat Vor- und Nachteile. Die Vorteile sind, dass sie
* die Basis für die Grenzwertanalyse ist,
* ein geeignetes Verfahren darstellt, um aus Spezifikationen repräsentative Testfälle abzuleiten.
Der Nachteil ist, dass nur einzelne Eingaben betrachtet werden. Beziehungen oder Wechselwirkungen zwischen Werten werden nicht behandelt.

#### Beispiel

In der Spezifikation eines Online-Banking-Systems wird gefordert, dass nur Beträge von 0,01 bis 500 € eingegeben werden dürfen. Man kann dann vermuten, dass eine Überweisung in Höhe von 123,45 € akzeptiert und korrekt ausgeführt wird, wenn ein Test ergeben hat, dass eine Überweisung von 123,44 € korrekt durchgeführt wird. Verallgemeinert kann angenommen werden, dass alle Beträge von 0,01 € bis 500,00 € korrekt verarbeitet werden, wenn dies für einen beliebigen Betrag aus diesem Bereich der Fall ist. Es reicht also aus, einen beliebigen Vertreter aus dem Bereich zu testen, um einem möglichen Fehler auf die Spur zu kommen.
In gleicher Weise kann man für negative Werte und für Werte größer als 500 € argumentieren. Für Tests sollte es daher ausreichen, drei Äquivalenzklassen zu bilden (eine gültige und zwei ungültige Äquivalenzklassen):
* Werte von 0,01 bis und mit 500,00 € (gültig)
* Werte kleiner gleich null (ungültig)
* Werte größer als 500,00 € (ungültig)
Jede Überweisung im Online-Banking-System muss durch die Eingabe einer TAN autorisiert werden. Analog zur ersten Äquivalenzklasse können hier für die Eingabe der TAN vier Äquivalenzklassen gebildet werden:
* Eingabe einer korrekten TAN
* Eingabe einer falschen TAN
* Eingabe zu kurzer TAN
* Eingabe zu langer TAN
Auf Basis der beiden Äquivalenzklassen werden die nachfolgenden Testfälle definiert:
* Eingabe eines gültigen Werts (z. B. 123,45 €) und Bestätigung mit einer korrekten TAN (ausgeführt, weil alles korrekt ist.)
* Eingabe eines gültigen Werts (z. B. 123,45 €) und Bestätigung mit einer falschen TAN (fehlgeschlagen, weil falsche TAN.)
* Eingabe eines ungültigen Werts (z. B. 600,00 €) und Bestätigung mit einer korrekten TAN (fehlgeschlagen, weil ungültiger Wert.)
* Eingabe eines gültigen Werts (z. B. 123,45 €) und Bestätigung mit einer zu kurzen TAN (fehlgeschlagen, weil TAN zu kurz ist.)
* Eingabe eines gültigen Werts (z. B. 123,45 €) und Bestätigung mit einer zu langen TAN (fehlgeschlagen, weil TAN zu lang ist.)
Mit der Äquivalenzklassenbildung ist es nicht möglich, Abhängigkeiten zwischen verschiedenen Eingabewerten zu berücksichtigen. So ist es etwa bei der Prüfung einer eingegebenen Adresse nicht ausreichend, für Ortsnamen, Straßennamen und Postleitzahlen jeweils (z. B. anhand einer Datenbank) zu prüfen, ob diese zur Klasse der gültigen Werte gehören. Sie müssen auch zusammenpassen.

### Grenzwertanalyse

Die Grenzwertanalyse ist ein Spezialfall der Äquivalenzklassenanalyse. Sie ist aus der Beobachtung entstanden, dass Fehler besonders häufig an den „Rändern“ der Äquivalenzklassen auftreten. Daher werden hier nicht beliebige Werte getestet, sondern sog. Randwerte oder Grenzwerte. Im Beispiel wären dies die Werte
* 0,00 € (ungültige Eingabe)
* 0,01 € (gültige Eingabe)
* 500,00 € (gültige Eingabe)
* 500,01 € (ungültige Eingabe)

### Pairwise-Methode

Die Pairwise-Methode ist ein Verfahren, die Anzahl von Tests von Kombinationen mehrerer Eingabewerte zu reduzieren, indem nicht alle möglichen Kombinationen getestet werden. Stattdessen wird lediglich jeder Eingabewert eines Feldes paarweise mit jedem Eingabewert der anderen Felder zusammen getestet. Dies reduziert die Anzahl der nötigen Tests radikal, bedeutet aber natürlich auch, dass unter Umständen Fehler nicht entdeckt werden, die nur bei ganz bestimmten Kombinationen von mehr als zwei Feldern auftreten.

### Zustandsbasierte Testmethoden

Zustandsbasierte Testmethoden basieren auf Zustandsautomaten, die heute oft als UML-Diagramm dargestellt werden.
In der Beschreibung des Zustandsautomaten sind üblicherweise keine Fehlerfälle vorgesehen. Diese sind zusätzlich zu spezifizieren, indem zu jeder Kombination „{Ausgangszustand; Ereignis}“ (auch den im Automaten nicht spezifizierten Kombinationen) der Folgezustand und die ausgelösten Aktionen angegeben werden. Diese Kombinationen können dann alle getestet werden. Einsetzbar sind zustandsbasierte Methoden außer in technischen Anwendungen auch beim Test grafischer Benutzeroberflächen und von Klassen, die durch Zustandsautomaten definiert sind.
Die Vollständigkeit der so ermittelten Testfälle ist gegeben, wenn alle folgenden Kriterien erfüllt sind:
* Werden alle Zustandsübergänge durchlaufen?
* Werden alle Ereignisse, die Zustandsübergänge hervorrufen sollen, getestet?
* Werden alle Ereignisse, die keine Zustandsübergänge hervorrufen dürfen, getestet?

### Ursache-Wirkung-Analyse

Bei dieser Methode werden Ursachen und Wirkungen jeder Teilspezifikation identifiziert. Eine Ursache ist dabei eine einzelne Eingabebedingung oder eine Äquivalenzklasse von Eingabebedingungen; eine Wirkung ist eine Ausgabebedingung oder eine Systemtransformation.
Die Teilspezifikation wird in einen Boole’schen Graphen überführt, der Ursachen und Wirkungen durch logische Verknüpfungen verbindet. Anschließend wird der Graph um Abhängigkeiten auf Grund von syntaktischen Zwängen oder Umgebungsbedingungen ergänzt. Die folgenden Arten von Abhängigkeiten zwischen Ursachen werden dabei unterschieden:
* Exklusive Abhängigkeit: Die Anwesenheit einer Ursache schließt andere Ursachen aus.
* Inklusive Beziehung: Mindestens eine von mehreren Ursachen liegt vor (z. B. ist eine Ampel immer grün, gelb oder rot – oder rot und gelb zusammen. Wenn sie funktioniert und eingeschaltet ist).
* One-and-only-one-Beziehung: Es liegt genau eine von mehreren Ursachen vor (z. B. männlich oder weiblich).
* Requires-Abhängigkeit: Die Anwesenheit einer Ursache ist Voraussetzung für das Vorhandensein einer anderen (z. B. Alter > 21 und Alter > 18).
* Maskierungsabhängigkeit: Eine Ursache verhindert, dass eine andere Ursache eintreten kann.
Der so entstandene Graph wird zu einer Entscheidungstabelle umgeformt. Dabei werden bestimmte Regeln angewandt, die aus einer Verknüpfung von n Ursachen n+1 Testfälle generieren (statt $2^{n}$, wie es bei einer vollständigen Entscheidungstabelle der Fall wäre). Dabei entspricht jeder Testfall einer Spalte der Entscheidungstabelle.

## Strukturorientierte Verfahren

Strukturorientierte bzw. White-Box Verfahren bestimmen Testfälle auf Basis des Softwarequellcodes (Whiteboxtest).
Software-Module enthalten Daten, die verarbeitet werden, und Kontrollstrukturen, die die Verarbeitung der Daten steuern. Entsprechend unterscheidet man Tests, die auf dem Kontrollfluss basieren, und Tests, die Datenzugriffe als Grundlage haben.
Kontrollflussorientierte Tests beziehen sich auf logische Ausdrücke der Implementierung. Datenflussorientierte Kriterien konzentrieren sich auf den Datenfluss der Implementierung. Genau genommen konzentrieren sie sich auf die Art und Weise, in welcher Hinsicht die Werte mit ihren Variablen verbunden sind und wie diese Anweisungen die Durchführung der Implementierung beeinflussen.

### Kontrollflussorientierte Tests

Die kontrollflussorientierten Testverfahren orientieren sich am Kontrollflussgraphen des Programms. Es werden folgende Arten unterschieden:
* Anweisungsüberdeckung
* Kantenüberdeckung (Zweigüberdeckung)
* Bedingungsüberdeckung
* Pfadüberdeckung

### Datenflussorientierte Tests

Datenflussorientierte Testmethoden basieren auf dem Datenfluss, also dem Zugriff auf Variablen. Sie sind besonders geeignet für objektorientiert entwickelte Systeme.
Für die datenflussorientierten Tests gibt es unterschiedliche Kriterien, welche im Folgenden beschrieben werden.
All defs-Kriterium Für jede Definition (all defs) einer Variablen wird eine Berechnung oder Bedingung getestet. Für jeden Knoten und jede Variable muss ein definitionsfreier Pfad zu einem Element getestet werden. Die Fehlererkennungsrate liegt bei diesem Kriterium bei ca. 24 %.
All-p-uses-Kriterium Die „p-uses“ dienen zur Bildung von Wahrheitswerten innerhalb eines Prädikates (predicate-uses). Die Fehlererkennungsrate liegt bei diesem Kriterium bei ca. 34 %. Es werden insbesondere Kontrollflussfehler erkannt.
All-c-uses-Kriterium Unter dem „c-uses-Kriterium“ wird die Berechnung (computation-uses) von Werten innerhalb eines Ausdrucks verstanden. Dieses Kriterium deckt ca. 48 % aller c-uses-Fehler auf. Es identifiziert insbesondere Berechnungsfehler.
Wegen ihrer Kompliziertheit sind die Techniken zur datenflussorientierten Testfallermittlung nur werkzeuggestützt einsetzbar. Da es aber kaum Werkzeuge gibt, haben sie zurzeit noch keine praktische Relevanz.

## Diversifizierende Testmethoden

Die Gruppe der diversifizierenden Tests umfasst eine Menge von Testtechniken, die verschiedene Versionen einer Software gegeneinander testen. Es findet kein Vergleich zwischen den Testergebnissen und der Spezifikation, sondern ein Vergleich der Testergebnisse der verschiedenen Versionen statt. Ein Testfall gilt als erfolgreich absolviert, wenn die Ausgaben der unterschiedlichen Versionen identisch sind. Auch wird im Gegensatz zu den spezifikations- und strukturorientierten Verfahren kein Vollständigkeitskriterium spezifiziert. Die notwendigen Testdaten werden mittels einer der anderen Techniken, per Zufall oder Aufzeichnung einer Benutzer-Session erstellt.
Die diversifizierenden Tests umgehen die oft aufwändige Beurteilung der Testergebnisse anhand der Spezifikation. Dies birgt natürlich die Gefahr, dass ein Fehler, der in den zu vergleichenden Versionen das gleiche Ergebnis produziert, nicht erkannt wird. Auf Grund des einfachen Vergleichens lassen sich solche Tests sehr gut automatisieren.

### Back-to-Back-Test

Beim Back-to-Back-Test entstehen verschiedene gegeneinander zu testende Versionen aus der n-Versionen-Programmierung, d. h. die Programmierung verschiedener Versionen einer Software nach der gleichen Spezifikation. Die Unabhängigkeit der Programmierteams ist dabei eine Grundvoraussetzung.
Dieses Verfahren ist sehr teuer und nur bei entsprechend hohen Sicherheits-Anforderungen gerechtfertigt.

### Mutationen-Test

Der Mutationen-Test ist keine Testtechnik im engeren Sinne, sondern ein Test der Leistungsfähigkeit anderer Testmethoden sowie der verwendeten Testfälle. Die verschiedenen Versionen entstehen durch künstliches Einfügen von typischen Fehlern. Es wird dann geprüft, ob die benutzte Testmethode mit den vorhandenen Testdaten diese künstlichen Fehler findet. Wird ein Fehler nicht gefunden, werden die Testdaten um entsprechende Testfälle erweitert. Diese Technik beruht auf der Annahme, dass ein erfahrener Programmierer meist nur noch "typische" Fehler macht.

### Regressionstest

Unter einem Regressionstest versteht man in der Softwaretechnik die Wiederholung von Testfällen.