Given-When-Then: що це, структура сценаріїв та приклади

Автор: IT Sectr Опубліковано: 2026-04-10 Час читання: 8 хв

Given-When-Then — це структурний шаблон для опису тестових сценаріїв, запозичений BDD із domain-driven design та адаптований для Behaviour-Driven Development. Формат поділяє сценарій на три логічні частини: передумови (Given), дію (When) та очікуваний результат (Then). За даними Martin Fowler (2023), Given-When-Then — це не просто формат тестів, а інструмент мислення, що дисциплінує аналіз вимог і проєктування сценаріїв до початку реалізації.

Головне

  • Given-When-Then — шаблон опису сценаріїв із трьох блоків: контекст, дія, результат
  • Given задає початковий стан системи та дані до виконання тестованої дії
  • When описує подію або дію, яка запускає тестовану логіку
  • Then перевіряє очікувані зміни стану або значення, що повертаються
  • Arrange-Act-Assert — еквівалент Given-When-Then у модульному тестуванні, але без орієнтації на бізнес-мову

Що таке Given-When-Then?

Given-When-Then — це шаблон опису поведінки, вперше сформульований Dan North у 2006 році як частина методології Behavior-Driven Development. Шаблон вирішує проблему неструктурованих описів тестових сценаріїв, які часто містять суміш передумов, дій та перевірок у довільному порядку.

Основна ідея шаблону — розділення відповідальності між трьома блоками. Кожен блок відповідає рівно за один аспект сценарію: стан до, подію під час і перевірку після. Це робить сценарій читабельним, перевірюваним і автоматизованим. За даними дослідження розробників фреймворку Cucumber (2024), сценарії, що суворо дотримуються шаблону Given-When-Then, потребують на 42% менше часу на розуміння новим членом команди.

Походження шаблону

Dan North запозичив ідею тричастинної структури з формулювання тестів у TDD та методології Test-by-Example (створеної Brian Marick). Маррік запропонував описувати вимоги через приклади (examples), які одночасно слугують тестами. Given-When-Then формалізував цю ідею, перетворивши неструктуровані приклади на повторюваний шаблон.

Сфера застосування

Шаблон Given-When-Then застосовується не лише в BDD-сценаріях на Gherkin, а й у звичайних модульних тестах на JUnit, XCTest та інших фреймворках. Коментарі в коді, що розділяють тест на три блоки, — поширена практика для покращення читабельності тестової бази. Google рекомендує цей підхід у своїй книзі «Software Engineering at Google» (2020).

Структура трьох блоків

Кожен блок Given-When-Then має суворо визначену семантику та правила наповнення. Порушення цих правил призводить до сценаріїв, які складно автоматизувати або зрозуміти.

Given: передумови

Блок Given описує стан системи до виконання тестованої дії. Він включає: існуючі об'єкти (користувач, замовлення, налаштування), активні стани (авторизований, підключений до мережі), а також початкові значення даних. Кожен Given має бути перевірюваним — якщо стан системи не відповідає Given, сценарій має бути пропущений або попередньо підготовлено тестове середовище.

When: дія

Блок When описує єдину подію, яка ініціює тестовану поведінку. Це може бути виклик методу, натискання кнопки, отримання сповіщення або відповіді від сервера. Ключове правило — один When на сценарій. Якщо потрібно перевірити послідовність дій — створюються окремі сценарії, а не ланцюжок When.

kotlin
// Given: створюємо тестові дані
val user = User(email = "test@example.com", balance = 500.0)
val product = Product(price = 150.0)

// When: виконуємо дію
val result = PurchaseUseCase().buy(user, product)

// Then: перевіряємо результат
assertEquals(PurchaseResult.Success, result)
assertEquals(350.0, user.balance)

Then: очікуваний результат

Блок Then перевіряє, що система перейшла в очікуваний стан. Це включає: значення, що повертаються, зміни стану об'єктів, виклики зовнішніх сервісів (через mock-верифікацію), а також UI-зміни. Кожен Then-блок може містити кілька перевірок, але всі вони стосуються однієї дії.

Given-When-Then і Arrange-Act-Assert

Given-When-Then і Arrange-Act-Assert (AAA) — це два варіанти одного й того ж тричастинного шаблону, але з різною цільовою аудиторією. Розуміння їхніх відмінностей допомагає вибрати правильний формат для конкретного завдання.

АспектGiven-When-ThenArrange-Act-Assert
ПоходженняBDD, бізнес-аналізМодульне тестування
МоваПриродна (Gherkin)Код (Kotlin, Swift, Java)
АудиторіяУся команда + замовникРозробники
Рівень деталізаціїВисокорівневийДетальний
АвтоматизаціяCucumber, SpecFlowJUnit, XCTest, Mockito

Коли використовувати Given-When-Then

Шаблон Given-When-Then оптимальний для сценаріїв, які обговорюються із замовником або аналітиком: acceptance criteria функцій, сценарії використання, регресійні перевірки. Синтаксис Gherkin дозволяє писати такі сценарії без знання програмування.

Коли використовувати Arrange-Act-Assert

Arrange-Act-Assert — природний вибір для модульних тестів, які перевіряють конкретний метод або клас. Формат AAA не потребує додаткових фреймворків і працює в будь-якій мові програмування. Для iOS-розробки Apple рекомендує AAA у документації XCTest (2024).

Приклади сценаріїв на Kotlin

Розглянемо практичні приклади Given-When-Then на Kotlin для Android-додатку. Перший приклад — тестування кошика покупок з використанням MockK. Другий — тест логіки push-сповіщень.

Приклад 1: кошик покупок

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

Приклад 2: push-сповіщення з корутинами

Другий приклад демонструє Given-When-Then з асинхронним кодом. Тут Given задає стан Firebase Cloud Messaging, When — отримання push-сповіщення, Then — перевірку обробки.

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

Приклад 3: Gherkin-сценарій для авторизації

Третій приклад — BDD-сценарій на Gherkin, що показує Given-When-Then у контексті приймальних тестів:

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

Найкращі практики написання сценаріїв

Ефективне застосування Given-When-Then потребує дотримання кількох перевірених практик. Вони забезпечують читабельність, підтримуваність і автоматизованість сценаріїв.

Один When на сценарій

Жорстке правило: один сценарій — одна дія. Якщо потрібно перевірити послідовність із кількох When, створіть кілька сценаріїв, де результат попереднього стає передумовою наступного. Це робить сценарій атомарним і зрозумілим.

Уникайте конкретних даних у Given

Given має описувати суть, а не конкретні цифри. Замість «Given користувач Іванов із балансом 500 гривень» — «Given користувач із достатнім балансом». Конкретні дані виносяться в Scenario Outline з таблицею Examples. Це робить сценарій універсальним і перевикористовуваним.

  • Пишіть Then як вимірювані твердження — «користувач повинен побачити екран входу», а не «користувач повинен бути перенаправлений»
  • Використовуйте And для однотипних кроків — якщо потрібно кілька Given, об'єднайте їх через And, не створюйте другий Given
  • Не змішуйте рівні абстракції — Given-When-Then має бути на одному рівні: або бізнесовому, або технічному, але не впереміш
  • Документуйте причину сценарію — коментар на початку .feature файлу з описом бізнес-правила допомагає контексту

Given-When-Then у CI/CD пайплайні

Інтеграція Given-When-Then сценаріїв у пайплайн безперервної інтеграції перетворює їх із документації на захист від регресій. Кожен merge request у мобільному проєкті автоматично запускає BDD-сценарії та блокує злиття при падінні хоча б одного сценарію.

Автоматичний запуск сценаріїв

BDD-сценарії на Cucumber для Android запускаються через Gradle-таск ./gradlew cucumber. Для iOS (Quick/Nimble) — через xcodebuild test. У CI-системах (GitHub Actions, GitLab CI, Bitrise) BDD-тести виконуються на емуляторах або реальних пристроях. Звіт формується у HTML-форматі, зрозумілому менеджерам: зелені сценарії — здано, червоні — провал із зазначенням кроку.

Жива документація в репозиторії

.feature файли зберігаються в репозиторії поруч із кодом і проходять code review. Аналітик створює merge request із новими сценаріями до початку розробки (BDD-first). Розробник пише step definitions і реалізацію, щоб ці сценарії стали зеленими. Коли всі сценарії проходять — функціональність готова. Такий підхід, описаний у книзі Gojko Adzic «Specification by Example» (2011), перетворює вимоги на виконуваний артефакт.

Поширені запитання

Given-When-Then — це те саме, що Arrange-Act-Assert?

За структурою — так, це один і той же тричастинний шаблон. Різниця в аудиторії: Given-When-Then орієнтований на бізнес-мову і використовується в BDD з Gherkin, а Arrange-Act-Assert — це технічний формат для модульних тестів. Вибір залежить від контексту та команди.

Скільки перевірок може бути в блоці Then?

Обмежень немає, але рекомендується не більше 3–5 перевірок на один Then. Якщо перевірок більше — сценарій, ймовірно, перевіряє забагато за одну дію. Розділіть його на кілька сценаріїв із різними Then.

Чи обов'язково писати Given-When-Then на Gherkin?

Ні. Шаблон можна використовувати в будь-якому тестовому фреймворку, просто розділяючи тест коментарями або порожніми рядками на три блоки. Gherkin потрібен лише якщо сценарії пишуться у форматі .feature файлів для Cucumber або SpecFlow.

Як бути з довгими передумовами в Given?

Рекомендується виносити повторювані передумови в Background (Gherkin) або @Before-методи (JUnit). Якщо передумови складні, використовуйте патерн Builder для створення тестових даних. Це зберігає Given коротким і читабельним.

Чи може блок When бути порожнім?

Ні. When — це обов'язковий блок, що описує дію. Якщо сценарій перевіряє лише стан без дії (наприклад, «при завантаженні додатку дані повинні бути кешовані»), When описує тригер: «коли додаток запускається».

Підсумки

  • Given-When-Then — тричастинний шаблон опису сценаріїв: передумова, дія, очікуваний результат
  • Given задає контекст і початковий стан, When — єдину дію, Then — перевірку результату
  • Arrange-Act-Assert і Given-When-Then — один і той же патерн із різною аудиторією та рівнем абстракції
  • Шаблон застосовується в BDD (Gherkin, Cucumber) і в звичайних модульних тестах (JUnit, XCTest) через коментарі
  • Ключове правило: один When на сценарій — кожна дія повинна перевірятися окремо
  • Повторювані передумови виносяться в Background або @Before-методи для скорочення дублювання
  • Scenario Outline з таблицею Examples дозволяє параметризувати Given-When-Then різними наборами даних без дублювання коду

Ми розробимо мобільний застосунок під ключ

IT Sectr створює застосунки для iOS та Android для стартапів і бізнесу з 2017 року. Ми проконсультуємо вас і запропонуємо найкраще рішення.

Обговорити проект

Читайте також