Übungsaufgaben zur Testfallerstellung

https://oer-informatik.de/

tl/dr; (ca. 90 min Bearbeitungszeit): Beispielfragen rund um Testgetriebene Entwicklung (Testdriven Development, TDD), Testfallerstellung aus Whitebox- und Blackbox-Systematik.

Die Aufgaben beziehen sich auf die Inhalte der folgenden Blogposts:

Verständnisfragen:

A) Leitfragen Testgetriebene Entwicklung:

  1. Was versteht man unter Testgetriebener Entwicklung (TDD)?

Bei Testgetriebener Entwicklung wird zunächst ein Test erstellt, der einen Teil der Spezifikation überprüft und erst im zweiten Schritt die zugehörige Implementierung, die den Test bestehen lässt.

  1. Welche drei Phasen gibt es in der Testgetriebenen Entwicklung, wie werden Sie genannt, und welche Aufgaben haben Sie als Entwicker*in in dieser Phase?

TDD umfass diese drei sich permanent wiederholenden Phasen: * Red: Erstelle einen Test, der einen kleinen (!) Bereich der Spezifikation umfasst. Dieser soll zunächst scheitern. * Green: Implementiere gerade so viel Code, damit der zuvor erstellte Test bestanden wird. * Refactor: Verbessere - wenn nötig - den Code des Tests und der Implementierung, ohne die Funktionalität zu verändern. Der TDD-Kreislauf: Red, Green, Refactor

  1. Testgetriebenen Entwicklung wurde v.a. im Umfeld eines bestimmten Vorgehensmodells bekannt. Welches Vorgehensmodell ist dies?

Testgetriebene Entwicklung wurde v.a. durch Kent Beck bekannt, der es im Rahmen des Vorgehensmodells extreme programming (XP) entwickelt hat.

  1. In der Softwareentwicklung verwenden wir bei der Problemlösung häufig die Strategien Atomisieren (Aufteilen in kleinere, lösbare Probleme) und Abstrahieren (Ähnlichkeiten zu bekannten Problemlösungen finden). Beschreiben Sie auf welche Art Testgetriebene Entwicklung eine dieser Strategien nutzt.

Testgetriebene Entwicklung geht davon aus, dass jeweils nur kleine Abschnitte der Spezifikation getestet und entwickelt werden. Durch diese Kleinschrittigkeit ist der Fokus auf ein Teilproblem gesetzt. Die anderen bereits realisierten Abschnitte geraten durch die dafür bereits realisierten Tests jedoch nicht in Vergessenheit, sondern werden von der Testsuite weiterhin abgedeckt. Das Lösen von kleinen Teilen der Spezifikation als zentraler Bestandteil von TDD steht für die Atomisierung von Problemstellungen.

  1. Zur Testfallerstellung für Software können Whitebox- und Blackbox-Verfahren genutzt werden. Beschreiben Sie, welches dieser beiden Verfahren bei der Testgetriebenen Entwicklung eingesetzt wird - und warum das jeweils andere nicht genutzt wird.

Bei der Testgetriebenen Entwicklung entsteht der Test vor der eigentlichen Implementierung. Daher können diese Tests nur gegen die Spezifikation erstellt werden, also aus Blackboxsicht. Whitebox-Tests könnten im Nachgang aufgrund der Abdeckungsmetriken ergänzt werden, das ist jedoch nicht (mehr) Bestandteil des TDD-Zyklus.

  1. Für ein Projekt, an dem Ihr Betrieb seit einem halben Jahr arbeitet, wurden für den letzten Sprint das Sprintziel “Code mit Unit-Tests abdecken” festgelegt. Die meisten Module besitzen bislang nur wenige Integrations- und keinerlei Unittests. Nach Abschluss des Sprints konnte das Team tatsächlich eine Codeüberdeckung von 100% erreichen. Wurde das Projekt nach dieser Phase testgetrieben entwickelt? Falls nein: Welche Änderungen wären erforderlich, damit es als “testgetrieben entwickelt” bezeichnet werden kann?

Der Ablauf, Tests erst während oder nach der Implementierung zu erstellen widerspricht den Grundsätzen der Testgetriebenen Entwicklung. Testgetrieben wäre das Vorgehen nur dann, wenn für kleine Spezifikationsabschnitte zunächst ein Test, danach der zugehörige Code implementiert würde, gemäß TDD-Zyklus.

  1. Ab welchem Überdeckungsgrad darf man von “testgetriebener Entwicklung” sprechen?

Der Überdeckungsgrad hat keinerlei bezug zur Testgetriebenen Entwicklung. Daher gibt es auch keine Festlegung, welche Testabdeckung erreicht werden soll. Die Überdeckungsmetriken können genutzt werden, um nach der Erstellung von Blackboxtests und nach der darauf folgenden Implementierung Hinweise darauf zu erhalten, welche Testfälle man ggf. noch ergänzen sollte.

  1. Bei testgetriebener Entwicklung wird in Phasen vorgegangen. Benennen Sie alle Phasen, in denen der eigentliche Programmcode angepasst wird!

In den Phasen Green und Refactor wird der Programmcode bearbeitet, wobei nur in Green neue Funktionalitäten hinzugefügt werden.

  1. Benennen Sie alle Phasen, in denen der Testcode angepasst wird!

In den Phasen Red und Refactor wird der Testcode bearbeitet, wobei nur in Red neue Tests für Funktionalitäten entstehen.

B) Leitfragen Whitebox-Tests:

  1. Was versteht man unter Whitebox-Tests?

Bei Whitebox-Tests handelt es sich um Tests, die gegen die Implementierung erstellt werden. Whitebox-Testfälle werden so erstellt, dass die Testsuite einen möglichst großen Bereich des Codes erreicht.

  1. Welche Systematiken können zur Generierung von Whitebox-Testfällen genutzt werden?

Für Whitebox-Tests werden Überdeckungsmetriken herangezogen. Es wird dabei überprüft, wie viel Prozent der vorhandenen Zeilen, Anweisungen, Zweige, Pfade oder Bedingungen durch die Testfälle erreicht wird. Häufig helfen Unittest-Frameworks mit Codeabdeckungstools bei der Berechnung und Visualisierung der nicht abgedeckten Codeabschnitte.

  1. Welche Aussagen können aus den Überdeckungs-Metriken abgeleitet werden?

Aus Überdeckungsmetriken können Aussagen über die Güte der Testsuite abgeleitet werden: Werden wenige Anweisungen oder Zweige durch die Tests erreicht, so ist die Wahrscheinlichkeit größer, dass sich in den nicht erreichten Zeilen Fehler befinden. Eine umgekehrte Aussage ist nicht möglich: auch eine Funktion, in der alle Überdeckungsgrade 100% betragen, kann voller logischer Fehler sein.

  1. Eine Testsuite für eine Funktion verfügt über Testfälle mit 100% Anweisungsüberdeckung. Wann und warum kann es sinnvoll sein, diese Testsuite mit Testfällen nach Blackbox-Systematik zu ergänzen?

Fehler passieren oft am Rand des Definitionsbereichs oder bei unerwarteten oder fehlerhaften Eingaben. Mit der Grenzfallanalyse bieten Blackbox-Testfälle eine Systematik, die dabei hilft, solche Szenarien mit in die Testsuite aufzunehmen.

  1. “Verfügt eine Testsuite über 100% Zweigabdeckung, so ist automatisch auch die Anweisungsüberdeckung und die Pfadüberdeckung bei 100% gegeben.” Bewerten sie diese Aussage!

Zweigüberdeckung setzt voraus, dass an allen bedingten Anweisungen alle Zweige durchlaufen wurden. Das beinhaltet, dass alle (erreichbaren) Anweisungen auch durchlaufen wurden. Sofern also kein “toter Code” im getesteten Modul vorhanden ist (nicht erreichbare Zeilen, etwa if (false) {nichtErreichbar()}) folgt aus eine Zweigüberdeckung von 100% auch eine Anweisungsüberdeckung. Die Pfadüberdeckung wiederum basiert auf der Kombination unterschiedlicher Zweige. Eine Pfadüberdeckung von 100% würde zwar die Zweigüberdeckung beinhalten. Umgekehrt gilt dies aber nicht.

C) Leitfragen Blackbox-Tests:

  1. Was versteht man unter Blackbox-Tests?

Blackbox-Tests sind Testfälle, die gegen die Anforderungen implementiert werden. Unabhängig davon, ob der Code bekannt oder unbekannt, ob er bereits existiert oder noch nicht implementiert wurde werden lediglich die in der Spezifikation beschriebenen Eingabe- und Ausgabewerte zur Erstellung der Testfälle herangezogen. siehe Artikel zu Blackbox-Testfällen

  1. Welche Systematiken können zur Generierung von Blackbox-Testfällen genutzt werden?

Blackbox-Testfälle werden durch die beiden Systematiken Grenzfallanalyse und Äquivalenzklassenbildung gebildet.

  1. Was versteht man unter Äquivalenzklassenbildung?

Eine Äquivalenzklasse fasst ein Set von Eingabewerten zusammen, bei dem wir ein ähnliches Verhalten unseres getesteten Systems (system under test - SUT) erwarten. Die Menge aller möglichen Eingabewerte für unser SUT wird so in möglichst wenige Gruppen aufgeteilt. Äquivalenzklassen

  1. Was versteht man unter Grenzfall-Analyse?

Grenzfälle sind diejenigen Eingabewerte für unser SUT, bei dem sich das Verhalten ändert. Häufig finden sich Grenzfälle an den Grenzen des Definitionsbereichs oder an den Grenzen von Äquivalenzklassen. Da hier besonders häufig Fehler passieren, wird im Rahmen der Grenzfallanalyse der Grenzwert selbst sowie die direkten Nachbarwerte getestet. Grenzwerte

  1. Die Methode int anzahlDerPunkteImString(String text) soll systematisch getestet werden. Welche Systematiken legen Sie an? Welche Testfälle wären möglich?

Da keine Implementierung vorliegt, aber die Spezifikation im Wesentlichen aus dem Namen hervorgeht, bietet sich die Blackboxsystematik (Äquivalenzklassen, Grenzfälle) an:

Testfall
Nr.
Beschreibender Name der Testklasse / des Testfalls Vor-
bedingungen
Eingabewerte
(Parameter text)
Erwartetes
Resultat
Nach-
bedingungen
Tatsächliches
Resultat
bestanden
/ nicht bestanden
1. ÄK: mehrere Kommata keine anzahlDerPunkteImString("1,2,3") 2 - ?? ??
2. ÄK: kein Komma keine anzahlDerPunkteImString("nix") 0 - ?? ??
3. GW: Leerer String keine anzahlDerPunkteImString("") 0 - ?? ??
4. GW: Ungültige Werte keine anzahlDerPunkteImString(NULL) Exception - ?? ??
  1. Die Methode int einzurichtendeKlassen(long anzahlSchueler; long schuelerProKlasseMax) berechnet die Anzahl der Klassen, die bei einer Schülerzahl eingerichtet werden muss – unter Berücksichtigung einer Obergrenze an Schülern pro Klasse. Die Methode soll systematisch getestet werden. Welche Testfälle wären möglich? Dokumentieren Sie je Systematik 2 Testfälle!
Testfall
Nr.
Beschreibender Name der Testklasse / des Testfalls Vor-
bedingungen
Eingabewerte
(Parameter anzahlSchueler, schuelerProKlasseMax )
Erwartetes
Resultat
Nach-
bedingungen
Tatsächliches
Resultat
bestanden
/ nicht bestanden
1. GW: Anzahl Schüler geht auf keine anzahlSchueler=60
, schuelerProKlasseMax=30
2 - ?? ??
2. GW: 0 Schüler keine anzahlSchueler=0
, schuelerProKlasseMax=30
0 - ?? ??
2. ÄK: Anzahl Schüler geht nicht auf keine anzahlSchueler=61
, schuelerProKlasseMax=30
3 - ?? ??
2. ÄK: Weniger Schüler als max keine anzahlSchueler=28
, schuelerProKlasseMax=30
1 - ?? ??

Übungsaufgaben

D) Aufgabe Überdeckungstests

Gegeben ist die folgende Methode, die Rabatte errechnet in Abhängigkeit der Positionskosten (über 100€ -> 5€ Rabatt) und Gesamtkosten (über 1000€ -> 5% Rabatt auf die rabattierte Gesamtsumme):

  1. Welchen Anweisungsüberdeckungsgrad und Zweigüberdeckungsgrad erhalten Sie mit dem Testfall

Testfall im Kontrollflußgraph: 1->2->3->4->5->6->3->4->6->3->7->8->9
Ausgabe von JaCoCo: C0: 100%, C1= 83%
Anweisung 1 + 2 kann zusammengefasst werden.
C0 = durchlaufende Anweisungen / mögliche Anweisungen = 9/9 = 100% (bei Zusammenfassung von 1+2: 8/8 = 100%)
C1 = durchlaufende Zweige / mögliche Zweige = 5/6 = (83%)
Berechnung über Kanten statt Zweige:
C1 = durchlaufende Kanten / mögliche Kanten = 9/10 = 90% Ausgabe von JaCoCo: C0: 100%, C1= 83%

  1. Ergänzen Sie so wenige Testfälle wie möglich, um eine 100%ige Zweigüberdeckung zu erhalten. (Erwartete Ergebnisse sind nicht erforderlich – lediglich die zu testenden Parameter sollen angegeben werden).

Bei den folgenden Fragen können die Testfälle abgekürzt werden nach dem Muster assertEquals(result, expected), für den obigen Testfall also - weil das erwartete Resultat ja nicht berechnet werden muss, z.B.:

summe-rabatt muss unter 1000 bleiben, damit else-Zweig genommen wird, also:
Testfall im Kontrollflußgraph: 1->2->3->4->6->3->7->9
assertEquals(rabattAusgeben({10 }), ??);

E) Aufgabe Überdeckungstests

Im Folgenden ist eine Beispielimplementierung für einen SelectionSort-Algorithmus abgebildet:

  1. Erstellen Sie für diese Methode einen Kontrollflussgraphen! Kontrollflussgraph mit 9 Knoten

  2. Berechnen Sie die Zyklomatische Komplexität (McCabe-Zahl)! Die McCabe-Zahl M lässt sich am einfachsten über die Anzahl der binären Verzweigungen (b) berechnen: im Kontrollflußgraph oben haben die Knoten 2, 5 und 7 je zwei ausgehende Kanten (b=3)
    M = b + 1 = 4 Hintergrund: Artikel zur McCabe-Zahl

  3. Welche Testfälle erhalten Sie aus Blackbox-Sicht für diesen Algorithmus? Erstellen Sie für jede Blackbox-Systematik zwei Testfälle und dokumentieren Sie die erforderlichen Informationen für die Testfälle tabellarisch!

Testfall
Nr.
Beschreibender Name der Testklasse / des Testfalls Vor-
bedingungen
Eingabewerte
(Parameter sortieren)
Erwartetes
Resultat
Nach-
bedingungen
Tatsächliches
Resultat
bestanden
/ nicht bestanden
1. ÄK: Unsortiertes Array keine selectionsort([2;3;1]) [1;2;3] - ?? ??
2. ÄK: bereits sortiertes Array keine selectionsort([3;4;5]) [3;4;5] - ?? ??
3. GW: Leeres Array keine selectionsort([]) [] - ?? ??
4. GW: Ungültige Werte keine selectionsort(NULL) Exception - ?? ??
  1. Es liegt folgender Testfall vor:

Berechnen Sie den Anweisungsüberdeckungsgrad und den Zweigüberdeckungsgrad! Anhand des Kontrollflussgraphen - am besten selbst nach zeichnen, alle durchlaufenen Anweisungen und Kanten kennzeichnen:
Kontrollflussgraph mit 9 Knoten
Anweisungsüberdeckung: C_0 = \frac{9}{9} = 100%
Über Zweige: Zweig 7-6 wird nicht durchlaufen,
Zweigüberdeckung: C_1 = \frac{5}{6} = 100% Über Kanten: Kante 7-6 wird nicht durchlaufen,
Kantenüberdeckung: C_1 = \frac{10}{11} = 100%

F) Aufgabe Blackbox-Tests

Testfallerstellung: Es soll eine einfache Funktion getestet werden, die ganzzahliges Teilen wie in der Grundschule durchführt und das Ergebnis als Zeichenkette ausgibt:

Ausgabe: 10 : 3 = 3 Rest 1

Wir kennen zwei Systematiken zur Blackbox-Testfallerstellung. Dokumentieren Sie für jede Systematik zwei Testfälle für die obige Funktion. Nennen Sie dabei neben der genutzten Systematik auch alle relevanten Werte, die für eine Testfalldokumentation wichtig sind!
Testfall
Nr.
Beschreibender Name der Testklasse / des Testfalls Vor-
bedingungen
Eingabewerte
(Parameter divident, divisor)
Erwartetes
Resultat gemäß Spezifikation
Nach-
bedingungen
Tatsächliches
Resultat
bestanden
/ nicht bestanden
1. ÄQ: Ergebnis ist Ganzzahl keine divident=8
divisor=4
2 - 2 ok
2. ÄK: Ergebnis ist Gleitkommazahl keine divident=1
divisor=10
0.1
auf sechs signifikante Stellen genau
- 0.1 ok
3. GW: Teilen durch 0 keine divident=1
divisor=0
UI muss zur Korrektur der Werte auffordern - Exception fail
4. GW: Teilen mit 0 keine divident=0
divisor=1
0 - 0 ok

Quellen und offene Ressourcen (OER)

Die Ursprungstexte (als Markdown), Grafiken und zugrunde liegende Diagrammquelltexte finden sich (soweit möglich in weiterbearbeitbarer Form) in folgendem git-Repository:

http://gitlab.com/oer-informatik/db-sql/dbms.

Sofern nicht explizit anderweitig angegeben sind sie zur Nutzung als Open Education Resource (OER) unter Namensnennung (H. Stein, oer-informatik.de) freigegeben gemäß der Creative Commons Namensnennung 4.0 International Lizenz (CC BY 4.0).

Creative Commons Lizenzvertrag

Kommentare gerne per Mastodon, Verbesserungsvorschläge per gitlab issue (siehe oben). Beitrag teilen: