Testende Verfahren
Kontrollflussorientierte Strukturtestverfahren
Anweisungsüberdeckungstest (C0-Test)
- Verlangt die Ausführung aller Anweisungen (Knoten)
- 100% Überdeckung bedeutet jede Anweisung wurde überprüft
- Testpfad enthält alle Knoten aber nicht alle Kanten
- Überdeckungsgrad = Zahl der ausgeführten Anweisungen / Gesamtzahl aller Anweisungen
Bemerkungen:
- Wesentliche Aspekte eines Programms werden nicht geprüft!
- Notwendige, aber nicht hinreichende Testbedingung
- Toter Code kann gefunden werden
- Nur in Kombination mit anderen Verfahren sinnvoll (18 % Fehleridentifizierung)
Zweigüberdeckungstest (C1-Test)
- auch Entscheidungsüberdeckungstest
- Verlangt die Ausführung aller Zweige (Kanten)
- Korrektheit des Kontrollflusses an Verzweigungen wird kontrolliert
Bemerkungen:
- Nicht ausführbare Zweige können gefunden werden
- Fehlende Zweige können nicht entdeckt werden
- Höhere Fehleridentifizierungsquote als Anweisungsüberdeckungstest, Leistungsfähigkeit schwankt zwischen 25 und 75 %
- Gilt als das minimale Testkriterium
- Unzureichender Schleifentest → Pfadüberdeckungstest notwendig
- Keine Berücksichtigung von Abhängigkeiten zwischen Zweigen → Pfadüberdeckungstest notwendig
- Nicht für Test komplexer Bedingungen → Bedingungsüberdeckungstest
Pfadüberdeckungstests
Ausführung aller unterschiedlichen Pfade im Programm
Allgemeiner Pfadüberdeckungstest
Problem:
- Schleifen mit unbekannter Zahl an Wiederholungen
- Bei aufeinander folgenden Schleifen steigt die Zahl der Testfälle multiplikativ
- Schleife mit N Durchläufen und einer inneren Verzweigung fordert 2N Testfälle
Bemerkungen:
- Einige (konstruierbare) Pfade können sich gegenseitig ausschließen
- Sehr mächtiges kontrollflussorientiertes Testverfahren
- Praktische Bedeutung nur für Programmteile ohne Schleifen
Boundary Interior-Test
Eingeschränkter Pfadüberdeckungstest, im Durchlauf wird nur zwischen keinmal, einmal und mehrmals unterschieden → dadurch praktisch anwendbar
Unterscheidung in 2 Gruppen:
- Grenztest-Gruppe (bondary tests): Pfade, wobei die Schleife nur einfach durchlaufen wird
- Gruppe zum Test der Reinitialisierung (interior tests): Pfade, die die Schleife mindestens einmal wiederholen
Strukturierte Pfadtest: Verallgemeinerung des Boundary Interior Test
Bedingungsüberdeckungstest
- Zur Analyse der Testbedingungen in Schleifen und Verzweigungen aus struktureller Perspektive
- Ansatz:
- Bedingung ist logische Verknüpfung atomarer boolescher Funktionen
- Testfälle sollen verschiedene Kombinationen abdecken
Varianten:
- Einfache Bedingungsüberdeckung
- Weder Zweig- noch Anweisungsüberdeckung → sehr schwach
- Mehrfach-Bedingungsüberdeckung
- Zweigüberdeckung enthalten → sehr aufwendig
- Minimale Mehrfach-Bedingungsüberdeckung
- Unter Beachtung der hierarchischen Struktur
- Überdeckung nicht nur der Blätter, sondern aller Teilbäume
- → sinnvolle Weiterentwicklung des Zweigtests
Auswahl geeigneter kontrollflussorientierter Testverfahren
- Programm im Quelltext?
⇒ Falls nicht, kein Strukturtest möglich - Besteht Programm nur aus Anweisungen?
⇒ Anweisungsüberdeckung sinnvoll - Besteht Programm nur aus Anweisungen und Verzweigungen mit atomaren Testbedingungen?
⇒ Zweigüberdeckung - Besteht Programm aus Anweisungen, Verzweigungen und Schleifen mit atomaren Testbedingungen?
⇒ Pfadüberdeckung
je nach Komplexität der Schleifensemantik doppelte oder mehrfache Schleifenüberdeckung - Besteht Programm aus komplexen Testbedingungen?
⇒ Kopplung geeigneter Verfahren mit Bedingungsüberdeckung
Datenflussorientierte Strukturtests
Dynamisches Strukturtestverfahren zum Test der Datenbenutzungen
Aufstellung eines Datenflussdiagramms mit
- Sichtbarkeit und Lebensdauer von Bezeichnern
- Variablenidentitäten
- Lesenden und schreibenden Zugriffen auf die Variablen
- Unterscheidung der lesenden Zugriffe in Anweisungen und Bedingungen
Besondere Eignung für Datenobjekte bzw. -klassen
Kennzeichnung durch Pfeil, ob Lese- oder Schreibzugriff ( a ← = ← a + 1)
Klassifikation:
- Zuweisung (def): Änderung des Variablenwertes
- Berechnung v. anderen Werten (computational-use, c-use)
- Berechnung v. Wahrheitswerten (predicate-use, p-use)
Testverfahren
- all-defs-Kriterium:
Testfälle sind so zu wählen, dass jeder Zuweisung auch eine Wertbenutzung folgt (exemplarische Überprüfung der Variablensemantik)
- Zu jeder Variablen gibt es einen Testfall, wo die Variable mindestens einmal geschrieben und gelesen wird → sonst Programm-Fehler
- all-p-uses-Kriterium:
Testfälle so wählen, dass jede Kombination einer Wertzuweisung mit einer prädikativen Nutzung des Wertes überdeckt wird (Prüfung der Auswirkung einer Zuweisung auf alle relevanten Bedingungsknoten); beinhaltet Zweigüberdeckung
- all-c-uses/some-p-uses-Kriterium:
Testfälle so wählen, dass jede Kombination einer Zuweisung mit jeder berechnenden Nutzung überdeckt wird (Überprüfung aller kausal abhängigen Ausdrücke und exemplarischer Test von bedingungsrelevanten Variablen)
- bei keinem berechnendem Zugriff mind. eine Nutzung als Prädikat
- all-p-uses/some-c-uses:
umgekehrt wie all c-uses/some p-uses
- all uses:
Testfälle werden so gewählt, dass jede Kombination der Zuweisung mit jeder Nutzung überdeckt wird (komplettester, aber aufwändigster Test)
Funktionale Testverfahren
Idee: Ableitung der Testfälle aus Programmspezifikationen, Black-Box-Test (ohne Quelltexte möglich)
Ziel: Test der Programmsemantik auf Erfüllung der Spezifikation
Bildung von Äquivalenzklassen für Testdaten:
- Exemplarischer Vertreter pro Klasse
- Klasseneinteilung für „typisches Programmverhalten“
- Korrektheit eines Vertreters einer Klasse lässt Korrektheit der ganzen Klasse erwarten (kein Beweis dafür!)
- Bewertung:
- Zur Herleitung repräsentativer Testfälle
- Nur Betrachtung einzelner Werte, nicht von Wechselwirkungen oder Abhängigkeiten
- Bildung von Klassen: Falls Eingabebereich =
- Ein zusammenhängender Wertebereich: 3 Klassen, eine gültige, 2 ungültige (rechts und links vom Wertebereich)
- Eine Menge von Werten, die alle unterschiedlich behandelt werden: für jeden gültigen Wert eine Klasse, eine Klasse für alle ungültigen Werte
- Eine Bedingung, die erfüllt werden muss: eine Klasse für Werte, die die Bedingung erfüllen und deren Komplement
- Grenzwertanalyse: Erweiterung und Verbesserung der funktionalen Aquivalenzklassenbildung durch Test mit Werten, die am Rand einer Klasse liegen → Erfahrung sagt, dass mit Grenzwerten Fehler besonders effektiv entdeckt werden
Test von Zustandsautomaten:
- Idee: Software ist als Menge von Zuständen und Übergängen modelliert → min. Teststrategie: jeder Übergang ist min. einmal abzudecken
- Überdeckung aller Übergänge garantiert keinen vollständigen Test → vgl. Zweigüberdeckung
Bewertung:
- Gut für Klassen, falls Objektlebenszyklus bekannt
- Gut geeignet, falls Spezifikation als Zustandsautomat vorliegt
Test von GUI-Komponenten und anderen ereignisbasierten Teilen:
- Ereigniskonzept als Kommunikationsebene, modelliert Nebenläufigkeit
- Auslösung durch man. Nutzerinteraktion → Automatisierung problematisch, mgl: manuelles Feuern von Events im Testcode
- Testfall simuliert speziellen Anwendungsfall in speziellem Programmzustand mit eingeschränkten funktionellen Möglichkeiten
- → Zustandsdiagramm → Generierung von Testfällen nach dieser Strukturierung (oft hierarchisch)
- Planung von GUI-Tests:
- Ermittlung der primitiven Operationen (1-zu-1 zu direkten Mausaktionen)
- Unter diesen die Expansionsoperatoren (z. B. Pull-down) ermitteln
- Konstruktion eines Zwischenoperators für jeden Interaktionsop. (z. B. für Edit: Cut, Paste → Edit + Cut und Edit + Paste)
- Unter diesen abstrakte Operatoren ermitteln, die GUI-Operation monopolisieren (Modaldialoge)
- Identifikation gemeinsamer Teilaktionen, da hierfür nur einmal Testfälle erforderlich sind
- Planung der Testfälle, zuerst höherwertige, abstrakte Op., danach schrittweise Verfeinerung
Testen von Klassen
Klasse = kleinste sinnvolle Testeinheit im OOP-Bereich
Besonderheiten:
- Wiederverwendbarkeitskonzept: Allgemeinheit von K führt zu vielen Testfällen
- Vererbung von Attributen und Methoden: Eliminierung von Redundanz vs. zusätzlichen Abhängigkeiten
- Polymorphismus, dynamisches Binden: Test jeder möglichen Bindung erforderlich
- Unterscheidung: normale K, abstrakte K, parametrisierte K
Testen normaler Klassen:
- Erzeugung einer Instanz der zu testenden Klasse
- Überprüfung jeder Op. für sich; zuerst die, die Zustand nicht ändern
- Test jeder Folge abhängiger Operationen
- Simulation von allen Objektausprägungen (bzw. Äquivalenzklassen) durch Testfälle
- Bei Objektlebenszyklus Zustands- bzw. Zustandsüberdeckungstests
- Testüberdeckung überprüfen (klassisch, w.o.), ggf. zusätzliche Testfälle hinzufügen
Testen abstrakter Klassen:
- Umwandlung in konkrete Klasse, Umwandlung abstrakter Operationen durch leere oder spezifikationsgemäße Implementierung
Testen parametrisierter Klassen:
- Einfache konkrete Klasse erzeugen, Testdaten so wählen, dass Test möglichst einfach wird
Testen von Unterklassen (erbenden Klassen):
- Neuer Kontext erfordert erneuten Test aller geerbten Operationen
- Überschriebene Operationen brauchen neue strukturelle Testfälle
- Überschriebene Operationen müssen alten Testfällen genügen und durch neue ergänzt werden (Test der neuen Semantik!)