Given-When-Then: co to jest, struktura scenariuszy i przykłady

Autor: IT Sectr Opublikowano: 2026-04-10 Czas czytania: 8 min

Given-When-Then — to strukturalny wzorzec opisywania scenariuszy testowych, zapożyczony przez BDD z domain-driven design i zaadaptowany dla Behaviour-Driven Development. Format dzieli scenariusz na trzy logiczne części: warunki wstępne (Given), akcję (When) i oczekiwany rezultat (Then). Według Martin Fowler (2023), Given-When-Then to nie tylko format testów, ale narzędzie myślenia, dyscyplinujące analizę wymagań i projektowanie scenariuszy przed rozpoczęciem implementacji.

Najważniejsze

  • Given-When-Then — wzorzec opisywania scenariuszy z trzech bloków: kontekst, akcja, rezultat
  • Given określa początkowy stan systemu i dane przed wykonaniem testowanej akcji
  • When opisuje zdarzenie lub akcję, która uruchamia testowaną logikę
  • Then sprawdza oczekiwane zmiany stanu lub zwracane wartości
  • Arrange-Act-Assert — odpowiednik Given-When-Then w testach jednostkowych, ale bez orientacji na język biznesowy

Co to jest Given-When-Then?

Given-When-Then — to wzorzec opisywania zachowania, po raz pierwszy sformułowany przez Dana Northa w 2006 roku jako część metodologii Behavior-Driven Development. Wzorzec rozwiązuje problem nieustrukturyzowanych opisów scenariuszy testowych, które często zawierają mieszankę warunków wstępnych, akcji i sprawdzeń w dowolnej kolejności.

Główną ideą wzorca jest podział odpowiedzialności między trzy bloki. Każdy blok odpowiada za dokładnie jeden aspekt scenariusza: stan przed, zdarzenie w trakcie i sprawdzenie po. To czyni scenariusz czytelnym, weryfikowalnym i automatyzowalnym. Według badań deweloperów frameworka Cucumber (2024), scenariusze ściśle stosujące wzorzec Given-When-Then wymagają o 42% mniej czasu na zrozumienie przez nowego członka zespołu.

Pochodzenie wzorca

Dan North zapożyczył ideę trójczęściowej struktury z formulation of tests w TDD i metodologii Test-by-Example (stworzonej przez Briana Maricka). Marick zaproponował opisywanie wymagań przez przykłady (examples), które jednocześnie służą jako testy. Given-When-Then sformalizował tę ideę, przekształcając nieustrukturyzowane przykłady w powtarzalny wzorzec.

Obszar zastosowania

Wzorzec Given-When-Then jest stosowany nie tylko w scenariuszach BDD w Gherkin, ale także w zwykłych testach jednostkowych w JUnit, XCTest i innych frameworkach. Komentarze w kodzie, dzielące test na trzy bloki, to powszechna praktyka poprawiająca czytelność bazy testowej. Google zaleca to podejście w swojej książce „Software Engineering at Google” (2020).

Struktura trzech bloków

Każdy blok Given-When-Then ma ściśle określoną semantykę i reguły wypełniania. Naruszenie tych reguł prowadzi do scenariuszy, które trudno zautomatyzować lub zrozumieć.

Given: warunki wstępne

Blok Given opisuje stan systemu przed wykonaniem testowanej akcji. Obejmuje: istniejące obiekty (użytkownik, zamówienie, ustawienia), aktywne stany (zalogowany, podłączony do sieci), a także początkowe wartości danych. Każdy Given powinien być weryfikowalny — jeśli stan systemu nie odpowiada Given, scenariusz powinien zostać pominięty lub środowisko testowe powinno zostać wcześniej przygotowane.

When: akcja

Blok When opisuje pojedyncze zdarzenie, które inicjuje testowane zachowanie. Może to być wywołanie metody, naciśnięcie przycisku, otrzymanie powiadomienia lub odpowiedzi z serwera. Kluczową zasadą jest jeden When na scenariusz. Jeśli trzeba sprawdzić sekwencję akcji — tworzone są osobne scenariusze, a nie łańcuch When.

kotlin
// Given: tworzymy dane testowe
val user = User(email = "test@example.com", balance = 500.0)
val product = Product(price = 150.0)

// When: wykonujemy akcję
val result = PurchaseUseCase().buy(user, product)

// Then: sprawdzamy rezultat
assertEquals(PurchaseResult.Success, result)
assertEquals(350.0, user.balance)

Then: oczekiwany rezultat

Blok Then sprawdza, czy system przeszedł w oczekiwany stan. Obejmuje to: zwracane wartości, zmiany stanu obiektów, wywołania zewnętrznych serwisów (przez mock-weryfikację), a także zmiany UI. Każdy blok Then może zawierać wiele sprawdzeń, ale wszystkie odnoszą się do jednej akcji.

Given-When-Then a Arrange-Act-Assert

Given-When-Then i Arrange-Act-Assert (AAA) — to dwa warianty tego samego trójczęściowego wzorca, ale z różną grupą docelową. Zrozumienie ich różnic pomaga wybrać odpowiedni format dla konkretnego zadania.

AspektGiven-When-ThenArrange-Act-Assert
PochodzenieBDD, analiza biznesowaTesty jednostkowe
JęzykNaturalny (Gherkin)Kod (Kotlin, Swift, Java)
Grupa docelowaCały zespół + klientDeweloperzy
Poziom szczegółowościWysokopoziomowySzczegółowy
AutomatyzacjaCucumber, SpecFlowJUnit, XCTest, Mockito

Kiedy stosować Given-When-Then

Wzorzec Given-When-Then jest optymalny dla scenariuszy, które są omawiane z klientem lub analitykiem: kryteria akceptacji funkcji, scenariusze użycia, sprawdzenia regresyjne. Składnia Gherkin pozwala pisać takie scenariusze bez znajomości programowania.

Kiedy stosować Arrange-Act-Assert

Arrange-Act-Assert — to naturalny wybór dla testów jednostkowych, które sprawdzają konkretną metodę lub klasę. Format AAA nie wymaga dodatkowych frameworków i działa w każdym języku programowania. Do rozwoju iOS Apple zaleca AAA w dokumentacji XCTest (2024).

Przykłady scenariuszy w Kotlin

Rozważmy praktyczne przykłady Given-When-Then w Kotlin dla aplikacji Android. Pierwszy przykład — testowanie koszyka zakupów z użyciem MockK. Drugi — test logiki powiadomień push.

Przykład 1: koszyk zakupów

kotlin
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)
    }
}

Przykład 2: powiadomienia push z corutinami

Drugi przykład demonstruje Given-When-Then z kodem asynchronicznym. Tutaj Given określa stan Firebase Cloud Messaging, When — otrzymanie powiadomienia push, Then — sprawdzenie przetwarzania.

kotlin
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)
    }
}

Przykład 3: scenariusz Gherkin dla autoryzacji

Trzeci przykład — scenariusz BDD w Gherkin, pokazujący Given-When-Then w kontekście testów akceptacyjnych:

gherkin
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

Najlepsze praktyki pisania scenariuszy

Efektywne stosowanie Given-When-Then wymaga przestrzegania kilku sprawdzonych praktyk. Zapewniają one czytelność, utrzymywalność i automatyzowalność scenariuszy.

Jeden When na scenariusz

Sztywna zasada: jeden scenariusz — jedna akcja. Jeśli trzeba sprawdzić sekwencję kilku When, utwórz kilka scenariuszy, gdzie rezultat poprzedniego staje się warunkiem wstępnym następnego. To czyni scenariusz atomowym i zrozumiałym.

Unikaj konkretnych danych w Given

Given powinien opisywać istotę, a nie konkretne liczby. Zamiast „Given użytkownik Iwanow z saldem 500 rubli” — „Given użytkownik z wystarczającym saldem”. Konkretne dane są przenoszone do Scenario Outline z tabelą Examples. To czyni scenariusz uniwersalnym i wielokrotnego użytku.

  • Pisz Then jako mierzalne twierdzenia — „użytkownik powinien zobaczyć ekran logowania”, a nie „użytkownik powinien zostać przekierowany”
  • Używaj And dla podobnych kroków — jeśli potrzeba kilka Given, połącz je przez And, nie twórz drugiego Given
  • Nie mieszaj poziomów abstrakcji — Given-When-Then powinien być na jednym poziomie: biznesowym lub technicznym, ale nie na zmianę
  • Dokumentuj powód scenariusza — komentarz na początku pliku .feature z opisem reguły biznesowej pomaga w kontekście

Given-When-Then w pipeline CI/CD

Integracja scenariuszy Given-When-Then z pipeline ciągłej integracji przekształca je z dokumentacji w ochronę przed regresjami. Każde merge request w projekcie mobilnym automatycznie uruchamia scenariusze BDD i blokuje scalenie w przypadku upadku choćby jednego scenariusza.

Automatyczne uruchamianie scenariuszy

Scenariusze BDD w Cucumber dla Androida są uruchamiane przez Gradle task ./gradlew cucumber. Dla iOS (Quick/Nimble) — przez xcodebuild test. W systemach CI (GitHub Actions, GitLab CI, Bitrise) testy BDD są wykonywane na emulatorach lub rzeczywistych urządzeniach. Raport jest generowany w formacie HTML, zrozumiałym dla menedżerów: zielone scenariusze — zaliczone, czerwone — porażka z wskazaniem kroku.

Żywa dokumentacja w repozytorium

Pliki .feature są przechowywane w repozytorium obok kodu i przechodzą code review. Analityk tworzy merge request z nowymi scenariuszami przed rozpoczęciem rozwoju (BDD-first). Deweloper pisze step definitions i implementację, aby te scenariusze stały się zielone. Gdy wszystkie scenariusze przechodzą — funkcjonalność jest gotowa. Takie podejście, opisane w książce Gojko Adzica „Specification by Example” (2011), przekształca wymagania w wykonywalny artefakt.

Często zadawane pytania

Given-When-Then — czy to to samo co Arrange-Act-Assert?

Pod względem struktury — tak, to ten sam trójczęściowy wzorzec. Różnica polega na grupie docelowej: Given-When-Then jest zorientowany na język biznesowy i używany w BDD z Gherkin, a Arrange-Act-Assert to techniczny format dla testów jednostkowych. Wybór zależy od kontekstu i zespołu.

Ile sprawdzeń może być w bloku Then?

Nie ma ograniczeń, ale zaleca się nie więcej niż 3–5 sprawdzeń na jeden Then. Jeśli sprawdzeń jest więcej — scenariusz prawdopodobnie testuje zbyt wiele w jednej akcji. Podziel go na kilka scenariuszy z różnymi Then.

Czy obowiązkowo jest pisać Given-When-Then w Gherkin?

Nie. Wzorzec można stosować w dowolnym frameworku testowym, po prostu dzieląc test komentarzami lub pustymi wierszami na trzy bloki. Gherkin jest potrzebny tylko wtedy, gdy scenariusze są pisane w formacie plików .feature dla Cucumber lub SpecFlow.

Co robić z długimi warunkami wstępnymi w Given?

Zaleca się przenoszenie powtarzających się warunków wstępnych do Background (Gherkin) lub metod @Before (JUnit). Jeśli warunki wstępne są złożone, użyj wzorca Builder do tworzenia danych testowych. To utrzymuje Given krótkim i czytelnym.

Czy blok When może być pusty?

Nie. When to obowiązkowy blok opisujący akcję. Jeśli scenariusz sprawdza tylko stan bez akcji (na przykład „przy ładowaniu aplikacji dane powinny być buforowane”), When opisuje wyzwalacz: „kiedy aplikacja się uruchamia”.

Podsumowanie

  • Given-When-Then — trójczęściowy wzorzec opisywania scenariuszy: warunek wstępny, akcja, oczekiwany rezultat
  • Given określa kontekst i stan początkowy, When — pojedynczą akcję, Then — sprawdzenie rezultatu
  • Arrange-Act-Assert i Given-When-Then — ten sam wzorzec z różną grupą docelową i poziomem abstrakcji
  • Wzorzec jest stosowany w BDD (Gherkin, Cucumber) i w zwykłych testach jednostkowych (JUnit, XCTest) przez komentarze
  • Kluczowa zasada: jeden When na scenariusz — każda akcja powinna być testowana osobno
  • Powtarzające się warunki wstępne są przenoszone do Background lub metod @Before w celu zmniejszenia duplikacji
  • Scenario Outline z tabelą Examples pozwala parametryzować Given-When-Then różnymi zestawami danych bez duplikowania kodu

Opracujemy aplikację mobilną pod klucz

IT Sectr tworzy aplikacje na iOS i Androida dla startupów i firm od 2017 roku. Doradzimy Ci i zaproponujemy najlepsze rozwiązanie.

Omów projekt

Przeczytaj również