1 / 59

Grundlagen der Informatik 1

Grundlagen der Informatik 1. Thema 19: Testverfahren. Prof. Dr. Max Mühlhäuser Dr. Guido Rößling. Inhaltsverzeichnis. Einführung in die Qualitätssicherung Design by Contract Strukturelle und funktionale Testmethoden. Qualitätssicherung: Motivation.

leland
Download Presentation

Grundlagen der Informatik 1

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Grundlagen der Informatik 1 Thema 19: Testverfahren Prof. Dr. Max Mühlhäuser Dr. Guido Rößling

  2. Inhaltsverzeichnis • Einführung in die Qualitätssicherung • Design byContract • Strukturelle und funktionale Testmethoden

  3. Qualitätssicherung: Motivation Dieser Code in java.util.Arrays hatte 9 Jahre einen Bug: publicstaticintbinarySearch(int[] a, int key) { int low = 0; int high = a.length - 1; while (low <= high) { int mid = (low + high) / 2; intmidVal = a[mid]; if (midVal < key) low = mid + 1; else if (midVal > key) high = mid - 1; else return mid; // key found } return -(low + 1); // key not found. }

  4. Qualitätssicherung: Motivation Informatik-Katastrophen • Röntgengerät Therac-25 (1985-1987) • Inkorrekte Dosierung, unklare Fehlermeldung und manuelle Kontrollmöglichkeit („manualoverride“) • Mehrere Patienten wurden verletzt oder starben • Ariane Flug 501 (1996, $500.000.000) • Verlust von Rakete und Satellit • Überlauf beim Konvertieren einer double nach short • Die „Rakete war zu schnell“ • AT&T Telefonnetz (1990) • Kettenreaktion durch zu schnelles „ping“ nach Neustart von Switches • Airbus Crash 1993 • Bodenkontakt bei Landung von Software nicht erkannt, daher zu spätes Bremsen • viele, viele mehr...

  5. Definition ok Design Entfernung von Fehlern ok Implemen-tierung ok Qualitätssicherung Zwei komplementäre Ansätze • Konstruktiver Ansatz • Ziel: fehlerfrei durch Konstruktion • z.B. Funktionskomposition • Analytischer Ansatz • Ziel: Fehlerfreiheit nachweisen bzw. vorhandene Fehler finden • Überprüfen des Produkts, z.B. mit • Konsistenzchecks • Vergleich mit der Spezifikation • Validierung durch den Kunden

  6. Warum wir analysieren müssen... • Solange Software von Menschen erstellt wird, wird sie auch fehlerhaft sein. • Fehler zu machen ist menschlich… • Fehler müssen gefunden werden, bevor sie Folgen haben Wo sind meine Krawattennadeln? Hunger!

  7. Wie intensiv müssen wir analysieren? • Wie kann man gründlich suchen? • Ab wann kann man davon ausgehen, dass mit hoher Wahrscheinlichkeit keine Fehler mehr vorhanden sind? Habe ich jetzt alle? Wird´s bald?!

  8. Was ist die Aufgabe der Analyse? • Nur das Aufspüren von Fehlern! • Die Ursachenforschung und die letztendliche Beseitigung (Debugging) ist eine andere Disziplin. Irgendwo ist noch eine! Und jetzt? 

  9. Spektrum der Fehler & Analyseansätze • Mögliches Spektrum der Fehler • nicht dramatisch: Klienten sind an niedrige Qualität gewöhnt • ungewollt: Klienten können verloren gehen • nichttolerierbar: können Schaden anrichten • Abhängig von der Notwendigkeit Fehler zu vermeiden werden verschiedene Qualitätssicherheitsmethoden eingesetzt. • Formale • Empirische

  10. Verschiedene Ansätze  Hypothese • Mathematiker: 3 OK, 5 OK, 7 OK; über Induktion folgt, dass alle ungerade Zahlen prim sind. • Physiker: 3 OK, 5 OK, 7 OK, 9 Messfehler, 11 OK, 13 OK, … • Ingenieur: 3 ist eine Primzahl, 5 ist eine Primzahl, 7 ist eine Primzahl, 9 ist eine Primzahl, 11 ist eine Primzahl, … • Informatiker: 112 ist eine Primzahl, 1012 ist eine Primzahl, 1112 ist eine Primzahl, … "Alle ungeraden Zahlen größer 1 sind Primzahlen" Vorsicht!Dies ist nur Satire. 

  11. Qualitätssicherungsmethoden z.B. Java Compiler: analysiert, ob Variablen initialisiert sind und ob return Anweisungen vorhanden sind.

  12. Qualitätssicherungsbegriffe • Verifikation: „Bauen wir die Software richtig?“ • Beweis, dass ein Produkt im Sinne der Spezifikation korrekt ist(funktionaler Test als grobe Annäherung) • Validierung: „Bauen wir die richtige Software?“ • Nachweis, dass ein Produkt in einer bestimmten Zielumgebung lauffähig ist und das tut, was der Benutzer wünscht • Ein verifiziertes Programm muss nicht den Wünschen entsprechen • Ein validiertes Programm muss nicht korrekt im Sinn der Spezifikation sein

  13. Das Analysedilemma Ansätze in umgekehrter Reihenfolge der Strenge • Nicht systematische „Methoden" sind nicht akzeptabel • „Überprüfen hier und da" (ad-hoc testing) ist nichtgeeignet, um genügendZuversichtzu gewinnen. • Systematisches Testen (coveragetesting) könnte ausreichend sein, kann aber die Abwesenheit von Schlupflöchern nicht garantieren. • Formale Verifikation (formal verification) könnte die absolute Korrektheit garantieren, aber… Testen kann nur die Gegenwart von Fehlern zeigen, aber niemals deren Abwesenheit. (Dijkstras Gesetz) Beware of bugs in the above code; I have only proved it correct, not actually tried it. (Donald Knuth)

  14. Das Analysedilemma If something can go wrong, it will— at the worst possible moment. If nothing can go wrong, it still will. If nothing has gone wrong, you have overlooked something. Murphy‘s Law Blinn‘s These: Jedes funktionierende Computergrafik- programm enthält eine gerade Anzahl von Vorzeichenfehlern

  15. Zeit Wert & Kosten des Testens • Entdeckungsrate • Aufspüren von Fehlern wird immer schwieriger mit der Zeit • Tests / Gefundene Fehler • Testen immer aufwändiger • Fehlerqualität • Fehler immer hartnäckiger • Kombination • Kosten pro gefundenen Fehler steigen überproportional • Aufhören, wenn es zu schwierig/ teuer wird, weitere Fehler zu finden?

  16. Notwendigkeit einer Systematik • In der Praxis gibt es folgende (nicht zufrieden stellende) Gründe mit dem Testen aufzuhören: • Zeit aufgebraucht – der Kunde möchte das Produkt • Alle vorhandenen Tests werden bestanden • Wir brauchen objektive Kriterien, ob noch zusätzliche Testfälle benötigt werden  Testmethoden • Das praktische Testen mit JUnit haben wir schon betrachtet

  17. Inhaltsverzeichnis • Einführung in die Qualitätssicherung • Design byContract • Strukturelle und funktionale Testmethoden

  18. Design byContract (Entwurf gemäß Vertrag) Wir erinnern uns: • Wir hatten Kontrakte schon bei Scheme benutzt • Definieren einen Kontrakt für jede Funktion oder bzw. hier Operation • Teilnehmer des Kontrakts: aufrufende und aufgerufene Klasse • Kontrakt bedeutet Vorteile und Verpflichtungen für beide Seiten • “Wenn du mir versprichst, op mit erfüllter vorbed aufzurufen, • dann verspreche ich im Gegenzug einen • Endzustand zurückzuliefern, in dem nachbed erfüllt ist.”

  19. Design by Contract • Ein Kontrakt besteht aus: • Vorbedingung: vor der Ausführung eine bestimmten Operation • Nachbedingung: nach dem Ausführen einer bestimmten Operation • InterneInvarianten: in einem Bereich (in einer Methode) • Kontrollflussinvarianten: ein bestimmter Kontrollfluss muss / darf nicht betreten werden • Klasseninvarianten: immer wahr vor und nach jeder Operation • Aber nicht unbedingt während sich das Objekt in Transition befindet • Effektbeschreibung: Beschreibt die Semantik der Operation und ihre (Seiten-)Effekte

  20. Design by Contract • Vergleich Scheme und Java • In Scheme mussten wir Argumenttypen überprüfen • In Java müssen wir Argumenttypen nur in wenigen Fällen prüfen • z.B. ein Object[]-Feld, in dem nur bestimmte Subtypen von Object in dem Feld erwartet werden • Design-by-Contract und OOP • Die Methoden von Subtypen erben die Kontrakte der Methode des Supertyps. • Haben gleiche Vor- und Nachbedingungen • Können stärkere Vor- und Nachbedingungen haben • Werfen die selben Ausnahmen • Können weiter spezialisierte Ausnahmen werfen

  21. Assertions (Zusicherungen) • Das assert Schlüsselwort ist eine einfache Sprachunterstützung für Design byContract in Java seit Java 1.4 • Wir können Assertions verwenden, um • die Benutzung der Objektschnittstelle einzuschränken • Den inneren Zustand eines Objekts einzuschränken • Assertions haben folgende Form: assertbooleanExpression [: Expression]; • WennbooleanExpressiontrue ist, wird das Programm normal weiter ausgeführt. Andernfalls wird ein AssertionError geworfen. • Expression ist ein optionaler Ausdruck, der zur Laufzeit ausgewertet und mit der Fehlernachricht zusammen ausgegeben wird. • Die AssertionError Klasse ist ein Subtyp der Error Klasse. Ähnlich der RuntimeException muss diese nicht gefangen und auch nicht deklariert werden. • Im Normalfall sind Assertions deaktiviert, man kann sie aktivieren über:> java –ea <classfilename>

  22. Assertions verwenden • assert wird benutzt, um folgendes auszudrücken: • Vor- und Nachbedingungen, • Interne Invarianten, • Kontrollflussinvarianten, • Klasseninvarianten • In folgenden Fällen ist Vorsicht geboten: • Verwenden Sie keineAssertions für das Prüfen von Argumenten in öffentlichen Methoden • Verwenden Sie keineAssertions, um bestimmte Aufgaben durchzuführen, die das Programm für eine korrekte Ausführung benötigt • Die Zusicherung wird nur ausgewertet, falls sie aktiviert ist! • Assertions sollten keine Seiteneffekte auf die normale Programmausführung haben

  23. Assertions für Vorbedingungen verwenden • Eine Ausnahme bei den Vorbedingungen für öffentliche Methoden: • Verwenden Sie keineAssertions für das Prüfen von Argumenten in öffentlichen Methoden  Die veröffentlichte Spezifikation (oder Kontrakt) muss immer eingehalten werden  Die allgemeingültige Konvention ist, eine entsprechende Laufzeit-Ausnahme zu verwenden: meist eine IllegalArgumentException • Vorbedingungen für private Methoden: publicvoid setAttr(int attr) { if (attr <= 0 || attr > MAX_VALUE) thrownewIllegalArgumentException("illegal value:"+attr); attribute = attr; } privatevoid setAttr(int attr) { assert attr > 0 && attr <= MAX_VALUE: "value for attr is not in interval:"+attr; attribute = attr; }

  24. Assertions für Nachbedingungen verwenden • Nachbedingungen sowohl für private als auch für öffentliche Methoden: publicString reverse(String oldStr) { String newStr = ""; // verschiebe in umgekehrter Reihenfolge//jeden char des alten in den neuen String assert oldStr.equals("") : "oldStr must be empty"; return newStr; }

  25. Assertions verwenden • Aussagen über interne Invarianten: • Aussagen über Kontrollflussinvarianten: if (i % 3 == 0) { ... } elseif (i % 3 == 1) { ... } else { asserti % 3 == 2 : i; ... } Muss nur im else-Block erfüllt sein voidfoo() { for (...) { if (...) return; // sollteirgendwannzutreffen } assert false : "Execution should never reach this point!" } Schlägt immer fehl, wenn erreicht!

  26. Assertions für Klasseninvarianten/Effektbeschreibungen verwenden • Eine Klasseninvariante ist eine besondere Aussage, die für jede Instanz der Klasse zu jeder Zeit gilt • Außer die Instanz befindet sich gerade in Überführung von einem konsistenten Zustand zum nächsten • Beziehung über mehrere Attribute • Sollte vor und nach jedem Methodenaufruf wahr sein • Jedeöffentliche Methode und jeder Konstruktor enthält eine Assertion unmittelbar vor dem Rücksprung (bei jedem „Austrittspunkt“)

  27. Assertions für Klasseninvarianten/Effektbeschreibungen verwenden • In Java benutzen wir JavaDoc, um Effektezu beschreiben: /** * Erh&ouml;ht den counter Feld um den Wert des step-Parameters. * <p>Effekte: der counter wird geändert.</p> * @param step Wert, um den der Z&auml;hlererh&ouml;ht werden soll. * @return Gibt den aktuellen Wert der counter-Variable zur&uuml;ck. */ publicint inc(int step) { counter += step; returncounter; }

  28. Komplexe Assertions • Wir verwenden innere Klassen für komplexe Assertions: void foo(finalint[] array) { // Innere Klasse sichert den Zustand und fuehrtendgueltige // Konsistenzpruefung durch class DataCopy { privateint[] arrayCopy; DataCopy() { arrayCopy = (int[]) array.clone(); } boolean isConsistent() { return Arrays.equals(array, arrayCopy); } } DataCopy copy = null; // Immer erfuellt; speichert als Seiteneffekt eine Kopie des Felds assert ((copy = new DataCopy()) != null); ... // Manipulieren des Felds // Stellt sicher, dass das Feld immer noch gleich aussieht assert copy.isConsistent(); } Die Kopie wird nur durchgeführt, wenn Assertions aktiviert sind

  29. Design byContract zusammengefasst • Möglichkeiten: • Vereinfachung: Wir definieren ein Korrektheitskriterium nur für einen bestimmten Teil des Programms. • Erwartung: Solange alle Teile des Programm die Kontrakte erfüllen, wird das Programm (fast) korrekt funktionieren. • Hoffnung: Wenn ein Fehler auftritt, dann können wir diesen durch eine Verletzung eines Kontrakts aufspüren. • Einschränkungen: • Auch wenn jeder Kontrakt erfüllt ist, kann es sein, dass das Programm nicht richtig funktioniert • Ein Kontrakt kann semantisch falsch sein • Wir haben vergessen, eine bestimmte Bedingung im Kontrakt anzugeben. Wir brauchen andere Herangehensweisen, um diese Fälle abzufangen!

  30. Inhaltsverzeichnis • Einführung in die Qualitätssicherung • Design byContract • Strukturelle und funktionale Testmethoden

  31. Testmethode Im Allgemeinen eine systematische Methode zur Auswahl und/oder Generierung von Tests. • Strukturelle Testmethoden • Funktionale Testmethoden Planmäßiges, auf einem Regelwerk aufbauendes Testverfahren. Testverfahren sind nur mit entsprechender Werkzeugunterstützung sinnvoll anwendbar.

  32. Grundbegriffe • Testdatum • Eingabewert, der einen Eingabeparameter oder eine Eingabevariable des Testobjekts mit einem Datum versorgt. • Testfall • Ein Satz von Testdaten, der die vollständige Ausführung eines zu testenden Programms bewirkt • sowie das Sollresultat. • Testsuite • Eine nicht-leere Menge von Testfällen, die nach einem bestimmten Kriterium ausgewählt wurden. • Testtreiber • Handelt es sich bei dem Prüfling um eine Operation in einer Klasse, dann kann sie nicht direkt getestet werden. • Der Tester muss für die jeweilige Klasse einen Testrahmen programmieren, der ein interaktives Aufrufen der Operationen ermöglicht.

  33. Grundbegriffe: Instrumentierung • Schlägt ein Testfall fehl, muss man nachvollziehen, welche Anweisungen des Testobjekts mit dem Testfall durchgeführt wurden  Fehler lokalisieren • Werkzeugunterstütztes Mitprotokollieren, welche Teile des Prüflings bei der Ausführung durchlaufen wurden • Nach dem Testlauf werden die Zählerstände ausgewertet. int maximum(inta, intb) { if(a > b) { thenBranch = true; returna; } else { elseBranch = true; returnb; } } In den Quellcode eingefügte Zähler In den Quellcode eingefügte Zähler

  34. Grundbegriffe: Testabdeckung • Testabdeckung: Verhältnis zwischen tatsächlich ausgeführten Testfällen und theoretisch existierenden Testfällen ausgeführte Testfälle existierende Testfälle • Bei einer Testabdeckung von 100% spricht man von einem erschöpfendem Test • Erschöpfendes Testen ist meist weder praktikabel noch sinnvoll • Testende-Kriterium • legt fest, welches Minimalziel durch die Testfälle erreicht werden soll TAB = Kriterium für die Auswahl von Testfällen!

  35. Testmethoden • Strukturelle Testmethoden:basieren auf der Programmstruktur (White-Box Tests) • Testfälle werden nur aus der Programmstruktur abgeleitet • Die Vollständigkeit der Prüfung wird anhand von Strukturelementen (Anweisungen, Zweige, Daten) des Prüfgegenstands bewertet • Die Spezifikation des Prüfgegenstands wird bei der Beurteilung der Vollständigkeit der Tests nicht beachtet • Funktionale Methoden: Basieren auf den Anforderungen(Black Box Tests) • Im Idealfall werden die Anforderungen in einer formellen Spezifikation ausgedrückt • Testfälle und Testdaten werden aus der funktionalen Spezifikation des Prüfgegenstands abgeleitet • Vollständigkeit der Prüfung wird anhand der Spezifikation bewertet • Struktur des Prüfgegenstands wird nicht ausgewertet

  36. Black Box funktionalesTesten Benutzungs-fälle überprüfen Zufallstest Grey Box Äquivalenz-klassenbildung Grenzwert-analyse Theoretisch reine „BlackBox“ Verfahren. In der Praxis auch Heranziehen der Struktur. White Box strukturellesTesten datenfluss-orientierte Testverfahren kontrollfluss-orientierte Testverfahren Testmethoden Überblick Klassifikation nach benötigter Information

  37. Kontrollflussgraphen • Kontrollflussgraph wirddurch einen gerichteten Graphen dargestellt • Jeder Knoten stellt eine Anweisung dar • Die Knoten sind durch gerichtete Kanten verbunden • Die Anzahl ausgehender Kanten eines Knotens heißt Ausgangsgrad • Kantenfolgen beschreiben einen möglichen Kontrollfluss von Knoten i zu Knoten j • Zweige • Gerichtete Kanten • Pfad • Folge von Knoten und Kanten, die mit dem Startknoten beginnt und mit einem Endknoten endet

  38. Kontrollflussgraphen • Kontrollflussgraphen besitzen grundsätzlich einen Start- und einen Endknoten • Der Endknotenhat den Ausgangsgrad0 • Jeder normale Knoten liegt auf einem Pfad vom Startknoten zum Endknoten • Knoten mit Ausgangsgrad 1 heißen Anweisungsknoten • Alle anderen Knoten außer dem Endknoten heißen Prädikatknoten

  39. nstart nende Kontrollflussgraphen (Beispiel) n2 c = System.in.read(); // n1 while (c >= 'A' && c <= 'Z' && totalNumber<5) { // n2 totalNumber = totalNumber + 1; // n3 if (c=='A'||c=='E'||c=='I'||c=='O'||c=='U') { // n4 vowelNumber = vowelNumber + 1; // n5 } c = System.in.read(); // n6 } n2 n3 n4 n5 n6

  40. Überdeckungstestverfahren • Strukturelemente wie Anweisungen, Zweige oder Bedingungen werden genutzt, um Testziele zu definieren • Beispiel: Das Anweisungsüberdeckungstestverfahren hat als Ziel, Testdaten so zu wählen, dass alle Anweisungen im Programm ausgeführt werden • Realisierung von Überdeckungstests • Quellcode wird instrumentiert • Bei der Ausführung erzeugen die Trace Statements ein Logbuch • Auswertung des Logbuchs zur Erstellung eines Überdeckungsberichts

  41. Pfadüberdeckung Bedingungsüberdeckungmehrfach Zweigüberdeckung Überdeckungstests Übersicht... Bedingungsüberdeckungeinfach Anweisungsüberdeckung A B  A impliziert B

  42. nstart n1 n1 n2 n2 n3 n3 n4 n4 n5 n5 n6 n6 nende Anweisungsüberdeckung (C0) • Ziel: Mit einer Anzahl von Testfällen alle vorhandenen Anweisungen auszuführen • Beispiel eines Testfalls, der das Kriterium erfüllt • Eingabe: <'A', '#'> • Hilft, toten Code zu finden • Ist notwendig aber nicht ausreichend • Besitzt wenig praktische Relevanz

  43. Anzahl der ausgeführten Zweige Czweig = Anzahl der vorhandenen Zweige Zweigüberdeckung (C1-Test) • Ziel: Die Ausführung aller Zweige, d.h. aller Kanten des Kontrollflussgraphen • Wird auch Entscheidungsüberdeckung genannt: Jede Entscheidung muss mindestens einmal die Wahrheitswerte wahr und falsch annehmen. • Metrik: • Hilft, nicht erreichbare Verzweigungen zu finden • Anweisungsüberdeckung vollständig enthalten • Betrachtet weder Kombination von Verzweigungen noch komplexe Bedingungen • Gilt als das minimale Testkriterium

  44. nstart nstart n1 n n1 n2 n n2 n3 n n3 n4 n4 n5 n n5 n6 n6 nend nend Zweigüberdeckung (C1): Beispiel • <'B','#'> • <'A','#'>

  45. Einfache Bedingungsüberdeckung (C2) nstart alle atomaren Bedingungen mind. einmal true & false • Testfälle • <'A', 'E', 'I', 'O', 'U', '@'> <'€‘> • Enthält weder Anweisungs- noch Zweigüberdeckung • Da beides minimale Testkriterien sind, ist eine alleinige einfache Bedingungsüberdeckung nicht ausreichend n1 n1 n2 n2 n3 n3 n4 n4 n5 n5 if (c=='A' || c=='E' || c=='I' || c=='O' || c=='U') n6 n6 Der „else“ Zweig wird nie beschritten nende

  46. Mehrfache Bedingungsüberdeckung nstart Alle Kombinationen von atomaren Bedingungen abdecken • Testfälle • <'A', 'E', 'I', 'O', 'U', '@'> <'A', 'E', 'I', 'O', 'U', '€'> <'A', 'E', 'I', 'O', 'U', 'A'> <'A', '@'>, <'A', '€'> • Zweigüberdeckung enthalten • Kombinationsexplosion: • N atomare Bedingungen 2N Möglichkeiten • Kombinationen teilweise unmöglich! • Auswertung wird eventuell abgebrochen (Lazy-Evaluation = nicht-strikte Auswertung) n1 n1 n2 n2 n3 n3 n4 n4 n5 n5 n6 n6 nende

  47. Pfadüberdeckung (C7) nstart Alle Kombinationen von Zweigen abdecken • Testfälle • <'#'>, <'B', '#'>, <'A', '#'> <'A', 'B', 'B', 'B', 'B'> <'B', 'A', 'B', 'B', 'B'>, … • Zweigüberdeckung enthalten • Schleifen führen praktisch zu unendlichen vielen Testfällen • Höchste Erfolgsaussichten, aber völlig unpraktikabel n1 n1 n2 n2 n3 n3 n4 n4 n5 n5 n6 n6 nende

  48. Überdeckungstests Vorteile • Defizite in der Teststrategie aufdecken • Nicht erreichbaren Code entdecken • Anhaltspunkt für den Testfortschritt Nachteile • 100% Abdeckung nicht praktikabel • Codeabdeckung ist kein Kriterium für vollständiges Testen • Fehlende Funktionalität wird nicht erkannt Produkt wird gegen sich selbst geprüft

  49. Funktionales Testen • Motivation: Es ist unzureichend, ein Programm lediglich gegen sich selbst zu testen  Testfälle aus Programmspezifikation ableiten • Programmstruktur wird nichtbetrachtet Ziel • Möglichst umfassende, aber redundanzarme Prüfung der spezifizierten Funktionalität • Überprüfung aller Programmfunktionen(Funktionsüberdeckung)

  50. Funktionales Testen • Hauptschwierigkeiten • Ableitung der geeigneten Testfälle • Vollständiger Funktionstest ist im allgemeinen nicht durchführbar • Ziel der Testplanung • Testfälle so auswählen, dass die Wahrscheinlichkeit groß ist, Fehler zu finden • Testfallbestimmung • Funktionale Äquivalenzklassenbildung • Grenzwertanalyse

More Related