Übungsaufgaben zu Akzeptanztests mit Gherkin und Cucumber: Szenarien, Step Definitions und Abnahmeprotokoll für die Mitfahrgesuche
https://bildung.social/@oerinformatik/
https://oer-informatik.de/flurmonitor-akzeptanztest-uebungsaufgaben
Akzeptanztest, Abnahmetest, Gherkin, Cucumber, Step Definition, Szenariogrundriss, Page Object, Abnahmeprotokoll, Sprint Review, Mitfahrgesuche, Übungsaufgaben, Prüfungsvorbereitung
tl/dr; (Bearbeitungszeit insgesamt 54 min, mehrere Aufgaben): Die Mitfahrgesuche auf den Flurmonitoren bekommen Akzeptanztests. In diesen Übungen bestimmst Du die Bestandteile einer Feature-Datei und sagst voraus, welche Schritte Cucumber zuordnen kann, schreibst Szenarien und Step Definitions für die Gesuche je Monitor und wertest das Abnahmeprotokoll eines Sprint Reviews aus [AI-Assisted]. (Zuletzt geändert am 11.11.2026)
Dieser Artikel ist Teil einer Artikelreihe über den Flurmonitor mit Thymeleaf: Projektübersicht / Scrum-Projektstart / Thymeleaf einbinden / Templates / Ansichtsmodell / Integrationstest der Web-Schicht / Konfiguration und Formatierung / Aktualisierung / Hinweise mit Formularen / Robustheit und Betrieb / GUI-Test mit Selenium / Akzeptanztest / Übungsaufgaben zu Akzeptanztest / Change Request Keycloak
Diese Übungsaufgaben gehören zum Artikel Akzeptanztests mit Gherkin, Cucumber und Selenium: Abnahmekriterien, die der Product Owner lesen kann. Alle Aufgaben spielen im Projektteam der Mitfahr-App Mitfahrlabor und setzen den Übungsstrang zu den Mitfahrgesuchen fort. Ausgangspunkt ist das Projekt im Ordner src/a11-akzeptanztest des Backend-Repositorys mit den Feature-Dateien, Step Definitions und Page Objects aus dem Artikel. Den Startcode für die Gesuche findest Du dort im Unterordner uebung-mitfahrgesuche; kopiere seinen Ordner src über den Ordner src des Projekts mitfahrlabor. Er enthält den MitfahrgesucheController mit der Adresse /flurmonitor/{monitor}/gesuche (Parameter ort optional), die GesucheAufbereitung, das Template flurmonitor-gesuche.html und den Platzhalter GesuchService mit zwei offenen Gesuchen für Montag, 16.11.2026: Gütersloh zur Schule (07:00–08:00 Uhr) und Bielefeld nach Hause (15:30–16:30 Uhr).
Hinweise zur Bearbeitung: Bis zur Teil-1-Prüfung der IT-Berufe solltest Du die Basiskompetenz beherrschen, also Aufgabe 1.1. Als FIA, FIDP oder FIDV musst Du zur Teil-2-Prüfung Aufgaben auf Kernkompetenz-Ebene lösen können, das sind Aufgabe 2.1 und Aufgabe 2.2. Von FIA wird zusätzlich erwartet, dass ihnen Aufgaben auf Profilkompetenz-Ebene (Aufgabe 3.1) keine Probleme bereiten. Notiere Deine Antworten zuerst vollständig, bevor Du die Beispiellösung aufklappst. Code-Aufgaben prüfst Du am besten im Projekt: ./gradlew akzeptanzTest startet alle Szenarien, mit -Dcucumber.filter.tags=@MON-13d nur die zu den Gesuchen und mit -Dgui.sichtbar=true siehst Du den Browser bei der Arbeit (Chrome muss installiert sein). Den Bericht findest Du danach unter build/reports/cucumber/akzeptanztest.html. Bei Formulierungen von Szenarien, Bezeichnern und Begründungen sind andere fachlich richtige Lösungen ebenso richtig.
Du möchtest eigene Aufgaben zum Üben von einem KI-Sprachmodell generieren lassen?
Kopiere den Text in ein KI-Sprachmodell Deiner Wahl und passe Kompetenzstufe, Anzahl, Bearbeitungszeit und Szenario bei Bedarf an. Wie die Aufgaben aufgebaut sind, beschreibt der Artikel Wie sind die Aufgaben aufgebaut?. Prüfe die Ergebnisse mit dem Lehrartikel: KI-Sprachmodelle machen Fehler.
Erstelle neue Übungsaufgaben zum Thema „Akzeptanztests mit Gherkin und
Cucumber: Szenarien, Step Definitions und Abnahmeprotokoll für die
Mitfahrgesuche“.
Bauplan: Halte Dich an Aufbau, Kompetenzstufen, Operatoren,
Anforderungsbereiche, Punkte und Zeitschätzung, die im Artikel
https://oer-informatik.de/aufgaben-aufbau beschrieben sind.
Fachliche Grundlage:
- https://oer-informatik.de/flurmonitor-akzeptanztest
- https://oer-informatik.de/szenario-mitfahrlabor
- Stilbeispiel: https://oer-informatik.de/flurmonitor-akzeptanztest-uebungsaufgaben
Die Aufgaben sollen Inhalte zu diesen Schlagwörtern abdecken:
- Akzeptanztest
- Abnahmetest
- Gherkin
- Cucumber
- Step Definition
- Szenariogrundriss
- Page Object
- Abnahmeprotokoll
- Sprint Review
- Mitfahrgesuche
Kompetenzstufe: Kernkompetenz (alternativ: Basiskompetenz, Profilkompetenz, Expertise)
Anzahl: 1 Aufgabe mit Teilaufgaben
Bearbeitungszeit in Minuten ca.: <5 bis 30 min>
Szenario: eines der Szenarien aus dem Bauplan
Vorgehen:
1. Lies zuerst die verlinkten Artikel. Kannst Du keine Webseiten
abrufen, sag mir das, statt zu raten.
2. Steht bei einer Angabe noch ein Platzhalter in <…>, frag mich
zuerst danach. Richte Punkte und Zahl der Teilaufgaben nach der
Bearbeitungszeit (ca. 0,9 min je Punkt).
3. Gib je Aufgabe Titel mit Kompetenzstufe, Ausgangssituation und
Teilaufgaben mit Operator und Punktzahl aus, dazu die geschätzte
Bearbeitungszeit.
4. Gib die Beispiellösungen mit Punkteverteilung erst aus, wenn ich
danach frage.
Aufgabe 1.1: Bestandteile einer Feature-Datei (Basiskompetenz)
(ca. 15 min Bearbeitungszeit)
Für die Verwaltungsseite der Gesuche hat das Team einen ersten Entwurf einer Feature-Datei geschrieben. Die Zeilen sind nummeriert:
1 # language: de
2 @akzeptanz @MON-13g
3 Funktionalität: Gesuche zurückziehen
4 Als Schulverwaltung möchte ich ein Gesuch mit Grund zurückziehen,
5 damit auf den Monitoren keine erledigten Gesuche stehen.
6
7 Grundlage:
8 Angenommen es ist Montag, der 16.11.2026, 06:00 Uhr
9 Und Heike Brinkmann ist an der Verwaltungsseite angemeldet
10
11 Szenariogrundriss: AK-MON-13g.1 Ein zurückgezogenes Gesuch verschwindet
12 Wenn sie das Gesuch ab "<ort>" mit dem Grund "<grund>" zurückzieht
13 Dann zeigt der Monitor "mensa" kein Gesuch ab "<ort>" mehr
14
15 Beispiele:
16 | ort | grund |
17 | Gütersloh | Mitfahrt gefunden |
18 | Bielefeld | Termin fällt aus |
19
20 Szenario: AK-MON-13g.2 Ohne Grund wird nichts zurückgezogen
21 Wenn sie das Gesuch ab "Gütersloh" ohne Grund zurückzieht
22 Dann zeigt das Formular die Meldung "Bitte einen Grund angeben."
23 Aber der Monitor "mensa" zeigt weiter 2 offene Gesuche
- Ordne den Bestandteilen in der Tabelle die passenden Zeilennummern zu und beschreibe kurz ihre Aufgabe. (6 Punkte)
| Bestandteil | Zeile(n) | Aufgabe |
|---|---|---|
| Sprachangabe | ||
| Tag | ||
| Funktionalität mit Beschreibung | ||
| Grundlage | ||
| Szenariogrundriss mit Platzhalter | ||
| Beispiele |
| Bestandteil | Zeile(n) | Aufgabe |
|---|---|---|
| Sprachangabe | 1 | schaltet auf die deutschen Schlüsselwörter um (Funktionalität, Angenommen …) |
| Tag | 2 | gruppiert die Szenarien; @akzeptanz wählt sie für die Gradle-Aufgabe aus, @MON-13g nennt die Story und dient als Filter |
| Funktionalität mit Beschreibung | 3–5 | Überschrift der Datei; die freie Beschreibung enthält die User Story |
| Grundlage | 7–9 | Schritte, die vor jedem Szenario der Datei laufen (Uhr, Anmeldung) |
| Szenariogrundriss mit Platzhalter | 11–13 | Vorlage, in der <ort> und <grund> durch die Werte der Beispiele ersetzt werden |
| Beispiele | 15–18 | Tabelle mit Kopfzeile (16) und je einer Zeile Werte für einen Durchlauf (17, 18) |
Je Zeile 1 Punkt: Zeilennummern und Aufgabe müssen stimmen.
- Bestimme, wie viele Szenarien Cucumber aus dieser Datei ausführt und wie viele Schritte diese Szenarien zusammen enthalten, die Schritte der Grundlage eingerechnet. (3 Punkte)
Es laufen 3 Szenarien: der Szenariogrundriss zweimal (je Zeile der Beispiele) und das Szenario AK-MON-13g.2 einmal. (1 Punkt)
Zu jedem Szenario gehören die 2 Schritte der Grundlage. Der Grundriss hat 2 eigene Schritte, das zweite Szenario 3. Insgesamt: 2 · (2 + 2) + (2 + 3) = 8 + 5 = 13 Schritte. (2 Punkte)
- Im Glue-Paket gibt es unter anderem diese Step Definitions:
@Wenn("sie das Gesuch ab {string} mit dem Grund {string} zurückzieht")
public void zurueckziehen(String ort, String grund) { … }
@Dann("zeigt der Monitor {string} weiter {int} offene(s) Gesuch(e)")
public void zeigtWeiter(String monitor, int anzahl) { … }
@Dann("zeigt der Monitor {string} kein Gesuch ab {string} mehr")
public void keinGesuchMehr(String monitor, String ort) { … }Sage für die Zeilen 12, 21 und 23 voraus, ob Cucumber eine dieser Methoden aufruft, und wenn ja, mit welchen Argumenten (Zeile 12 im ersten Durchlauf). Nenne für jeden Schritt ohne passende Methode, was Cucumber meldet. (4 Punkte)
- Zeile 12 (erster Durchlauf: „Wenn sie das Gesuch ab “Gütersloh” mit dem Grund “Mitfahrt gefunden” zurückzieht“):
zurueckziehen("Gütersloh", "Mitfahrt gefunden"). Die Platzhalter sind schon ersetzt, bevor Cucumber zuordnet. (1 Punkt) - Zeile 21: keine Methode passt, weil „ohne Grund“ nicht zu „mit dem Grund {string}“ passt. Der Schritt ist undefined; Cucumber lässt das Szenario scheitern, überspringt die übrigen Schritte und schlägt eine Methode mit
@Wenn("sie das Gesuch ab {string} ohne Grund zurückzieht")vor. (1,5 Punkte) - Zeile 23:
zeigtWeiter("mensa", 2). Das SchlüsselwortAberspielt beim Zuordnen keine Rolle, undoffene(s) Gesuch(e)passt durch die optionalen Teile auch zu „offene Gesuche“. (Weil Zeile 21 undefined ist, kommt Cucumber in diesem Szenario allerdings gar nicht bis Zeile 23.) (1,5 Punkte)
- Entscheide für jede Aussage, ob sie eher zum Systemtest oder zum Abnahmetest passt, und begründe kurz. (3 Punkte)
- „Der Test prüft, ob die Seite
/flurmonitor/mensa/gesuchemit Status 200 und einer Tabelle mit sechs Spalten antwortet.“ - „Heike Brinkmann hat die Sätze des Szenarios mitformuliert; nach dem Lauf entscheidet Thomas Becker, ob die Story fertig ist.“
- „Grundlage des Tests ist AK-MON-13g.1 aus dem Product Backlog.“
- Systemtest: geprüft wird gegen den Entwurf der Oberfläche (Adresse, Status, Aufbau der Tabelle), nicht gegen eine Anforderung. (1 Punkt)
- Abnahmetest: Fachseite schreibt mit, der Product Owner entscheidet über die Abnahme. (1 Punkt)
- Abnahmetest: Prüfgrundlage ist ein Abnahmekriterium, also eine Anforderung. (1 Punkt)
Aufgabe 2.1: Szenarien für die Gesuche je Monitor (Kernkompetenz)
(ca. 11 min Bearbeitungszeit)
Im Refinement hat Thomas Becker für die Story MON-13d „Gesuche je Monitor“ drei Abnahmekriterien vereinbart:
- AK-MON-13d.1: Wenn ein Monitor die Gesuche lädt, dann zeigt er nur die Gesuche in seinen Richtungen: die Mensa beide, Flur B nur „zur Schule“, Parkplatz C nur „nach Hause“.
- AK-MON-13d.2: Wenn ein Monitor die Gesuche für einen bestimmten Ort lädt, dann zeigt er nur die Gesuche ab diesem Ort.
- AK-MON-13d.3: Angenommen, es gibt für einen Ort keine offenen Gesuche. Wenn ein Monitor die Gesuche für diesen Ort lädt, dann zeigt er die Anzahl 0 und den Satz „Gerade keine offenen Gesuche.“ statt einer leeren Tabelle.
Die Gesuche aus dem Startcode gelten für Montag, 16.11.2026. Für die Uhr gibt es schon den Schritt „es ist {word}, der {datum}, {uhrzeit} Uhr“ aus dem Artikel.
- Schreibe die Feature-Datei
src/test/resources/features/gesuche.featuremit je einem Szenario bzw. Szenariogrundriss für die drei Kriterien. Nutze für AK-MON-13d.1 einen Szenariogrundriss mit allen drei Monitoren und für die Uhr eine Grundlage. Die Datei soll für den Product Owner lesbar sein und für die Gradle-AufgabeakzeptanzTestgefunden werden. (9 Punkte)
# language: de
@akzeptanz @MON-13d
Funktionalität: Mitfahrgesuche je Monitor
Als Auszubildende*r mit Auto möchte ich an jedem Monitor die offenen Gesuche
in seinen Richtungen sehen, damit ich jemanden mitnehmen kann (MON-13d).
Grundlage:
Angenommen es ist Montag, der 16.11.2026, 06:00 Uhr
Szenariogrundriss: AK-MON-13d.1 Jeder Monitor zeigt die Gesuche seiner Richtungen
Wenn der Monitor "<monitor>" die Gesuche lädt
Dann zeigt er <gesuche> aus "<orte>"
Beispiele:
| monitor | gesuche | orte |
| mensa | 2 offene Gesuche | Gütersloh, Bielefeld |
| flur-b | 1 offenes Gesuch | Gütersloh |
| parkplatz-c | 1 offenes Gesuch | Bielefeld |
Szenario: AK-MON-13d.2 Ein Monitor zeigt auf Wunsch nur die Gesuche eines Orts
Wenn der Monitor "mensa" die Gesuche für den Ort "Bielefeld" lädt
Dann zeigt er 1 offenes Gesuch aus "Bielefeld"
Szenario: AK-MON-13d.3 Ohne passende Gesuche steht ein Satz statt einer leeren Tabelle
Wenn der Monitor "mensa" die Gesuche für den Ort "Herford" lädt
Dann zeigt er 0 offene Gesuche
Und steht dort der Satz "Gerade keine offenen Gesuche."
Bewertung: Sprachangabe und Tag @akzeptanz (1 Punkt), Funktionalität mit Beschreibung der Story (1 Punkt), Grundlage mit der Uhr auf Montag, 16.11.2026 (1 Punkt), Szenariogrundriss mit Platzhaltern und drei Beispielzeilen mit richtigen Erwartungen (3 Punkte), Szenarien für 13d.2 und 13d.3 mit genau einem Wenn (2 Punkte), Namen beginnen mit der Nummer des Kriteriums (1 Punkt).
Die Spalte gesuche enthält Zahl und Wort („1 offenes Gesuch“), damit der Satz grammatisch stimmt. Schreibt man stattdessen Dann zeigt er <anzahl> offene(s) Gesuch(e) aus "<orte>", steht nach dem Ersetzen „offene(s) Gesuch(e)“ wörtlich im Schritt. Optionaler Text ist nur in Cucumber Expressions erlaubt, nicht im Gherkin-Text; der Schritt wäre undefined.
- Begründe, warum die Uhr in eine Grundlage gehört und nicht als „Angenommen“ in jedes Szenario, und nenne einen Fall, in dem ein Szenario trotzdem einen eigenen Uhr-Schritt braucht. (3 Punkte)
Alle Szenarien der Datei brauchen denselben Ausgangszeitpunkt; die Grundlage nennt ihn einmal, die Szenarien bleiben kurz und zeigen nur, worin sie sich unterscheiden (2 Punkte). Einen eigenen Schritt braucht ein Szenario, dessen Kriterium von einem anderen Zeitpunkt handelt, zum Beispiel „Angenommen, es ist Freitag, 15:00 Uhr“, um zu prüfen, dass Gesuche für Montag schon am Freitagnachmittag erscheinen. Der Schritt im Szenario stellt die Uhr nach der Grundlage noch einmal um (1 Punkt).
Aufgabe 2.2: Step Definitions für die Gesuche (Kernkompetenz)
(ca. 13 min Bearbeitungszeit)
Für die Seite der Gesuche gibt es aus den letzten Übungen ein Page Object. Ergänze es um die Methode meldungOhneGesuche():
package de.dbh.mitfahrlabor.guitest.seiten;
import java.util.List;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
/** Page Object für /flurmonitor/{monitor}/gesuche (MON-13d). */
public class GesucheSeite {
private static final By ANZAHL = By.cssSelector("header p strong");
private static final By ZEILEN = By.cssSelector("table.abfahrten tbody tr");
private static final By KEINE = By.cssSelector("main > p.fs-4");
private final WebDriver browser;
public GesucheSeite(WebDriver browser) {
this.browser = browser;
}
/** Öffnet die Gesuche eines Monitors; {@code ort} darf null sein (dann alle Orte). */
public static GesucheSeite oeffnen(WebDriver browser, String basisadresse, String monitor, String ort) {
String filter = ort == null ? "" : "?ort=" + ort;
browser.get(basisadresse + "/flurmonitor/" + monitor + "/gesuche" + filter);
return new GesucheSeite(browser);
}
public int anzahl() {
return Integer.parseInt(browser.findElement(ANZAHL).getText());
}
/** Spalte „Ort“ (dritte Zelle) aller Zeilen, von oben nach unten. */
public List<String> orte() {
return browser.findElements(ZEILEN).stream()
.map(zeile -> zeile.findElement(By.cssSelector("td:nth-child(3)")).getText()).toList();
}
/** Satz statt einer leeren Tabelle; leer, wenn Gesuche angezeigt werden. */
public String meldungOhneGesuche() {
return browser.findElements(KEINE).stream().map(WebElement::getText).findFirst().orElse("");
}
}- Schreibe die Klasse
GesucheSchritteim Paketde.dbh.mitfahrlabor.akzeptanztestmit den Step Definitions für Deine Feature-Datei aus Aufgabe 2.1. Nutze dieTestweltaus dem Artikel für Browser und Basisadresse und das Page Object für alle Zugriffe auf die Seite. (8 Punkte)
package de.dbh.mitfahrlabor.akzeptanztest;
import static org.assertj.core.api.Assertions.assertThat;
import java.util.Arrays;
import de.dbh.mitfahrlabor.guitest.seiten.GesucheSeite;
import io.cucumber.java.de.Dann;
import io.cucumber.java.de.Wenn;
/** Step Definitions zu den Mitfahrgesuchen am Monitor (MON-13d). */
public class GesucheSchritte {
private final Testwelt welt;
private GesucheSeite seite;
public GesucheSchritte(Testwelt welt) {
this.welt = welt;
}
@Wenn("der Monitor {string} die Gesuche lädt")
public void gesucheLaden(String monitor) {
seite = GesucheSeite.oeffnen(welt.browser(), welt.basis(), monitor, null);
}
@Wenn("der Monitor {string} die Gesuche für den Ort {string} lädt")
public void gesucheFuerOrtLaden(String monitor, String ort) {
seite = GesucheSeite.oeffnen(welt.browser(), welt.basis(), monitor, ort);
}
@Dann("zeigt er {int} offene(s) Gesuch(e) aus {string}")
public void zeigtGesucheAus(int anzahl, String orte) {
assertThat(seite.anzahl()).isEqualTo(anzahl);
assertThat(seite.orte()).containsExactlyElementsOf(Arrays.asList(orte.split(",\\s*")));
}
@Dann("zeigt er {int} offene(s) Gesuch(e)")
public void zeigtGesuche(int anzahl) {
assertThat(seite.anzahl()).isEqualTo(anzahl);
assertThat(seite.orte()).hasSize(anzahl);
}
@Dann("steht dort der Satz {string}")
public void stehtDerSatz(String satz) {
assertThat(seite.meldungOhneGesuche()).isEqualTo(satz);
}
}Bewertung: Konstruktor mit Testwelt (1 Punkt), zwei @Wenn-Methoden mit passenden Cucumber Expressions und Page Object (2 Punkte), {int} und optionaler Text offene(s) Gesuch(e) für Einzahl und Mehrzahl (2 Punkte), Prüfung von Anzahl und Reihenfolge der Orte (2 Punkte), Satz über das Page Object statt eines Locators in der Step Definition (1 Punkt).
Die Seite liegt hier in einem Feld der Step-Definition-Klasse, weil nur diese Klasse sie braucht; Cucumber legt die Klasse für jedes Szenario neu an. Der Schritt „Dann zeigt er 1 offenes Gesuch aus …“ und „zeigt er 0 offene Gesuche“ passen nicht zur gleichen Methode, weil der eine mit aus {string} endet. Mit dem Code aus diesem Artikel und dem Startcode laufen alle fünf Szenarien grün (./gradlew akzeptanzTest -Dcucumber.filter.tags=@MON-13d).
- Der Schritt „Dann zeigt er bei den Fahrten zur Schule diese Fahrt:“ aus dem Artikel und Dein Schritt „Dann zeigt er 2 offene Gesuche aus …“ beginnen beide mit „zeigt er“. Erkläre, warum Cucumber trotzdem keine
AmbiguousStepDefinitionsExceptionmeldet, und unter welcher Bedingung sie auftreten würde. (2 Punkte)
Cucumber vergleicht den ganzen Satz mit dem ganzen Ausdruck, nicht nur den Anfang. „bei den Fahrten {richtung} diese Fahrt:“ und „{int} offene(s) Gesuch(e) aus {string}“ passen nie auf denselben Text (1 Punkt). Mehrdeutig wäre es erst, wenn zwei Ausdrücke denselben Satz vollständig treffen, etwa zeigt er {int} offene(s) Gesuch(e) aus {string} und zeigt er {int} offene Gesuche aus {string} für den Satz „zeigt er 2 offene Gesuche aus …“ (1 Punkt).
- Die Gesuche liegen im Startcode nicht in der Datenbank, sondern in einer Liste im
GesuchService. Für AK-MON-13g.1 aus Aufgabe 1.1 zieht ein Szenario ein Gesuch zurück. Erkläre, welches Problem dadurch für die Szenarien aus Aufgabe 2.1 entstehen kann, obwohl der HookVorbereitungnach jedem Szenario aufräumt, und schlage eine Lösung vor. (4 Punkte)
Der Spring-Kontext und damit die Bean GesuchService leben für alle Szenarien weiter. Der Hook nachDemSzenario löscht nur neue Zeilen in den Tabellen angebot und hinweis; die Liste im GesuchService setzt er nicht zurück (1 Punkt). Läuft das Szenario zum Zurückziehen vor gesuche.feature, fehlt danach ein Gesuch, und AK-MON-13d.1 meldet zum Beispiel 1 statt 2 Gesuchen an der Mensa. Das Ergebnis hängt von der Reihenfolge der Dateien ab: Der Test ist nicht unabhängig (1 Punkt).
Lösung (2 Punkte, eine reicht): Der GesuchService bekommt eine Methode, die den Startzustand wiederherstellt, und ein @Before-Hook ruft sie auf; oder die Gesuche wandern wie Angebote und Hinweise in die Datenbank (der eigentliche Plan von MON-13), dann räumt der vorhandene Hook auch sie auf; oder das Szenario zum Zurückziehen legt sich sein Gesuch selbst an und zieht nur dieses zurück. Den Kontext für jedes Szenario neu zu starten (@DirtiesContext) wäre richtig, aber sehr langsam.
Aufgabe 3.1: Ein Abnahmeprotokoll auswerten (Profilkompetenz)
(ca. 15 min Bearbeitungszeit)
Sprint 4 des Flurmonitor-Teams ist zu Ende. Das Team hat 9 Story Points geplant: MON-15 „Hinweise mit Beginn“ (2), MON-13d „Gesuche je Monitor“ (3), MON-13e „Gesuche lesbar und barrierefrei“ (3) und MON-07.5 „Langer Hinweis vollständig“ (1). Für das Sprint Review liegt dieser Auszug aus dem Abnahmeprotokoll vor:
| Eintrag | Kriterium | Beleg | Ergebnis |
|---|---|---|---|
| MON-15 | AK-MON-15.1 | Szenario | erfüllt |
| MON-13d | AK-MON-13d.1 | Szenariogrundriss (3 Beispiele) | erfüllt |
| MON-13d | AK-MON-13d.2 | Szenario | erfüllt |
| MON-13d | AK-MON-13d.3 | Szenario | nicht erfüllt: Monitor zeigt eine leere Tabelle mit Kopfzeile statt des Satzes |
| MON-13e | AK-MON-13e.1 Kontrast mindestens 4,5 : 1 | Pipeline-Job templates |
nicht geprüft: Job wurde für den Merge manuell übersprungen |
| MON-13e | AK-MON-13e.2 lesbar aus 5 m | Sichtprüfung im Foyer | erfüllt |
| MON-07.5 | AK-MON-07.5 | Szenario | erfüllt; in der Vorführung am hochkant montierten Monitor der Mensa ist der Text abgeschnitten |
| Nicht geprüft | Merge Request zu MON-13e ohne Review durch eine zweite Person |
- Entscheide für jeden der vier Einträge, ob Thomas Becker ihn abnehmen kann. Beziehe Dich auf die Abnahmekriterien und die Definition of Done des Teams aus dem Artikel. (6 Punkte)
- MON-15: abnehmbar. Das einzige Kriterium ist durch ein Szenario belegt und erfüllt; zur DoD gibt es keinen Befund. (1 Punkt)
- MON-13d: nicht abnehmbar. AK-MON-13d.3 ist nicht erfüllt, und die DoD verlangt, dass alle Abnahmekriterien als automatisierte Tests grün sind. Der Eintrag wird nicht vorgeführt und geht zurück ins Product Backlog. (2 Punkte)
- MON-13e: nicht abnehmbar. AK-MON-13e.1 ist nicht geprüft, und zwei Punkte der DoD sind verletzt: Merge Request ohne Review, Pipeline nicht vollständig grün (der Kontrast gehört zur Barrierefreiheit der DoD). Dass die Sichtprüfung erfüllt ist, reicht nicht. (2 Punkte)
- MON-07.5: abnehmbar, wenn das Kriterium nur „vollständig auf dem Monitor“ im Querformat verlangt; das Szenario ist grün. Die Beobachtung am hochkant montierten Monitor ist eine neue Erkenntnis aus dem Review, kein Mangel am vereinbarten Kriterium. Eine Begründung, ihn wegen des abgeschnittenen Texts nicht abzunehmen, ist ebenfalls vertretbar, wenn sie sich darauf stützt, dass der Mensa-Monitor zu „auf dem Monitor“ gehört. (1 Punkt)
- Berechne die Velocity von Sprint 4 und den neuen Durchschnitt über alle vier Sprints (Sprint 1: 10, Sprint 2: 21, Sprint 3: 13 Story Points). Erkläre, warum die halb fertigen Einträge nicht anteilig zählen. (3 Punkte)
Velocity Sprint 4 = MON-15 (2) + MON-07.5 (1) = 3 Story Points (bei der anderen Entscheidung zu MON-07.5 sind es 2). (1 Punkt)
Durchschnitt = (10 + 21 + 13 + 3) / 4 = 47 / 4 = 11,75 Story Points (bzw. 46 / 4 = 11,5). (1 Punkt)
Ein Eintrag ist fertig oder nicht fertig; ein Inkrement mit einer leeren Tabelle oder ungeprüftem Kontrast kann nicht ausgeliefert werden. Anteilige Punkte würden die Velocity schönrechnen und die nächste Planung verfälschen. (1 Punkt)
- Leite aus dem Protokoll mindestens drei Folgen für das Product Backlog bzw. den Prozess ab. (4 Punkte)
Je sinnvoller, begründeter Folge 1 Punkt, höchstens 4, zum Beispiel:
- MON-13d und MON-13e gehen unverändert mit ihrer Schätzung zurück ins Product Backlog; Thomas Becker ordnet sie neu, voraussichtlich weit oben, weil wenig Arbeit fehlt. Die Schätzung wird nicht nachträglich verkleinert.
- Für die Darstellung am hochkant montierten Monitor entsteht ein neues Abnahmekriterium (zum Beispiel AK-MON-07.6 „… auch auf dem Monitor der Mensa im Hochformat“) oder eine neue Story „Monitore im Hochformat“, die im nächsten Refinement geschätzt wird.
- Im Szenariogrundriss zu den Gesuchen fehlt ein Fall „Monitor ohne Gesuche ohne Ortsfilter“; das Team prüft, ob die leere Tabelle nur mit Ortsfilter auftritt, und ergänzt ein Beispiel.
- Prozess für die Retrospektive: Pipeline-Jobs dürfen für einen Merge nicht übersprungen werden; der Job
templateswird als Pflicht-Job eingerichtet (in GitLab: Merge nur bei erfolgreicher Pipeline). - Prozess: Das fehlende Review durch eine zweite Person fiel erst im Sprint Review auf; sie gehört vor den Merge (Einstellung „Genehmigung erforderlich“ im Merge Request).
- Thomas Becker möchte MON-13d trotzdem abnehmen: „Es fehlt doch nur ein Satz, den baut ihr nächste Woche ein. Die Schulleitung soll im Review sehen, dass wir die Gesuche geschafft haben.“ Nimm Stellung. (3 Punkte)
Der Wunsch ist verständlich: Der Fehler ist klein, und das Ergebnis soll sichtbar werden (1 Punkt). Dagegen spricht: Die DoD ist eine Vereinbarung des ganzen Scrum Teams; wird sie für einen Eintrag ausgesetzt, verliert sie für alle ihre Wirkung, und die Velocity zeigt Arbeit als fertig, die noch offen ist. Außerdem hat Thomas Becker AK-MON-13d.3 selbst vereinbart; das Szenario ist das vereinbarte Prüfmittel (1 Punkt). Vorschlag: Die Gesuche dürfen im Review als Zwischenstand gezeigt werden, ausdrücklich als „nicht fertig“; MON-13d bleibt im Product Backlog und wird im nächsten Sprint abgeschlossen. Will der Product Owner die Anforderung ändern (leere Tabelle ist akzeptabel), muss er das Kriterium im Refinement ändern, nicht im Review übergehen (1 Punkt). Andere begründete Stellungnahmen sind möglich, wenn sie DoD und Abnahmekriterien berücksichtigen.
Links und weitere Informationen
zum Lehrartikel: Akzeptanztests mit Gherkin, Cucumber und Selenium: Abnahmekriterien, die der Product Owner lesen kann
zum Szenario: Szenario Mitfahrlabor mit Personas und Flurmonitoren
als Nachschlagewerk: Gherkin-Referenz und Cucumber Expressions
zum Weiterlesen: Scrum Guide 2020 (deutsch) zu Sprint Review, Definition of Done und Inkrement
Hinweis zur Nachnutzung als Open Educational Resource (OER)
Dieser Artikel und seine Texte, Bilder, Grafiken, Code und sonstiger Inhalt sind - sofern nicht anders angegeben - lizenziert unter CC BY 4.0. Nennung gemäß TULLU-Regel bitte wie folgt: “Übungsaufgaben zu Akzeptanztests mit Gherkin und Cucumber: Szenarien, Step Definitions und Abnahmeprotokoll für die Mitfahrgesuche” von oer-informatik.de (H. Stein), Lizenz: CC BY 4.0. Der Artikel wurde unter https://oer-informatik.de/flurmonitor-akzeptanztest-uebungsaufgaben veröffentlicht, die Quelltexte sind in weiterverarbeitbarer Form verfügbar im Repository unter https://gitlab.com/oer-informatik/java-springboot/Backend. Erstellt mit KI-Assistenz; von mir umfassend redaktionell überarbeitet, geprüft und freigegeben. Stand: 11.11.2026.
[Kommentare zum Artikel lesen, schreiben] / [Artikel teilen] / [gitlab-Issue zum Artikel schreiben]
