3: Systematisches Testen



Ähnliche Dokumente
3: Systematisches Testen

6 Systematisches Testen von Programmen

Qualitätssicherung von Software (SWQS)

zu große Programme (Bildschirmseite!) zerlegen in (weitgehend) unabhängige Einheiten: Unterprogramme

Qualitätssicherung von Software

Excel VBA. Teil Zusammenfassung! Was wir können sollten! V

zu große Programme (Bildschirmseite!) zerlegen in (weitgehend) unabhängige Einheiten: Unterprogramme

Programmierkurs Python I

Software-Test: Funktionstest

Techniken im Software-Test

Testen und Debugging

Array-Zuweisungen. Array-Zuweisungen können über die Position, den Namen oder gemischt erfolgen.

Software-Test: Strukturtest

8 Zugriffstypen ( Zeiger )

Steuerung von Programmabläufen. Vorlesung Computergestützte Mathematik zur Linearen Algebra. Lehrstuhl für Angewandte Mathematik Sommersemester 2009

Java Einführung ABLAUFSTEUERUNG Kapitel 3 und 4

Java 8. Elmar Fuchs Grundlagen Programmierung. 1. Ausgabe, Oktober 2014 JAV8

White-Box-Test. Black-Box-Test. Testen. Testen. Vorlesung Methoden des Software Engineering. Martin Wirsing. Einheit D.2,

Funktionen. Überblick über Stored Functions. Syntax zum Schreiben einer Funktion. Schreiben einer Funktion

C.3 Funktionen und Prozeduren

ECDL MODUL COMPUTING. Syllabus Version 1.0

Unterprogramme. Komplexes Verhalten kann modular mit Hilfe von Unterprogrammen beschrieben werden Es gibt zwei Arten von Unterprogrammen:

Programmieren I. Martin Schultheiß. Hochschule Darmstadt Wintersemester 2010/2011

Vorsemesterkurs Informatik Sommersemester Aufgabenblatt Nr. 5A. Lösung zu Aufgabe 1 (Fehler in Haskell-Quelltext: Parsefehler)

Algorithmen und Datenstrukturen 2. Stefan Florian Palkovits, BSc Juni 2016

Beispiel 1 zur Verifikation eines bedingten Anweisung. Hoare-Regel für die bedingte Anweisung. else

Qualität von Software - Prof. Schlingloff, Lackner - SS2013 DYNAMISCHER TEST. Whitebox Testen mit JUnit

Testen mit Use Cases. Chris Rupp Dr. Stefan Queins

Software Engineering

Arrays. Arrays werden verwendet, wenn viele Variablen benötigt werden. Der Vorteil in Arrays liegt darin, dass man nur eine Variable deklarieren muss

Aufbau eines dynamischen ETL Frameworks auf Basis eines PL/SQL Codegenerators

Praktikum Ingenieurinformatik. Termin 4. Funktionen, numerische Integration

ASIL-relevante SW-Module identifiziert! Was nun?

Elementare Konzepte von

Programmierkurs Java

Beispiel 1 zur Verifikation eines bedingten Anweisung. Hoare-Regel für die bedingte Anweisung. Beispiel 2 zur Verifikation eines bedingten Anweisung

Syntax der Sprache PASCAL

C++ Teil 2. Sven Groß. 16. Apr IGPM, RWTH Aachen. Sven Groß (IGPM, RWTH Aachen) C++ Teil Apr / 22

Theoretische Informatik SS 03 Übung 3

Grundlagen der Programmierung (Vorlesung 15)

Wiederholung. Testen. Tests nach Methode zum Ableiten der Testfälle White Box Test Black Box Test

Übersicht. C Ein-/Ausgabe und Kontrollanweisungen. I/O-Funktionen aus stdio. printf() Ein-/Ausgabe. Kontrollanweisungen.

Test-Suite Beurteilung

FACHHOCHSCHULE AUGSBURG Hochschule für Technik, Wirtschaft und Gestaltung

Einstieg in die Informatik mit Java

5.3 Korrektheit und Verifikation

4.Grundsätzliche Programmentwicklungsmethoden

Heap vs. Stack vs. statisch. 6 Speicherorganisation. Beispiel Statische Variablen. Statische Variablen

5.3 Korrektheit und Verifikation

6 Speicherorganisation

Heap vs. Stack vs. statisch. 6 Speicherorganisation. Beispiel Statische Variablen. Statische Variablen

Automatische Testfallgenerierung für den Systemtest. 1/5

Informatik I Übung, Woche 40

Tableaukalkül für Aussagenlogik

5. Algorithmen. K. Bothe, Institut für Informatik, HU Berlin, GdP, WS 2015/16

(Aufgaben zu Wertzuweisungen siehe Vorlesungsbeilage S. 49)

Algorithmen mit konstantem Platzbedarf: Die Klasse REG

Programm heute. Algorithmen und Datenstrukturen (für ET/IT) Definition Algorithmus. Wie beschreibt man Algorithmen?

Algorithmen und Datenstrukturen (für ET/IT)

Programmieren I. Kapitel 5. Kontrollfluss

Kurs 1613 Einführung in die imperative Programmierung

Musterlösung zur Vorlesung Modellbasierte Softwareentwicklung Wintersemester 2014/2015 Übungsblatt 10

Einführung in die Informatik 1

Ausführen eines Makros beim Starten von OpenOffice.org

Kapitel 5: Syntaxdiagramme und Grammatikregeln

Methoden des Software Engineering

Kontrollstrukturen -- Schleifen und Wiederholungen

Programmieren mit statistischer Software

I EINLEITUNG SYNTAX SPEZIELLE PROBLEME BEISPIEL AUSBLICK

Kapitel 9. Komplexität von Algorithmen und Sortieralgorithmen

Softwaretechnikpraktikum SS Qualitätsmanagement I. 1. Überblick. Qualität. Qualitätsmerkmal

1 Algorithmische Grundlagen

Vom Testkonzept zu JUnit

Unit Tests. Programmiermethodik. Eva Zangerle Universität Innsbruck

4. Einfache Programmstrukturen in C Einfache Programmstrukturen in C

Verwenden Sie für jede Aufgabe die C++ IDE von Eclipse (pro Aufgabe ein Projekt).

Transkript:

3: Systematisches Testen Testen ist ein Prozess, ein Programm mit der Absicht auszuführen, Fehler zu finden. Man muss destruktiv denken! Testen ist ungeeignet, die Fehlerfreiheit eines Programms nachzuweisen! Testen ist keine Form des Debuggens! Die systematische Auswahl von Testfällen ist eine schwierige kreative Arbeit. Testergebnisse sollen reproduzierbar sein. Das Durchführen von Tests kann man oft automatisieren. Und man sollte es automatisieren, wenn möglich. 150

Ich habe einen Fehler in meinem Programm gefunden. Was soll ich tun? NICHT: Den Fehler sofort beheben, den Testfall vergessen. Stattdessen: 1. Den Testfall T, der zu dem Fehler führte, schriftlich festhalten, um den Fehler reproduzieren können. ( ) 2. Den Test weiterführen und nach weiterern Fehlern suchen. 3. Den Testfall T in den Regressionstest aufnehmen! 4. Jetzt den Fehler korrigieren. 5. Anhand des Testfalls T nachprüfen, ob der Fehler tatsächlich korrigiert wurde. ( ) Leider gibt es auch Heisenbugs... 151

Kein Testen, aber auch nützlich: Untersuchung des Source-Codes Code-Inspectionen (strenge Regeln, Entscheidung über die Freigabe des Source-Codes) Eine Anomalie wie if ((options == ( WCLONE WALL)) && (current->uid = 0)) retval = -EINVAL; hat in dem Source-Code für ein sicheres System nichts zu suchen! Walk-Throughs (weniger strikte Regeln) Programming in Pairs Formale Verifikation ( in ein paar Wochen) 152

Testpsychologie Man muss die Fehler finden wollen! Idealerweise Trennung zwischen Programmautoren und Testern. Auch hilfreich: Test-Driven Developement (zuerst die Black-Box-Tests, danach die Implementation). Es ist gut, wenn ein Test einen Fehler findet. Erfolg = Fehler gefunden! 153

Regressionstest Batterie von Testfällen, die im Laufe eines Projekts wächst, weil für jeden neu nachgewiesenen Fehler ein Testfall aufgenommen wird. Möglichst viele Testfälle sollten automatisiert bearbeitet werden. Änderungen werden nur freigegeben, wenn der Regressionstest fehlschlägt (keine Fehler findet). Wird ein Fehler entdeckt, der vom Regressionstest bisher nicht gefunden wurde: Zuerst neuer Testfall für den Regressionstest. Erst dann Fehler beheben. (Das ist wichtig! Deshalb die Wiederholung des zuvor Gesagten.) Denn: Fehler kommen oft wieder! 154

Testfall Beschreibung einer Eingabe(-Bedingung) mit einem erwarteten Ergebnis Zweck Vorbedingung Erwartetes Ergebnis Aufräumarbeiten Bei der Durchführung des Tests: Vergleich des tatsächlichem mit dem Erwarteten Ergebnis, Protokollierung. Ggf. Verknüpfung mehrerer Testfälle zu einer Kette. 155

Beispiel: Wie sollte man diese Funktion testen? function Fibonacci(X: Positive) return Positive is Kind, Vater, Opa: Positive; begin if X <= 2 then return 1; else Vater := 1; Opa := 1; for Generation in 3.. X loop Kind := Vater + Opa; Opa := Vater; Vater := Kind; end loop; return Kind; end if; end Fibonacci; 156

3.1: White-Box Tests Tests, die mit Hilfe der Kenntnis eines (Unter-)Programms definiert werden, mit Hilfe des Kokntrollflussgraphen: Knoten: Ausführbare Anweisung (Zuweisung, Prozeduraufruf) zusätzlich je ein Start- und Zielknoten ggf. Zusammenfassung mehrerer zusammenhängender Anweisungen zu einem Knoten Kante: möglicher Programmfluss zwischen zwei Anweisungen Pfad: Kombination von Kanten, die vom Start- zum Zielknoten laufen 3.1: White-Box Tests 157

Kriterien für White-Box Tests Kontrollflussorientierte Tests: Anweisungsüberdeckung: Jeder Knoten des Kontrollflussgraphen wird mindestens einmal ausgeführt. Zweigabdeckung: Jede Kante des Kontrollflussgraphen wird mindestens einmal ausgeführt. Pfadabdeckung: Jeder Pfad im Kontrollflussgraphen wird mindestens einmal ausgeführt (theoretisches Kriterium, da meistens unendlich viele Pfade). Datenflussorientierte Tests (übernächste Folie) 3.1: White-Box Tests 158

Pfadabdeckung mit Schleifen Programme mit Schleifen können unendlich viele Pfade haben. Das würde undentlich viele Tests implizieren. Varianten der Pfadabdeckung mit endlich vielen Pfaden: Boundary Interior : Zwei Pfade pro Schleife: Verlassen der Schleife bei der ersten Gelegenheit (while-schleife wird keinmal durchlaufen, repeat-until-schleife wird einmal durchlaufen). Verlassen der Schleife bei der zweiten Gelegenheit (while-schleife einmal, repeat-until-schleife zweimal). Strukturierte Pfadabdeckung mit Parameter k. Für alle j {1,..., k}: Verlassen der Schleife bei der j-ten Gelegenheit. 3.1: White-Box Tests 159

Datenfluss Idee: Eine Variable V wird entweder verändert (z.b. V :=... ) oder lesend benutzt (z.b.... := V ). Daten fließen von der Veränderung zur Benutzung. Testen (Datenfluss-orientiert): Betrachte Pfade, die von einer Veränderung ohne weitere Veränderung zur Benutzung führen. 3.1: White-Box Tests 160

Datenflussorientierte Tests Unterscheide 1. def: Wertzuweisung an eine Variable 2. use: lesende Benutzung einer Variablen. Weitere Unterscheidung: 2.1 c(omputational)-use: Der Wert der Variablen ist Teil einer Berechnung 2.2 p(redicate)-use: Der Wert der Variablen beeinflusst eine Entscheidung 3.1: White-Box Tests 161

function Fibonacci(X: Positive) return Positive is Kind, Vater, Opa: Positive; begin def(x) if X <= 2 then p-use(x) return 1; else Vater := 1; def(vater) Opa := 1; def(opa) for Generation in 3..X def(generation), p-use(generation, X) loop Kind := Vater + Opa; c-use(vater, Opa), def(kind) Opa := Vater; c-use(vater), def(opa) Vater := Kind; c-use(kind), def(vater) end loop; return Kind; c-use(kind) end if; end Fibonacci; 3.1: White-Box Tests 162

Das all-defs Kriterum Für jede Variable V und jede def(v)-anweisung gibt es mindestens einen Pfad in den Testfällen, der bezüglich V definitionsfrei ist und in einer use(v)-anweisung mündet. Ein Pfad ist bezüglich V definitionsfrei, wenn auf dem Pfad keine def(v)-anweisung auftritt. Idee: Jede Variable V hat (hoffentlich!) einen semantischen Nutzen, der wenigstens in einem Testfall überprüft werden soll. 3.1: White-Box Tests 163

all-uses und weitere Kriterien all-uses: Für alle Variablen V und alle Paare (X, Y ) (X eine def(v)-anweisung und Y eine use(v)-anw.) gilt: Wenn mindestens ein bezüglich V definitionsfreier Pfad von X nach Y existiert, dann muss ein solcher Pfad in einem der Testfälle auftreten. Starkes Kriterium, aber seeeehr viele Testfälle. Sparsamer: all-p-uses (berücksichtigt nur p-use(v), ignoriert c-use) und all-c-uses (genau umgekehrt). Nicht klar was besser: all-p-uses oder all-c-uses. Künstliche Unterscheidung zw. p-use und c-use. 3.1: White-Box Tests 164

Testen: Die Praxis Verbreitet: Black-Box-Tests ( nächster Abschn.). Kontrollflussorientierte Tests oft genutzt (und z.t. vorgeschrieben) für die Entw. Sicherer Systeme. Typisches Vorgehen: Starte mit den Testfällen eines gründlich entwickelten Black-Box-Tests. Ermittle (mit Hilfe von Werkzeugen) die anfängliche Testabdeckung (bei reinen Black-Box Tests typischerweise 60 80%). Ergänze die Testfälle, um die Testabdeckung auf einen vorgegebenen Minimalwert zu bringen (typischerweise 90-95%). Datenflussorientierte Tests: theoretisches Konzept, in der Praxis (bisher?) selten, kaum Werkzeuge. 3.1: White-Box Tests 165

Mutationstesten Etwas unsystematische, aber wirkungsvolle Methode, die Vollständigkeit der Testbatterie zu testen. Grundlage: Kleine Änderungen ( Mutationen ) am Quelltext. Jeder Mutant enthält nur eine Abweichung, z.b. Ersetzen eines durch ein <, eines and durch ein or,... Vorzeichenfehler, Auskommentieren einzelner Statements, Vertauschen der Reihenfolge einzelner Statements,... Kriterium: Wenn irgend eine Mutation den Test besteht, hat man vermutlich nicht genug Testfälle, oder die falschen Testfälle. 3.1: White-Box Tests 166

3.2: Black-Box Tests Tests, die anhand der Spezifikation eines (Unter-)Programms definiert, werden, ohne das Programm selbst zu kennen. Techniken zur Erzeugung von Testfällen: Äquivalenzklassenbildung (sowohl für gültige, als auch für ungültige Eingaben) Grenzwertanalyse Beispiel: Wie testet man die ein (Unter-)Programm, das ein Datum in der Form (Tag, Monat, Jahr) einlesen und bei ungültigen Daten eine Ausnahme auslösen soll: 3.2: Black-Box Tests 167

Beispiel Kaffeeautomat package Kaffee_Automat is type Zustand is private; type Benutzer_Handlung is (Cent10, Cent20, Knopf); type Aktionen is (Muenze_Angenommen, Muenze_Abgelehnt, Alle_Muenzen_Zurueck, Gib_Kaffee_Aus); 3.2: Black-Box Tests 168

Kaffeeautomat (2) procedure Initialisiere (X: in out Zustand); procedure Agiere(X: in out Zustand; Eingabe: Benutzer_Handlung; Aktion: out Aktionen); private type Zustand is range 0.. 50; end Kaffee_Automat; 3.2: Black-Box Tests 169

Wie testen wir den Kaffeeautomaten? Spezifikationen, wie für derartige Automaten üblich. Insbesondere: Eingabe 10-Cent und 20-Cent Münzen Kaffee für 50 Cent, kein Überbezahlen Geldrückgabeknopf Gibt es Äquivalenzklassen, die wir hier nutzen können? 3.2: Black-Box Tests 170

3.3: Fallbeispiel: Fakultät Man gebe einen Black-Box-Test für die folgende Funktion an: function Fak1(N: Positive) return Positive is return N! 3.3: Fallbeispiel 171

Findet der Black-Box-Test den Fehler? function Fak2(N: Positive) return Positive is optimised variant of Fak1 begin case N is when 1 => return 1; when 2 => return 2; when 3 => return 6; when 4 => return 24; when 5 => return 120; when 6 => return 270; Error: 6!=720 when 7 => return 5040; when others => return N * Fak2(N-1); end case; end Fak2; 3.3: Fallbeispiel 172

Hier kann auch ein White-Box-Test versagen! function Fak3(N: Positive) return Positive is yet another optimised Fak1 Opt: array (Positive range 1..7) of Positive := (1,2,6,24,120,270,5040); begin if N in Opt Range then return Opt(N); else return N*Fak3(N-1); end if; end Fak3; 3.3: Fallbeispiel 173

3.4: Automatisches Testen Manuelles Testen ist arbeitsaufwändig, langweilig und... fehlerträchtig. Und wer will nach jeder (kleinen) Änderung den kompletten Regressionstrest durchführen... Um die Reproduzierbarkeit der Test zu gewährleisten, muss bei jeder Wiederholung des Tests (z.b. Regressionstest), der gleiche Input eingegeben werden. 3.4: Automatisches Testen 174

Der Test-Driver Generator testgen Ein einfach zu handhabendes Werkzeug, um Test-Driver zu erzeugen ist der Test-Driver Generator testgen (eine Weiterentwicklung von tg. Er dient als Beispiel für ein Werkzeug beim Testen. Für anspruchsvollere Aufgaben würde man z.b. AUnit verwenden. 3.4: Automatisches Testen 175

Arbeitsweise von testgen Eingabe von testgen ist ein Test-Script (z.b. beispiel.ts), Ausgabe der Quelltest eines Ada-Programms (z.b. beispiel.adb). Typische Test-Scripts bestehen aus 1. Einer globalen Kontext-Vereinbarung, bestehend aus with und use -Klauseln für Ada.Text_IO und dem getesteten Modul, und 2. einzelnen Testfällen. 3.4: Automatisches Testen 176

Die Syntax eines Test-Scripts Context with Ada.Text_IO; use Ada.Text_IO; with Datum_Manager; use Datum_Manager; ***** 30. Juni 2003 (kein Schaltjahr) Define Dat: Datum; Test Dat := Setze(30, Juni, 2003); Pass (Tag(Dat)=30) and (Monat(Dat)=Juni) and (Jahr(Dat)=2003) ***** 31. Juni 2003 (kein Schaltjahr) Define Dat: Datum; Test Dat := Setze(31, Juni, 2003); Pass exception Falsches_Datum 3.4: Automatisches Testen 177

Die Syntax eines Testfalls Testfall-Name, Define-, Test- und Pass-Vereinbarungen: ***** Mai, alle Tage, 2003 (kein Schaltjahr) Define Fehler: Natural := 0; Dat: Datum; Test for T in Tag_Typ loop Dat := Setze(T, Mai, 2003); if (Tag(Dat) /= T) or (Monat(Dat) /= Mai) or (Jahr(Dat) /= 2003) then Fehler := Fehler + 1; end if; end loop; Pass Fehler = 0 3.4: Automatisches Testen 178

Verhalten eines Test-Scripts (1) pass. (2) pass. (3) pass. (4) Februar, 1..28, 2003 (kein Schaltjahr) Script name: dat_man.ts ; Line:34... FAIL. (path => was taken, but predicate is FALSE) (5) pass. (6) pass. (7) pass. Script name dat_man.ts ; total test result: FAIL. Hurra! Der Test war erfolgreich Fehler gefunden! 3.4: Automatisches Testen 179