03 Quiz: Äquivalenzklassen
November 2025 (2629 Words, 15 Minutes)
Anleitung
- Dieser Quiz testet dein Verständnis der Kernkonzepte aus Chapter 03 (Testing Basics): Äquivalenzklassen
- Jede Frage hat 4 Optionen mit genau einer richtigen Antwort
- Versuche zunächst ohne Vorlesungsmaterialien zu antworten
- Konzentriere dich auf das Verständnis der Konzepte, nicht auf das Auswendiglernen spezifischer Zahlen oder Code
- Nimm dir Zeit für jede Frage
Frage 1: Definition von Äquivalenzklassen
Was ist der Hauptzweck der Äquivalenzklassen-Partitionierung beim Testen?
A) Jeden möglichen Eingabewert erschöpfend zu testen
B) Ähnliche Eingaben zu gruppieren, die die gleiche Verhaltenskategorie erzeugen, und einen Vertreter aus jeder Gruppe zu testen
C) Sich nur auf Grenzwerte zwischen Eingabebereichen zu konzentrieren
D) Die Notwendigkeit von Tests durch mathematischen Beweis der Korrektheit zu eliminieren
Antwort anzeigen
Richtige Antwort: B
Die Äquivalenzklassen-Partitionierung gruppiert Eingaben, die auf die gleiche Weise von der Funktion verarbeitet werden und die gleiche Kategorie von Ausgabe oder Verhalten erzeugen. Durch das Testen eines Vertreters aus jeder Gruppe erreichen wir hohe Testabdeckung ohne erschöpfendes Testen. Option A ist unmöglich (32 Milliarden Jahre!), C beschreibt Grenzwertanalyse (eine andere Technik), und D ist für die meiste reale Software nicht erreichbar.
Frage 2: Schlüsseleigenschaften von Äquivalenzklassen
Welche der folgenden ist KEINE erforderliche Eigenschaft von Äquivalenzklassen?
A) Disjunkt - jede Eingabe gehört zu genau einer Äquivalenzklasse
B) Vollständig - jede mögliche Eingabe gehört zu einer Äquivalenzklasse
C) Repräsentativ - teste einen Wert aus jeder Klasse statt aller Werte
D) Geordnet - Äquivalenzklassen müssen in einer bestimmten Reihenfolge getestet werden
Antwort anzeigen
Richtige Antwort: D
Äquivalenzklassen müssen nicht in einer bestimmten Reihenfolge getestet werden. Die drei erforderlichen Eigenschaften sind: disjunkt (keine Überlappung zwischen Klassen), vollständig (alle Eingaben werden abgedeckt) und repräsentatives Testen (ein Wert pro Klasse). Die Reihenfolge der Tests beeinflusst nicht die Gültigkeit der Äquivalenzklassen-Partition.
Frage 3: Ausgabekategorien bestimmen Eingabeklassen
Für die Funktion reciprocal_sum(x, y, z) = 1/(x+y+z), wie viele Äquivalenzklassen gibt es?
A) 27 Klassen (3 Parameter × 3 mögliche Vorzeichen = 3³)
B) 9 Klassen (3 Parameter × 3 mögliche Werte)
C) 3 Klassen (basierend auf dem Vorzeichen der Summe: positiv, negativ oder null)
D) Unendlich viele Klassen (weil Eingaben kontinuierliche Floats sind)
Antwort anzeigen
Richtige Antwort: C
Obwohl die Funktion 3 Parameter hat, gibt es nur 3 Äquivalenzklassen! Die wichtigste Erkenntnis aus White-Box-Testing ist, dass die Funktion zuerst total = x + y + z berechnet und dann 1/total zurückgibt. Was zählt ist die Summe, nicht die einzelnen Parameterwerte. Die drei Ausgabekategorien sind: positives Ergebnis (Summe > 0), negatives Ergebnis (Summe < 0) und Fehler (Summe ≈ 0). Dies ist ein kritisches Konzept: Ausgabekategorien bestimmen Eingabeklassen, nicht die Anzahl der Eingabeparameter.
Frage 4: White-Box vs. Black-Box Testing
Wie hilft White-Box-Testing beim Finden von Äquivalenzklassen?
A) Es eliminiert die Notwendigkeit von Äquivalenzklassen vollständig
B) Es ermöglicht dir, die Implementierung zu sehen und zu identifizieren, was die Ausgabe bestimmt (z.B. dass reciprocal_sum zuerst x+y+z berechnet)
C) Es erfordert das Testen aller möglichen Eingabekombinationen
D) Es funktioniert nur bei Funktionen mit weniger als 3 Parametern
Antwort anzeigen
Richtige Antwort: B
White-Box-Testing bedeutet, dass du den Implementierungscode sehen kannst. Dies zeigt genau, was das Verhalten der Funktion bestimmt. Zum Beispiel zeigt dir das Sehen von total = x + y + z in reciprocal_sum sofort, dass die Summe wichtig ist, nicht die einzelnen Parameterwerte. Dies macht das Finden von Äquivalenzklassen einfacher und genauer als Black-Box-Testing, wo du basierend auf der Funktionssignatur und Dokumentation raten müsstest.
Frage 5: Granularität von Partitionen
Für reciprocal(x) = 1/x könntest du 2 Klassen (nicht-null, null) oder 3 Klassen (positiv, negativ, null) wählen. Was bestimmt, welche besser ist?
A) Die 3-Klassen-Partition ist immer mathematisch korrekt; die 2-Klassen-Partition ist falsch
B) Die Anzahl der Eingabeparameter bestimmt die Anzahl der Klassen
C) Es ist ein Kompromiss basierend auf Code-Pfaden, mathematischer Bedeutung, Bug-Risiko und Fehlerkosten
D) Du musst immer die Partition mit den meisten Klassen wählen für maximale Abdeckung
Antwort anzeigen
Richtige Antwort: C
Beide Partitionen sind mathematisch gültig! Die Wahl hängt von deinen Testzielen ab. Die 3-Klassen-Partition (positiv/negativ/null) fängt vorzeichenbezogene Bugs und ist normalerweise besser für mathematische Funktionen. Die 2-Klassen-Partition (nicht-null/null) ist schneller, könnte aber Vorzeichenfehler übersehen. Zu berücksichtigende Faktoren: Code-Verzweigungen, mathematische Eigenschaften, Domain-Bedeutung, Bug-Risiko-Historie und Fehlerkosten. Granularität ist eine Designentscheidung, kein mathematisches Mandat.
Frage 6: Null als Sonderfall
Warum hat calculate_ray_slope(angle) 4 Äquivalenzklassen statt 3?
A) Weil es mehr Codezeilen hat als reciprocal(x)
B) Weil null (horizontaler Strahl) spezielle geometrische Bedeutung hat und sich von positiven/negativen Steigungen unterscheidet
C) Weil es NumPy statt einfaches Python verwendet
D) Weil die Funktionssignatur länger ist
Antwort anzeigen
Richtige Antwort: B
Die Funktion hat 4 Klassen (abwärts/horizontal/aufwärts/vertikal) statt 3, weil null (horizontaler Strahl) kritische geometrische Bedeutung im Raytracing hat. Horizontale Strahlen (Steigung = 0) verhalten sich grundlegend anders als geneigte Strahlen. Zusätzlich geben vertikale Strahlen (±90°) None statt einem Float zurück, was eine vierte eindeutige Kategorie schafft. Dies zeigt, dass die Anzahl der Klassen von bedeutungsvollen Verhaltensunterschieden abhängt, nicht von Code-Komplexität.
Frage 7: Array-Strukturklassen
Was macht das Testen von Array-basierten Funktionen komplexer als das Testen einfacher numerischer Funktionen?
A) Arrays können nur positive Zahlen enthalten
B) Arrays benötigen mehr Speicher zur Verarbeitung
C) Arrays führen zwei Dimensionen von Äquivalenz ein: strukturell (Länge, Form) und wertbasiert (Inhaltsmuster)
D) Arrays können nicht mit Äquivalenzklassen getestet werden
Antwort anzeigen
Richtige Antwort: C
Arrays sind schwieriger zu testen, weil sie zwei Dimensionen von Äquivalenzklassen haben. Die strukturelle Dimension umfasst: leer (Länge 0), einzelnes Element (Länge 1), zwei Elemente (minimal nicht-trivial) und viele Elemente. Die Wertdimension umfasst: alle positiv, alle negativ, gemischte Vorzeichen, enthält Nullen, alle Nullen. Diese Dimensionen multiplizieren sich: 4 strukturell × 5 Werte = 20 potenzielle Kombinationen! Du musst beide Dimensionen beim Entwerfen von Tests berücksichtigen.
Frage 8: Übertesten derselben Klasse
Welcher Ansatz ist verschwenderisch?
A) Testen von reciprocal(1.0), reciprocal(2.0), reciprocal(5.0), reciprocal(10.0), reciprocal(100.0)
B) Testen von reciprocal(5.0), reciprocal(-5.0), reciprocal(0.0)
C) Testen von reciprocal_sum(1,2,3), reciprocal_sum(-1,-2,-3), reciprocal_sum(1,-0.5,-0.5)
D) Testen von calculate_ray_slope(-45), calculate_ray_slope(0), calculate_ray_slope(45), calculate_ray_slope(90)
Antwort anzeigen
Richtige Antwort: A
Option A testet 5 verschiedene positive Zahlen, aber sie gehören alle zur gleichen Äquivalenzklasse (positive Eingaben → positive Ausgaben). Das Testen eines Vertreters (z.B. reciprocal(5.0)) ist ausreichend! Dies ist Übertesten - es verschwendet Zeit ohne Erhöhung der Abdeckung. Optionen B, C und D testen alle verschiedene Äquivalenzklassen und sind daher effiziente Ansätze.
Frage 9: Kombinatorische Explosion
Für find_intersection() mit 5 Dimensionen der Komplexität (Array-Struktur: 5 Klassen, Winkel: 5 Klassen, Kameraposition: 6 Klassen, Ergebnis: 4 Klassen, Straßenform: 3 Klassen), wie viele Gesamtkombinationen sind theoretisch möglich?
A) 23 Tests (5+5+6+4+3)
B) 150 Tests (5×5×6)
C) 600 Tests (5×5×6×4)
D) 1800 Tests (5×5×6×4×3)
Antwort anzeigen
Richtige Antwort: C
Die Rechnung ist 5 × 5 × 6 × 4 = 600 Tests! (Wir haben die Straßenform vereinfacht, um nicht über 1000 zu gehen). Dies demonstriert kombinatorische Explosion - Komplexität multipliziert sich schnell mit mehreren Dimensionen. Allerdings brauchen wir nicht wirklich alle 600 Tests. Menschliches Domänenwissen kann dies auf 25-30 strategische Tests reduzieren, indem wir erkennen, welche Kombinationen redundant oder unmöglich sind (z.B. “abwärts gerichteter Strahl von Kamera über Straße nach unten schauend” vs. “aufwärts gerichteter Strahl von Kamera unter Straße nach oben schauend” testen unterschiedliche Physik).
Frage 10: Menschliche Einsicht vs. KI-Einschränkungen
Warum können LLMs (wie ChatGPT/Claude) nicht einfach alle notwendigen Tests für komplexe Funktionen wie find_intersection() generieren?
A) LLMs haben nicht genug Rechenleistung
B) LLMs fehlt geometrische Intuition, Domänenwissen und sie können nicht priorisieren, welche Kombinationen tatsächlich wichtig sind
C) LLMs sind nur auf englischem Text trainiert, nicht auf Code
D) LLMs können alle Tests perfekt generieren; menschliche Überprüfung ist unnötig
Antwort anzeigen
Richtige Antwort: B
LLMs haben Schwierigkeiten mit komplexem Testen, weil ihnen fehlt: (1) geometrische Intuition - können Strahl-Straßen-Schnittpunkte nicht visualisieren, (2) Domänenwissen - verstehen Kamera-Straßen-physikalische Beziehungen nicht, (3) Priorisierung - behandeln alle Kombinationen gleich, wissen nicht was wichtig ist, (4) Randfallbewusstsein - übersehen parallele Strahlen, degenerierte Geometrie, (5) Mustererkennung - generieren sich wiederholende Tests mit unterschiedlichen Zahlen. Menschen liefern Domänenexpertise um 600 Tests auf 25-30 strategische zu reduzieren. LLMs können beim Implementieren von Tests helfen, aber Menschen müssen die Äquivalenzklassen entwerfen.
Frage 11: Reduktionsstrategie
Wie reduzierst du praktisch 600 potenzielle Testkombinationen auf ~30 strategische Tests?
A) Wähle 30 Tests zufällig aus den 600
B) Teste nur die erste Dimension und ignoriere den Rest
C) Decke jede Dimension mit 2-3 Vertretern ab, stelle sicher, dass alle Ergebnistypen erscheinen, und füge Randfälle basierend auf Domänenwissen hinzu
D) Verwende automatisierte Tools um alle 600 Tests zu generieren
Antwort anzeigen
Richtige Antwort: C
Die Reduktionsstrategie ist: (1) Decke jede Dimension mit 2-3 Vertretern ab (nicht alle Werte), (2) Stelle sicher, dass alle Ergebnistypen irgendwo in der Test-Suite erscheinen (Schnittpunkt gefunden, kein Schnittpunkt, Parallelfall, etc.), (3) Füge Randfälle hinzu, die durch Domänenwissen identifiziert wurden (vertikaler Strahl, Kamera hinter Straße, etc.). Dies gibt ungefähr: 3 + 3 + 2 + 4 + 2 = 14 Basistests, plus ~10 Randfälle = 25-30 Tests. Der Schlüssel ist die Nutzung von menschlicher Einsicht um zu identifizieren, welche Kombinationen redundant oder unmöglich sind.
Frage 12: Mathematische Grundlagen
Was bedeutet die Äquivalenzrelation x ~ y für eine Funktion f?
A) Die Eingaben x und y haben den gleichen numerischen Wert
B) Die Ausgaben f(x) und f(y) gehören zur gleichen Ausgabekategorie (z.B. beide positiv, beide negativ)
C) Die Eingaben x und y müssen im gleichen Testfall getestet werden
D) Die Funktion f muss den exakt gleichen Wert für x und y zurückgeben
Antwort anzeigen
Richtige Antwort: B
Die Äquivalenzrelation x ~ y bedeutet “die Ausgaben f(x) und f(y) gehören zur gleichen Ausgabekategorie”. Zum Beispiel haben wir in reciprocal(x) 5.0 ~ 100.0, weil beide positive Ausgaben erzeugen (gleiche Kategorie), obwohl reciprocal(5.0) = 0.2 und reciprocal(100.0) = 0.01 unterschiedliche Werte sind. Die Relation geht um Verhaltensähnlichkeit (gleiche Ausgabekategorie), nicht um numerische Gleichheit.
Frage 13: Partitionsvollständigkeit
Was bedeutet es, dass Äquivalenzklassen “vollständig” sind?
A) Alle Testfälle müssen erfolgreich bestehen
B) Jede mögliche Eingabe gehört zu genau einer Äquivalenzklasse
C) Die Implementierung muss vor dem Testen fertig sein
D) Testen muss 100% Code-Abdeckung erreichen
Antwort anzeigen
Richtige Antwort: B
“Vollständig” bedeutet, dass jeder mögliche Eingabewert zu einer Äquivalenzklasse gehört - keine Eingabe wird unkategorisiert gelassen. Kombiniert mit “disjunkt” (keine Eingabe gehört zu mehreren Klassen) stellt dies sicher, dass die Klassen eine Partition des Eingaberaums bilden. Für reciprocal(x) ist jeder Float entweder positiv (E₁), negativ (E₂) oder null (E₃), also E₁ ∪ E₂ ∪ E₃ = ℝ (alle reellen Zahlen). Vollständigkeit garantiert, dass wir keine Eingabekategorien vermissen.
Frage 14: Wertbasierte vs. Strukturelle Klassen
Für array_sum(arr), welche davon ist eine STRUKTURELLE Äquivalenzklasse, keine wertbasierte?
A) Alle Elemente sind positiv
B) Array enthält gemischte Vorzeichen (positiv und negativ)
C) Array hat genau zwei Elemente
D) Alle Elemente sind null
Antwort anzeigen
Richtige Antwort: C
“Array hat genau zwei Elemente” ist eine strukturelle Klasse - es geht um die Form/Länge des Arrays, nicht um seinen Inhalt. Optionen A, B und D sind wertbasierte Klassen - sie beschreiben, welche Werte die Elemente enthalten. Arrays erfordern das Testen beider Dimensionen: strukturell (leer, einzelnes, zwei, viele Elemente) UND wertbasiert (alle positiv, alle negativ, gemischt, enthält Nullen, alle Nullen). Diese orthogonale Partitionierung schafft die Komplexität des Array-Testens.
Frage 15: Äquivalenzklassen und Code-Pfade
Welche Aussage ist am genauesten über Äquivalenzklassen und Code-Pfade?
A) Jede Äquivalenzklasse muss genau einem Code-Pfad durch die Funktion entsprechen
B) Äquivalenzklassen basieren auf Ausgabeverhaltens-Kategorien, die oft (aber nicht immer) mit Code-Pfaden übereinstimmen
C) Code-Pfade sind irrelevant für die Identifikation von Äquivalenzklassen
D) Du brauchst so viele Äquivalenzklassen wie Codezeilen in der Funktion
Antwort anzeigen
Richtige Antwort: B
Äquivalenzklassen basieren fundamental auf Ausgabeverhaltens-Kategorien. Diese stimmen oft mit Code-Pfaden überein (z.B. der if x == 0 Zweig in reciprocal(x) erzeugt eine eindeutige Ausgabekategorie), aber nicht immer. Zum Beispiel folgen reciprocal_sum(1,2,3) und reciprocal_sum(100,-50,-44) dem gleichen Code-Pfad, könnten aber als verschiedene strukturelle Klassen betrachtet werden, wenn dir Vorzeichenkombinationen wichtig sind. Der beste Ansatz nutzt White-Box-Testing um Code-Struktur zu identifizieren, gruppiert dann Eingaben nach ähnlichem Ausgabeverhalten.
Frage 16: Wann feine vs. grobe Granularität wählen
Wann solltest du eine FEINERE Partition (mehr Äquivalenzklassen) wählen?
A) Wenn die Funktion weniger als 5 Codezeilen hat
B) Wenn die Funktion sicherheitskritisch ist, Finanzdaten verarbeitet oder eine Historie von Bugs in diesem Bereich hat
C) Wenn du weniger Zeit zum Testen hast
D) Wenn die Funktion einfache Datentypen wie Integers verwendet
Antwort anzeigen
Richtige Antwort: B
Wähle feinere Granularität (mehr Äquivalenzklassen) wenn: (1) Hohes Bug-Risiko - die Funktion war vorher problematisch, (2) Kritische Domäne - Sicherheit, Finanzen, Medizin, Sicherheitssysteme, (3) Komplexe Logik - viele Code-Verzweigungen und Randfälle, (4) Fehlerkosten - Bugs wären teuer oder gefährlich. Umgekehrt verwende gröbere Granularität für: einfache/niedrig-Risiko-Funktionen, schnelle Smoke-Tests oder wenn Ressourcen begrenzt sind. Die Wahl ist risikobasiert, nicht basierend auf Codelänge oder Datentypen.
Frage 17: Repräsentative Werte
Was macht einen guten repräsentativen Wert für eine Äquivalenzklasse aus?
A) Es muss der kleinste mögliche Wert in der Klasse sein
B) Es sollte ein “typischer” Wert sein, der eindeutig zur Klasse gehört und leicht nachvollziehbar ist
C) Es muss ein Grenzwert am Rand der Klasse sein
D) Es sollte zufällig aus der Klasse ausgewählt werden
Antwort anzeigen
Richtige Antwort: B
Ein guter Vertreter ist ein typischer Wert, der eindeutig zur Klasse gehört und leicht zu verstehen ist. Für die “positive Zahlen” Klasse in reciprocal(x) wählten wir x = 5.0 - es ist eindeutig positiv, erzeugt ein leicht zu verifizierendes Ergebnis (0.2) und ist weit von Grenzen entfernt. Während Grenzwerte wichtig sind (behandelt in Grenzwertanalyse), sind sie nicht die besten Vertreter für Äquivalenzklassen-Testing. Das Ziel ist es, das Kernverhalten jeder Klasse mit einem klaren, eindeutigen Beispiel zu testen.
Frage 18: Test-Philosophie
Was ist die fundamentale Philosophie hinter Äquivalenzklassen-Testing?
A) Alle Eingaben erschöpfend testen um Korrektheit zu garantieren
B) Nur die wahrscheinlichsten Eingaben testen, die Benutzer liefern werden
C) Du testest nicht alle Eingaben - du testest alle Verhaltensweisen durch Gruppierung ähnlicher Eingaben
D) Eingaben zufällig testen bis ein Zeitlimit erreicht ist
Antwort anzeigen
Richtige Antwort: C
Die Kern-Einsicht des Äquivalenzklassen-Testens ist: wir testen Verhaltensweisen, nicht einzelne Eingaben. Anstatt unendliche Eingaben zu testen, identifizieren wir eindeutige Verhaltenskategorien (z.B. positive Ausgabe, negative Ausgabe, Fehler) und testen einen Vertreter aus jeder. Dies erreicht hohes Vertrauen ohne erschöpfendes Testen. Der Perspektivwechsel von “teste alle Eingaben” (unmöglich) zu “teste alle Verhaltensweisen” (erreichbar) ist die Grundlage praktischen Software-Testens.
Bewertungsleitfaden
- 16-18 richtig: Ausgezeichnet! Du hast ein starkes Verständnis der Äquivalenzklassen-Konzepte und kannst sie auf reale Tests anwenden
- 13-15 richtig: Gutes Verständnis! Überprüfe die verpassten Fragen, besonders um menschliche Einsicht und Reduktionsstrategien
- 10-12 richtig: Ordentliches Verständnis. Besuche die Vorlesungsabschnitte zu Granularitätswahlen und Array-Komplexität erneut
- Unter 10: Bitte überprüfe die Vorlesung sorgfältig, konzentriere dich auf die Kerndefinition, Schlüsseleigenschaften und die Beziehung zwischen Ausgabekategorien und Eingabeklassen
Wichtige Erkenntnisse zum Merken
-
Äquivalenzklassen gruppieren Eingaben nach ähnlichem Verhalten - Eingaben, die die gleiche Kategorie von Ausgabe erzeugen, gehören zur gleichen Äquivalenzklasse
-
Drei Schlüsseleigenschaften - Disjunkt (keine Überlappung), Vollständig (alle Eingaben abgedeckt), Repräsentativ (teste einen pro Klasse)
-
Ausgabekategorien bestimmen Eingabeklassen - Die Anzahl der Äquivalenzklassen entspricht der Anzahl der Ausgabekategorien, die du definierst, nicht der Anzahl der Eingabeparameter
-
White-Box-Testing zeigt, was zählt - Den Code zu sehen (z.B.
total = x+y+z) sagt dir, was das Verhalten bestimmt -
Granularität ist eine Wahl - Du wählst grob (2-3 Klassen) vs. fein (5-10 Klassen) basierend auf Risiko, Bug-Historie und Domänenkritikalität
-
Arrays haben zwei Dimensionen - Strukturelle (Länge, Form) UND wertbasierte (Inhaltsmuster) Äquivalenzklassen
-
Kombinatorische Explosion ist real - Mehrere Parameter/Dimensionen multiplizieren Komplexität (5×5×6×4 = 600 Kombinationen!)
-
Menschliche Einsicht reduziert Komplexität - Domänenwissen beschneidet 600 theoretische Tests auf 25-30 strategische
-
KI hat Einschränkungen - LLMs fehlt geometrische Intuition, Domänenwissen und Priorisierungsfähigkeit für komplexe Funktionen
-
Teste Verhaltensweisen, nicht Eingaben - Die fundamentale Verschiebung: anstatt alle Eingaben zu testen (unmöglich), teste alle Verhaltenskategorien (erreichbar)