Given-When-Then ist ein strukturelles Muster zur Beschreibung von Testszenarien, das von BDD aus dem Domain-driven Design übernommen und für Behaviour-Driven Development adaptiert wurde. Das Format unterteilt das Szenario in drei logische Teile: Vorbedingungen (Given), Aktion (When) und erwartetes Ergebnis (Then). Laut Martin Fowler (2023) ist Given-When-Then nicht nur ein Testformat, sondern ein Denkwerkzeug, das die Anforderungsanalyse und die Szenariogestaltung vor Beginn der Implementierung diszipliniert.
Das Wichtigste
Given-When-Then ist ein Muster zur Verhaltensbeschreibung, das erstmals 2006 von Dan North als Teil der Methodik Behavior-Driven Development formuliert wurde. Das Muster löst das Problem unstrukturierter Beschreibungen von Testszenarien, die oft eine Mischung aus Vorbedingungen, Aktionen und Prüfungen in beliebiger Reihenfolge enthalten.
Die Hauptidee des Musters ist die Trennung von Verantwortlichkeiten zwischen drei Blöcken. Jeder Block ist für genau einen Aspekt des Szenarios verantwortlich: Zustand vorher, Ereignis während und Prüfung nachher. Dies macht das Szenario lesbar, überprüfbar und automatisierbar. Laut einer Studie der Entwickler des Cucumber-Frameworks (2024) benötigen Szenarien, die dem Given-When-Then-Muster strikt folgen, 42% weniger Zeit, um von einem neuen Teammitglied verstanden zu werden.
Dan North entlehnte die Idee der dreiteiligen Struktur der Formulierung von Tests in TDD und der Methodik Test-by-Example (entwickelt von Brian Marick). Marick schlug vor, Anforderungen durch Beispiele (examples) zu beschreiben, die gleichzeitig als Tests dienen. Given-When-Then formalisierte diese Idee und verwandelte unstrukturierte Beispiele in ein wiederholbares Muster.
Das Given-When-Then-Muster wird nicht nur in BDD-Szenarien mit Gherkin angewendet, sondern auch in gewöhnlichen Unit-Tests mit JUnit, XCTest und anderen Frameworks. Kommentare im Code, die den Test in drei Blöcke unterteilen, sind eine gängige Praxis zur Verbesserung der Lesbarkeit der Testbasis. Google empfiehlt diesen Ansatz in seinem Buch „Software Engineering at Google" (2020).
Jeder Block von Given-When-Then hat eine streng definierte Semantik und Befüllungsregeln. Die Verletzung dieser Regeln führt zu Szenarien, die schwer zu automatisieren oder zu verstehen sind.
Der Given-Block beschreibt den Zustand des Systems vor Ausführung der zu testenden Aktion. Er umfasst: vorhandene Objekte (Benutzer, Bestellung, Einstellungen), aktive Zustände (authentifiziert, mit Netzwerk verbunden) sowie Anfangswerte von Daten. Jedes Given muss überprüfbar sein — wenn der Systemzustand nicht dem Given entspricht, sollte das Szenario übersprungen oder die Testumgebung vorbereitet werden.
Der When-Block beschreibt das einzige Ereignis, das das zu testende Verhalten auslöst. Dies kann ein Methodenaufruf, ein Button-Klick, der Empfang einer Benachrichtigung oder einer Serverantwort sein. Die Schlüsselregel ist ein When pro Szenario. Wenn eine Abfolge von Aktionen überprüft werden muss, werden separate Szenarien erstellt, keine Kette von When.
// Given: Testdaten erstellen
val user = User(email = "test@example.com", balance = 500.0)
val product = Product(price = 150.0)
// When: Aktion ausführen
val result = PurchaseUseCase().buy(user, product)
// Then: Ergebnis überprüfen
assertEquals(PurchaseResult.Success, result)
assertEquals(350.0, user.balance)
Der Then-Block überprüft, ob das System in den erwarteten Zustand übergegangen ist. Dies umfasst: Rückgabewerte, Zustandsänderungen von Objekten, Aufrufe externer Dienste (durch Mock-Verifikation) sowie UI-Änderungen. Jeder Then-Block kann mehrere Prüfungen enthalten, aber alle beziehen sich auf eine einzige Aktion.
Given-When-Then und Arrange-Act-Assert (AAA) sind zwei Varianten desselben dreiteiligen Musters, jedoch mit unterschiedlichen Zielgruppen. Das Verständnis ihrer Unterschiede hilft, das richtige Format für eine bestimmte Aufgabe zu wählen.
| Aspekt | Given-When-Then | Arrange-Act-Assert |
|---|---|---|
| Ursprung | BDD, Geschäftsanalyse | Unit-Testing |
| Sprache | Natürlich (Gherkin) | Code (Kotlin, Swift, Java) |
| Zielgruppe | Ganzes Team + Kunde | Entwickler |
| Detailgrad | Hohe Ebene | Detailiert |
| Automatisierung | Cucumber, SpecFlow | JUnit, XCTest, Mockito |
Das Given-When-Then-Muster ist optimal für Szenarien, die mit dem Kunden oder Analysten besprochen werden: Abnahmekriterien von Features, Anwendungsfälle, Regressionstests. Die Gherkin-Syntax ermöglicht das Schreiben solcher Szenarien ohne Programmierkenntnisse.
Arrange-Act-Assert ist die natürliche Wahl für Unit-Tests, die eine bestimmte Methode oder Klasse überprüfen. Das AAA-Format erfordert keine zusätzlichen Frameworks und funktioniert in jeder Programmiersprache. Für die iOS-Entwicklung empfiehlt Apple AAA in der XCTest-Dokumentation (2024).
Betrachten wir praktische Beispiele für Given-When-Then in Kotlin für eine Android-Anwendung. Das erste Beispiel ist ein Test des Warenkorbs mit MockK. Das zweite ein Test der Push-Benachrichtigungslogik.
class CartTest {
fun `apply discount when total exceeds threshold`() {
// Given
val cart = Cart()
cart.addItem(Item("Laptop", price = 1000.0))
cart.addItem(Item("Mouse", price = 50.0))
val discount = DiscountCalculator(0.1)
// When
val total = discount.applyIfEligible(cart)
// Then
assertEquals(945.0, total)
assertTrue("Discount was not applied", total < 1050.0)
}
}
Das zweite Beispiel demonstriert Given-When-Then mit asynchronem Code. Hier legt Given den Zustand von Firebase Cloud Messaging fest, When — den Empfang einer Push-Benachrichtigung, Then — die Überprüfung der Verarbeitung.
class PushNotificationTest {
fun `handle push notification when app in background`() = runTest {
// Given
val prefs = mockk<SharedPreferences>()
every { prefs.getString("token", null) } returns "fcm-token-abc"
val handler = PushHandler(prefs)
// When
val data = RemoteMessage().apply {
putData("type", "order_update")
putData("order_id", "123")
}
val result = handler.handleNotification(data)
// Then
assertEquals(NotificationAction.OpenOrder("123"), result)
}
}
Das dritte Beispiel ist ein BDD-Szenario in Gherkin, das Given-When-Then im Kontext von Abnahmetests zeigt:
Feature: User Authorization
Scenario: User cannot login with expired token
Given the user has an expired refresh token
When they try to access the protected profile screen
Then they should see the login screen
And the app should clear all cached data
Die effektive Anwendung von Given-When-Then erfordert die Einhaltung mehrerer bewährter Praktiken. Sie gewährleisten Lesbarkeit, Wartbarkeit und Automatisierbarkeit der Szenarien.
Strenge Regel: ein Szenario — eine Aktion. Wenn eine Abfolge mehrerer When überprüft werden muss, erstellen Sie mehrere Szenarien, bei denen das Ergebnis des vorherigen zur Vorbedingung des nächsten wird. Dies macht das Szenario atomar und verständlich.
Given sollte das Wesen beschreiben, nicht konkrete Zahlen. Statt „Given Benutzer Ivanov mit Guthaben von 500 Rubel" — „Given ein Benutzer mit ausreichendem Guthaben". Konkrete Daten werden in ein Scenario Outline mit einer Examples-Tabelle ausgelagert. Dies macht das Szenario universell und wiederverwendbar.
Die Integration von Given-When-Then-Szenarien in die Continuous-Integration-Pipeline verwandelt sie von Dokumentation in einen Schutz vor Regressionen. Jeder Merge-Request in einem Mobilprojekt führt automatisch BDD-Szenarien aus und blockiert die Zusammenführung, wenn mindestens ein Szenario fehlschlägt.
BDD-Szenarien mit Cucumber für Android werden über die Gradle-Aufgabe ./gradlew cucumber ausgeführt. Für iOS (Quick/Nimble) — über xcodebuild test. In CI-Systemen (GitHub Actions, GitLab CI, Bitrise) werden BDD-Tests auf Emulatoren oder echten Geräten ausgeführt. Der Bericht wird im für Manager verständlichen HTML-Format erstellt: grüne Szenarien — bestanden, rote — Fehler mit Angabe des Schritts.
.feature-Dateien werden im Repository neben dem Code gespeichert und durchlaufen ein Code-Review. Der Analyst erstellt vor Entwicklungsbeginn (BDD-first) einen Merge-Request mit neuen Szenarien. Der Entwickler schreibt Schrittdefinitionen und die Implementierung, damit diese Szenarien grün werden. Wenn alle Szenarien bestehen — ist die Funktionalität fertig. Dieser Ansatz, beschrieben im Buch von Gojko Adzic „Specification by Example" (2011), verwandelt Anforderungen in ein ausführbares Artefakt.
Häufig gestellte Fragen
Strukturell gesehen ja, es ist dasselbe dreiteilige Muster. Der Unterschied liegt in der Zielgruppe: Given-When-Then ist auf die Geschäftssprache ausgerichtet und wird in BDD mit Gherkin verwendet, während Arrange-Act-Assert ein technisches Format für Unit-Tests ist. Die Wahl hängt vom Kontext und Team ab.
Es gibt keine Begrenzung, aber es wird empfohlen, nicht mehr als 3–5 Prüfungen pro Then zu verwenden. Bei mehr Prüfungen überprüft das Szenario wahrscheinlich zu viel in einer einzigen Aktion. Teilen Sie es in mehrere Szenarien mit verschiedenen Then auf.
Nein. Das Muster kann in jedem Test-Framework verwendet werden, indem der Test einfach mit Kommentaren oder Leerzeilen in drei Blöcke unterteilt wird. Gherkin wird nur benötigt, wenn die Szenarien im .feature-Format für Cucumber oder SpecFlow geschrieben werden.
Es wird empfohlen, wiederholte Vorbedingungen in Background (Gherkin) oder @Before-Methoden (JUnit) auszulagern. Bei komplexen Vorbedingungen verwenden Sie das Builder-Muster zum Erstellen von Testdaten. Dies hält Given kurz und lesbar.
Nein. When ist ein obligatorischer Block, der die Aktion beschreibt. Wenn das Szenario nur einen Zustand ohne Aktion überprüft (z.B. „beim Laden der Anwendung sollten die Daten zwischengespeichert sein"), beschreibt When den Auslöser: „wenn die Anwendung gestartet wird".
Zusammenfassung
Wir entwickeln eine mobile Applikation schlüsselfertig
IT Sectr entwickelt seit 2017 iOS- und Android-Apps für Startups und Unternehmen. Wir beraten Sie und schlagen die beste Lösung vor.
Lesen Sie auch