Given-When-Then — är en strukturell mall för att beskriva testscenarier, lånad av BDD från domain-driven design och anpassad för Behaviour-Driven Development. Formatet delar upp scenariot i tre logiska delar: förutsättningar (Given), handling (When) och förväntat resultat (Then). Enligt Martin Fowler (2023) är Given-When-Then inte bara ett testformat, utan ett tankeverktyg som disciplinerar kravanalys och design av scenarier innan implementeringen påbörjas.
Huvudpunkter
Given-When-Then — är ett mönster för att beskriva beteende, först formulerat av Dan North 2006 som en del av metodologin Behavior-Driven Development. Mönstret löser problemet med ostrukturerade beskrivningar av testscenarier som ofta innehåller en blandning av förutsättningar, handlingar och kontroller i godtycklig ordning.
Huvudidén med mönstret är ansvarsfördelning mellan de tre blocken. Varje block ansvarar för exakt en aspekt av scenariot: tillståndet före, händelsen under och kontrollen efter. Detta gör scenariot läsbart, verifierbart och automatiserbart. Enligt forskning av utvecklare av ramverket Cucumber (2024) kräver scenarier som strikt följer mönstret Given-When-Then 42% mindre tid att förstå för en ny teammedlem.
Dan North lånade idén om den tredelade strukturen från formulation of tests i TDD och metodologin Test-by-Example (skapad av Brian Marick). Marick föreslog att beskriva krav genom exempel (examples) som samtidigt fungerar som tester. Given-When-Then formaliserade denna idé och omvandlade ostrukturerade exempel till ett repeterbart mönster.
Mönstret Given-When-Then tillämpas inte bara i BDD-scenarier i Gherkin, utan också i vanliga enhetstester i JUnit, XCTest och andra ramverk. Kommentarer i koden som delar upp testet i tre block är en utbredd praxis för att förbättra läsbarheten av testbasen. Google rekommenderar detta tillvägagångssätt i sin bok „Software Engineering at Google” (2020).
Varje Given-When-Then-block har strikt definierad semantik och ifyllnadsregler. Brott mot dessa regler leder till scenarier som är svåra att automatisera eller förstå.
Blocket Given beskriver systemets tillstånd före utförandet av den testade handlingen. Det omfattar: befintliga objekt (användare, order, inställningar), aktiva tillstånd (auktoriserad, ansluten till nätverk) samt initiala datavärden. Varje Given måste vara verifierbart — om systemets tillstånd inte matchar Given bör scenariot hoppas över eller testmiljön förberedas i förväg.
Blocket When beskriver den enskilda händelsen som initierar det testade beteendet. Detta kan vara ett metodanrop, ett knapptryck, mottagande av en notifikation eller ett svar från servern. Nyckelregeln — en When per scenario. Om en sekvens av handlingar behöver kontrolleras skapas separata scenarier, inte en When-kedja.
// Given: skapa testdata
val user = User(email = "test@example.com", balance = 500.0)
val product = Product(price = 150.0)
// When: utför handlingen
val result = PurchaseUseCase().buy(user, product)
// Then: kontrollera resultatet
assertEquals(PurchaseResult.Success, result)
assertEquals(350.0, user.balance)
Blocket Then kontrollerar om systemet har övergått till det förväntade tillståndet. Detta omfattar: returvärden, förändringar i objekttillstånd, anrop av externa tjänster (via mock-verifiering) samt UI-förändringar. Varje Then-block kan innehålla flera kontroller, men alla hänför sig till en enda handling.
Given-When-Then och Arrange-Act-Assert (AAA) — är två varianter av samma tredelade mönster, men med olika målgrupp. Att förstå deras skillnader hjälper till att välja rätt format för en specifik uppgift.
| Aspekt | Given-When-Then | Arrange-Act-Assert |
|---|---|---|
| Ursprung | BDD, affärsanalys | Enhetstestning |
| Språk | Naturligt (Gherkin) | Kod (Kotlin, Swift, Java) |
| Målgrupp | Hela teamet + kund | Utvecklare |
| Detaljnivå | Hög nivå | Detaljerad |
| Automatisering | Cucumber, SpecFlow | JUnit, XCTest, Mockito |
Mönstret Given-When-Then är optimalt för scenarier som diskuteras med kunden eller analytikern: acceptanskriterier för funktioner, användningsscenarier, regressionstester. Gherkin-syntax gör det möjligt att skriva sådana scenarier utan programmeringskunskaper.
Arrange-Act-Assert — är det naturliga valet för enhetstester som kontrollerar en specifik metod eller klass. AAA-formatet kräver inga ytterligare ramverk och fungerar i vilket programmeringsspråk som helst. För iOS-utveckling rekommenderar Apple AAA i XCTest-dokumentationen (2024).
Låt oss titta på praktiska exempel på Given-When-Then i Kotlin för en Android-applikation. Det första exemplet — testning av en varukorg med MockK. Det andra — testning av logik för push-notifikationer.
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)
}
}
Det andra exemplet demonstrerar Given-When-Then med asynkron kod. Här anger Given tillståndet för Firebase Cloud Messaging, When — mottagandet av en push-notifikation, Then — kontroll av bearbetning.
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)
}
}
Det tredje exemplet — ett BDD-scenario i Gherkin, som visar Given-When-Then i kontexten av acceptanstester:
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
Effektiv användning av Given-When-Then kräver efterlevnad av flera beprövade metoder. De säkerställer scenariernas läsbarhet, underhållbarhet och automatiserbarhet.
Strikt regel: ett scenario — en handling. Om en sekvens av flera When behöver kontrolleras, skapa flera scenarier där resultatet av det föregående blir förutsättningen för nästa. Detta gör scenariot atomärt och begripligt.
Given bör beskriva essensen, inte specifika siffror. Istället för „Given användaren Ivanov med ett saldo på 500 rubel” — „Given användare med tillräckligt saldo”. Specifik data flyttas till Scenario Outline med en tabell Examples. Detta gör scenariot universellt och återanvändbart.
Integration av Given-When-Then-scenarier i pipeline för kontinuerlig integration förvandlar dem från dokumentation till skydd mot regressioner. Varje merge request i ett mobilprojekt startar automatiskt BDD-scenarier och blockerar sammanslagning om minst ett scenario misslyckas.
BDD-scenarier i Cucumber för Android startas via Gradle-uppgift ./gradlew cucumber. För iOS (Quick/Nimble) — via xcodebuild test. I CI-system (GitHub Actions, GitLab CI, Bitrise) körs BDD-tester på emulatorer eller verkliga enheter. Rapporten genereras i HTML-format, förståelig för chefer: gröna scenarier — godkända, röda — misslyckade med angivelse av steget.
.feature-filer lagras i repositoryt bredvid koden och genomgår code review. Analytikern skapar en merge request med nya scenarier före utvecklingsstart (BDD-first). Utvecklaren skriver step definitions och implementation för att dessa scenarier ska bli gröna. När alla scenarier passerar — är funktionaliteten klar. Detta tillvägagångssätt, beskrivet i Gojko Adzics bok „Specification by Example” (2011), omvandlar krav till ett körbart artefakt.
Vanliga frågor
Strukturmässigt — ja, det är samma tredelade mönster. Skillnaden ligger i målgruppen: Given-When-Then är inriktat på affärsspråk och används i BDD med Gherkin, medan Arrange-Act-Assert är ett tekniskt format för enhetstester. Valet beror på sammanhanget och teamet.
Det finns inga begränsningar, men det rekommenderas inte fler än 3–5 kontroller per Then. Om det finns fler kontroller testar scenariot sannolikt för mycket i en handling. Dela upp det i flera scenarier med olika Then.
Nej. Mönstret kan användas i vilket testramverk som helst, genom att helt enkelt dela upp testet med kommentarer eller tomma rader i tre block. Gherkin behövs bara om scenarier skrivs i .feature-filformat för Cucumber eller SpecFlow.
Det rekommenderas att flytta återkommande förutsättningar till Background (Gherkin) eller @Before-metoder (JUnit). Om förutsättningarna är komplexa, använd Builder-mönstret för att skapa testdata. Detta håller Given kort och läsbart.
Nej. When är ett obligatoriskt block som beskriver handlingen. Om scenariot endast kontrollerar tillstånd utan handling (till exempel „vid laddning av applikationen bör data cachas”), beskriver When utlösaren: „när applikationen startas”.
Sammanfattning
Vi utvecklar en mobil applikation nyckelfärdigt
IT Sectr skapar iOS- och Android-applikationer för startups och företag sedan 2017. Vi ger dig råd och föreslår den bästa lösningen.
Läs också