Given-When-Then: What It Is, Scenario Structure and Examples

Author: IT Sectr Published: 2026-04-10 Reading time: 8 min

Given-When-Then is a structural pattern for describing test scenarios, borrowed by BDD from domain-driven design and adapted for Behaviour-Driven Development. The format divides a scenario into three logical parts: preconditions (Given), action (When), and expected result (Then). According to Martin Fowler (2023), Given-When-Then is not just a test format but a thinking tool that disciplines requirements analysis and scenario design before implementation begins.

Key Takeaways

  • Given-When-Then is a scenario description pattern with three blocks: context, action, result
  • Given sets the initial system state and data before executing the tested action
  • When describes the event or action that triggers the logic under test
  • Then verifies expected state changes or return values
  • Arrange-Act-Assert is the equivalent of Given-When-Then in unit testing, but without a business language orientation

What Is Given-When-Then?

Given-When-Then is a behavior description pattern first formulated by Dan North in 2006 as part of the Behavior-Driven Development methodology. The pattern solves the problem of unstructured test scenario descriptions that often mix preconditions, actions, and assertions in arbitrary order.

The core idea of the pattern is separation of concerns among three blocks. Each block is responsible for exactly one aspect of the scenario: the state before, the event during, and the verification after. This makes the scenario readable, verifiable, and automatable. According to research by the Cucumber framework developers (2024), scenarios that strictly follow the Given-When-Then pattern require 42% less time for a new team member to understand.

Origin of the Pattern

Dan North borrowed the idea of a three-part structure from the formulation of tests in TDD and the Test-by-Example methodology (created by Brian Marick). Marick proposed describing requirements through examples that simultaneously serve as tests. Given-When-Then formalized this idea, turning unstructured examples into a repeatable pattern.

Scope of Application

The Given-When-Then pattern is used not only in BDD scenarios in Gherkin but also in regular unit tests using JUnit, XCTest, and other frameworks. Comments in code that separate the test into three blocks are a common practice for improving test base readability. Google recommends this approach in its book “Software Engineering at Google” (2020).

Structure of the Three Blocks

Each Given-When-Then block has a strictly defined semantics and filling rules. Violating these rules leads to scenarios that are difficult to automate or understand.

Given: Preconditions

The Given block describes the system state before executing the tested action. It includes: existing objects (user, order, settings), active states (authorized, connected to the network), and initial data values. Each Given must be verifiable — if the system state does not match the Given, the scenario should be skipped or the test environment should be pre-configured.

When: Action

The When block describes a single event that initiates the behavior under test. This can be a method call, a button click, receiving a notification, or a server response. The key rule is one When per scenario. If you need to verify a sequence of actions, create separate scenarios rather than a chain of Whens.

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

// When: perform the action
val result = PurchaseUseCase().buy(user, product)

// Then: verify the result
assertEquals(PurchaseResult.Success, result)
assertEquals(350.0, user.balance)

Then: Expected Result

The Then block verifies that the system has transitioned to the expected state. This includes: return values, changes in object states, calls to external services (via mock verification), and UI changes. Each Then block can contain multiple assertions, but all of them relate to a single action.

Given-When-Then and Arrange-Act-Assert

Given-When-Then and Arrange-Act-Assert (AAA) are two variants of the same three-part pattern, but with different target audiences. Understanding their differences helps choose the right format for a specific task.

AspectGiven-When-ThenArrange-Act-Assert
OriginBDD, business analysisUnit testing
LanguageNatural (Gherkin)Code (Kotlin, Swift, Java)
AudienceEntire team + stakeholdersDevelopers
Level of DetailHigh-levelDetailed
AutomationCucumber, SpecFlowJUnit, XCTest, Mockito

When to Use Given-When-Then

The Given-When-Then pattern is optimal for scenarios discussed with clients or analysts: feature acceptance criteria, use cases, regression checks. Gherkin syntax allows writing such scenarios without programming knowledge.

When to Use Arrange-Act-Assert

Arrange-Act-Assert is the natural choice for unit tests that verify a specific method or class. The AAA format requires no additional frameworks and works in any programming language. For iOS development, Apple recommends AAA in the XCTest documentation (2024).

Scenario Examples in Kotlin

Let’s look at practical Given-When-Then examples in Kotlin for an Android application. The first example tests a shopping cart using MockK. The second tests push notification logic.

Example 1: Shopping Cart

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

Example 2: Push Notifications with Coroutines

The second example demonstrates Given-When-Then with asynchronous code. Here Given sets the Firebase Cloud Messaging state, When receives a push notification, and Then verifies the processing.

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

Example 3: Gherkin Scenario for Authorization

The third example is a BDD scenario in Gherkin, showing Given-When-Then in the context of acceptance tests:

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

Best Practices for Writing Scenarios

Effective application of Given-When-Then requires following several proven practices. They ensure readability, maintainability, and automability of scenarios.

One When per Scenario

Strict rule: one scenario — one action. If you need to verify a sequence of multiple Whens, create several scenarios where the result of the previous one becomes the precondition of the next. This makes the scenario atomic and clear.

Avoid Concrete Data in Given

Given should describe the essence, not specific numbers. Instead of “Given user Ivanov with a balance of 500 rubles” — “Given a user with sufficient balance.” Specific data is moved to a Scenario Outline with an Examples table. This makes the scenario universal and reusable.

  • Write Then as measurable assertions — “the user should see the login screen”, not “the user should be redirected”
  • Use And for similar steps — if multiple Givens are needed, combine them with And, do not create a second Given
  • Do not mix abstraction levels — Given-When-Then should be at one level: either business or technical, not mixed
  • Document the scenario’s reason — a comment at the beginning of the .feature file describing the business rule helps provide context

Given-When-Then in CI/CD Pipeline

Integrating Given-When-Then scenarios into the continuous integration pipeline turns them from documentation into regression protection. Each merge request in a mobile project automatically runs BDD scenarios and blocks merging if at least one scenario fails.

Automatic Scenario Execution

BDD scenarios on Cucumber for Android are run via a Gradle task ./gradlew cucumber. For iOS (Quick/Nimble) — via xcodebuild test. In CI systems (GitHub Actions, GitLab CI, Bitrise), BDD tests run on emulators or real devices. The report is generated in HTML format understandable to managers: green scenarios — passed, red ones — failed with the failing step indicated.

Living Documentation in the Repository

.feature files are stored in the repository alongside the code and go through code review. An analyst creates a merge request with new scenarios before development starts (BDD-first). The developer writes step definitions and implementation to make these scenarios pass. When all scenarios pass — the functionality is ready. This approach, described in Gojko Adzic’s book “Specification by Example” (2011), turns requirements into an executable artifact.

Frequently Asked Questions

Is Given-When-Then the same as Arrange-Act-Assert?

In terms of structure — yes, it is the same three-part pattern. The difference is in the audience: Given-When-Then is oriented toward business language and used in BDD with Gherkin, while Arrange-Act-Assert is a technical format for unit tests. The choice depends on the context and the team.

How many assertions can be in a Then block?

There are no strict limits, but it is recommended to have no more than 3–5 assertions per Then. If there are more assertions, the scenario is probably testing too much in a single action. Split it into several scenarios with different Then blocks.

Is it mandatory to write Given-When-Then in Gherkin?

No. The pattern can be used in any test framework by simply separating the test into three blocks with comments or blank lines. Gherkin is only needed if scenarios are written in .feature file format for Cucumber or SpecFlow.

What about long preconditions in Given?

It is recommended to extract repeating preconditions into Background (Gherkin) or @Before methods (JUnit). If preconditions are complex, use the Builder pattern to create test data. This keeps Given short and readable.

Can the When block be empty?

No. When is a mandatory block that describes the action. If a scenario only verifies a state without an action (for example, “when the application loads, data should be cached”), When describes the trigger: “when the application starts.”

Summary

  • Given-When-Then is a three-part scenario description pattern: precondition, action, expected result
  • Given sets the context and initial state, When — the single action, Then — result verification
  • Arrange-Act-Assert and Given-When-Then are the same pattern with different audiences and abstraction levels
  • The pattern is used in BDD (Gherkin, Cucumber) and in regular unit tests (JUnit, XCTest) via comments
  • Key rule: one When per scenario — each action should be verified separately
  • Repeating preconditions are extracted into Background or @Before methods to reduce duplication
  • Scenario Outline with an Examples table allows parameterizing Given-When-Then with different data sets without code duplication

We will develop a mobile application turnkey

IT Sectr creates iOS and Android applications for startups and businesses since 2017. We will advise you and propose the best solution.

Discuss the project

Read also