Given-When-Then: какво е, структура на сценарии и примери

Автор: IT Sectr Публикувано: 2026-04-10 Време за четене: 8 мин

Given-When-Then — е структурен шаблон за описване на тестови сценарии, заимстван от BDD от domain-driven design и адаптиран за Behaviour-Driven Development. Форматът разделя сценария на три логически части: предварителни условия (Given), действие (When) и очакван резултат (Then). Според Мартин Фаулър (2023), Given-When-Then не е просто формат за тестове, а инструмент за мислене, който дисциплинира анализа на изискванията и проектирането на сценарии преди започване на имплементацията.

Основни точки

  • Given-When-Then — шаблон за описание на сценарии от три блока: контекст, действие, резултат
  • Given задава началното състояние на системата и данните преди изпълнение на тестваното действие
  • When описва събитието или действието, което задейства тестваната логика
  • Then проверява очакваните промени в състоянието или върнатите стойности
  • Arrange-Act-Assert — еквивалент на Given-When-Then в unit тестването, но без ориентация към бизнес език

Какво е Given-When-Then?

Given-When-Then — е шаблон за описание на поведение, формулиран за първи път от Дан Норт през 2006 г. като част от методологията Behavior-Driven Development. Шаблонът решава проблема с неструктурираните описания на тестови сценарии, които често съдържат смесица от предварителни условия, действия и проверки в произволен ред.

Основната идея на шаблона е разделяне на отговорностите между трите блока. Всеки блок отговаря за точно един аспект на сценария: състояние преди, събитие по време и проверка след. Това прави сценария четим, проверим и автоматизируем. Според проучване на разработчиците на рамката Cucumber (2024), сценариите, които стриктно следват шаблона Given-When-Then, изискват 42% по-малко време за разбиране от нов член на екипа.

Произход на шаблона

Дан Норт заимства идеята за триделната структура от formulation of tests в TDD и методологията Test-by-Example (създадена от Брайън Марик). Марик предложи описването на изискванията чрез примери (examples), които едновременно служат като тестове. Given-When-Then формализира тази идея, превръщайки неструктурираните примери в повтаряем шаблон.

Област на приложение

Шаблонът Given-When-Then се прилага не само в BDD сценарии на Gherkin, но и в обикновени unit тестове на 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, бизнес анализUnit тестване
ЕзикЕстествен (Gherkin)Код (Kotlin, Swift, Java)
АудиторияЦелият екип + клиентРазработчици
Ниво на детайлностВисоко нивоДетайлно
АвтоматизацияCucumber, SpecFlowJUnit, XCTest, Mockito

Кога да използвате Given-When-Then

Шаблонът Given-When-Then е оптимален за сценарии, които се обсъждат с клиента или анализатора: критерии за приемане на функционалности, сценарии за използване, регресионни проверки. Синтаксисът на Gherkin позволява писането на такива сценарии без познания по програмиране.

Кога да използвате Arrange-Act-Assert

Arrange-Act-Assert — естественият избор за unit тестове, които проверяват конкретен метод или клас. Форматът 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 сценарии в пайплайна за непрекъсната интеграция ги превръща от документация в защита срещу регресии. Всяка заявка за сливане в мобилен проект автоматично стартира BDD сценарии и блокира сливането при неуспех на поне един сценарий.

Автоматично стартиране на сценарии

BDD сценариите в Cucumber за Android се стартират чрез Gradle задача ./gradlew cucumber. За iOS (Quick/Nimble) — чрез xcodebuild test. В CI системи (GitHub Actions, GitLab CI, Bitrise) BDD тестовете се изпълняват на емулатори или реални устройства. Отчетът се генерира в HTML формат, разбираем за мениджърите: зелени сценарии — преминали, червени — неуспех с посочване на стъпката.

Жива документация в хранилището

.feature файловете се съхраняват в хранилището до кода и преминават през code review. Анализаторът създава заявка за сливане с нови сценарии преди започване на разработката (BDD-first). Разработчикът пише дефиниции на стъпките и имплементация, за да станат тези сценарии зелени. Когато всички сценарии преминат — функционалността е готова. Този подход, описан в книгата на Гойко Аджич „Specification by Example” (2011), превръща изискванията в изпълним артефакт.

Често задавани въпроси

Given-When-Then — същото ли е като Arrange-Act-Assert?

Структурно — да, това е същият триделен шаблон. Разликата е в аудиторията: Given-When-Then е ориентиран към бизнес език и се използва в BDD с Gherkin, докато Arrange-Act-Assert е технически формат за unit тестове. Изборът зависи от контекста и екипа.

Колко проверки могат да бъдат в блок 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) и в обикновени unit тестове (JUnit, XCTest) чрез коментари
  • Ключово правило: един When на сценарий — всяко действие трябва да се проверява отделно
  • Повтарящите се предварителни условия се преместват в Background или @Before методи за намаляване на дублирането
  • Scenario Outline с таблица Examples позволява параметризиране на Given-When-Then с различни набори от данни без дублиране на код

Ще разработим мобилно приложение под ключ

IT Sectr създава iOS и Android приложения за стартъпи и бизнеси от 2017 г. Ще ви консултираме и ще предложим най-доброто решение.

Обсъдете проекта

Прочетете също