Given-When-Then — ay isang istrukturang pattern para sa paglalarawan ng mga senaryo ng pagsubok, na kinuha ng BDD mula sa domain-driven design at inangkop para sa Behaviour-Driven Development. Hinahati ng format ang senaryo sa tatlong lohikal na bahagi: mga precondition (Given), aksyon (When) at inaasahang resulta (Then). Ayon kay Martin Fowler (2023), ang Given-When-Then ay hindi lamang isang format ng pagsubok, kundi isang kasangkapan sa pag-iisip na nagdidisiplina sa pagsusuri ng mga kinakailangan at pagdidisenyo ng mga senaryo bago magsimula ang implementasyon.
Mga Pangunahing Punto
Given-When-Then — ay isang pattern ng paglalarawan ng pag-uugali, na unang binuo ni Dan North noong 2006 bilang bahagi ng metodolohiya ng Behavior-Driven Development. Nilulutas ng pattern ang problema ng hindi nakaayos na mga paglalarawan ng senaryo ng pagsubok, na kadalasang naglalaman ng halo ng mga precondition, aksyon at pagsusuri sa di-makatwirang pagkakasunud-sunod.
Ang pangunahing ideya ng pattern ay paghihiwalay ng mga responsibilidad sa pagitan ng tatlong bloke. Ang bawat bloke ay may pananagutan para sa eksaktong isang aspeto ng senaryo: estado bago, kaganapan habang, at pagsusuri pagkatapos. Ginagawa nitong nababasa, napapatunayan at nai-automate ang senaryo. Ayon sa pananaliksik ng mga developer ng Cucumber framework (2024), ang mga senaryo na mahigpit na sumusunod sa pattern na Given-When-Then ay nangangailangan ng 42% mas kaunting oras upang maunawaan ng isang bagong miyembro ng koponan.
Kinuha ni Dan North ang ideya ng tatlong-bahaging istraktura mula sa formulation of tests sa TDD at metodolohiyang Test-by-Example (nilikha ni Brian Marick). Iminungkahi ni Marick na ilarawan ang mga kinakailangan sa pamamagitan ng mga halimbawa (examples) na sabay na nagsisilbing mga pagsubok. Pormalisado ng Given-When-Then ang ideyang ito, na ginagawang isang mauulit na pattern ang hindi nakaayos na mga halimbawa.
Ang pattern na Given-When-Then ay inilalapat hindi lamang sa mga senaryo ng BDD sa Gherkin, kundi pati na rin sa mga ordinaryong unit test sa JUnit, XCTest at iba pang frameworks. Ang mga komento sa code na naghahati sa pagsubok sa tatlong bloke — isang karaniwang kasanayan para sa pagpapabuti ng pagiging nababasa ng base ng pagsubok. Inirerekomenda ng Google ang pamamaraang ito sa aklat nitong “Software Engineering at Google” (2020).
Ang bawat bloke ng Given-When-Then ay may mahigpit na tinukoy na semantika at mga panuntunan sa pagpupuno. Ang paglabag sa mga panuntunang ito ay humahantong sa mga senaryo na mahirap i-automate o maunawaan.
Ang bloke na Given ay naglalarawan ng estado ng sistema bago isagawa ang sinusubok na aksyon. Kabilang dito: mga umiiral na bagay (gumagamit, order, setting), mga aktibong estado (naka-log in, naka-konekta sa network), pati na rin ang mga paunang halaga ng data. Ang bawat Given ay dapat na mapatunayan — kung ang estado ng sistema ay hindi tumutugma sa Given, ang senaryo ay dapat laktawan o ang kapaligiran ng pagsubok ay ihanda nang maaga.
Ang bloke na When ay naglalarawan ng iisang kaganapan na nagpapasimula ng sinusubok na pag-uugali. Ito ay maaaring isang pagtawag ng pamamaraan, pagpindot ng buton, pagtanggap ng notipikasyon o tugon mula sa server. Ang pangunahing panuntunan — isang When bawat senaryo. Kung kailangang suriin ang pagkakasunod-sunod ng mga aksyon, gumawa ng hiwalay na mga senaryo, hindi isang kadena ng When.
// Given: gumagawa ng data ng pagsubok
val user = User(email = "test@example.com", balance = 500.0)
val product = Product(price = 150.0)
// When: isinasagawa ang aksyon
val result = PurchaseUseCase().buy(user, product)
// Then: sinusuri ang resulta
assertEquals(PurchaseResult.Success, result)
assertEquals(350.0, user.balance)
Ang bloke na Then ay sumusuri kung ang sistema ay lumipat sa inaasahang estado. Kabilang dito: mga ibinalik na halaga, pagbabago sa estado ng mga bagay, pagtawag sa mga panlabas na serbisyo (sa pamamagitan ng pagpapatunay ng mock), pati na rin mga pagbabago sa UI. Ang bawat bloke ng Then ay maaaring maglaman ng maraming pagsusuri, ngunit lahat ay nauugnay sa isang aksyon.
Given-When-Then at Arrange-Act-Assert (AAA) — dalawang variant ng parehong tatlong-bahaging pattern, ngunit may iba't ibang target na madla. Ang pag-unawa sa kanilang mga pagkakaiba ay tumutulong sa pagpili ng tamang format para sa isang partikular na gawain.
| Aspekto | Given-When-Then | Arrange-Act-Assert |
|---|---|---|
| Pinagmulan | BDD, pagsusuri ng negosyo | Unit testing |
| Wika | Natural (Gherkin) | Code (Kotlin, Swift, Java) |
| Madla | Buong koponan + kliyente | Mga developer |
| Antas ng detalye | Mataas na antas | Detalyado |
| Automation | Cucumber, SpecFlow | JUnit, XCTest, Mockito |
Ang pattern na Given-When-Then ay optimal para sa mga senaryo na tinalakay sa kliyente o analista: mga pamantayan sa pagtanggap ng feature, mga senaryo ng paggamit, mga pagsusuri sa regression. Ang sintaks ng Gherkin ay nagpapahintulot sa pagsulat ng gayong mga senaryo nang walang kaalaman sa programming.
Arrange-Act-Assert — ang natural na pagpipilian para sa mga unit test na sumusuri ng isang partikular na pamamaraan o klase. Ang format na AAA ay hindi nangangailangan ng karagdagang mga framework at gumagana sa anumang programming language. Para sa pag-develop ng iOS, inirerekomenda ng Apple ang AAA sa dokumentasyon ng XCTest (2024).
Tingnan natin ang mga praktikal na halimbawa ng Given-When-Then sa Kotlin para sa isang Android application. Ang unang halimbawa — pagsubok ng shopping cart gamit ang MockK. Ang pangalawa — pagsubok ng lohika ng push notification.
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)
}
}
Ang pangalawang halimbawa ay nagpapakita ng Given-When-Then na may asynchronous na code. Dito, ang Given ay nagtatakda ng estado ng Firebase Cloud Messaging, When — pagtanggap ng push notification, Then — pagsusuri ng pagproseso.
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)
}
}
Ang pangatlong halimbawa — BDD scenario sa Gherkin na nagpapakita ng Given-When-Then sa konteksto ng acceptance testing:
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
Ang epektibong paggamit ng Given-When-Then ay nangangailangan ng pagsunod sa ilang napatunayang kasanayan. Tinitiyak nito ang pagiging nababasa, mapananatili at nai-automate ng mga senaryo.
Mahigpit na panuntunan: isang senaryo — isang aksyon. Kung kailangang suriin ang pagkakasunod-sunod ng maraming When, lumikha ng maraming senaryo kung saan ang resulta ng nauna ay nagiging precondition ng susunod. Ginagawa nitong atomic at naiintindihan ang senaryo.
Ang Given ay dapat ilarawan ang esensya, hindi ang mga konkretong numero. Sa halip na “Given user Ivanov na may balance na 500 rubles” — “Given user na may sapat na balance”. Ang konkretong data ay inililipat sa Scenario Outline na may talahanayan ng Examples. Ginagawa nitong unibersal at magagamit muli ang senaryo.
Ang pagsasama ng mga senaryo ng Given-When-Then sa pipeline ng tuloy-tuloy na integrasyon ay ginagawang proteksyon laban sa regression mula sa dokumentasyon. Ang bawat merge request sa isang mobile project ay awtomatikong nagpapatakbo ng mga BDD scenario at hinaharangan ang pagsasama kung hindi bababa sa isang senaryo ang nabigo.
Ang mga BDD scenario sa Cucumber para sa Android ay pinapatakbo sa pamamagitan ng Gradle task ./gradlew cucumber. Para sa iOS (Quick/Nimble) — sa pamamagitan ng xcodebuild test. Sa mga CI system (GitHub Actions, GitLab CI, Bitrise) ang mga BDD test ay isinasagawa sa mga emulator o totoong device. Ang ulat ay nabubuo sa format na HTML na naiintindihan ng mga manager: berdeng senaryo — pumasa, pula — nabigo na may indikasyon ng hakbang.
Ang mga .feature file ay naka-imbak sa repositoryo sa tabi ng code at dumaraan sa code review. Ang analista ay lumilikha ng merge request na may mga bagong senaryo bago magsimula ang pag-develop (BDD-first). Ang developer ay sumusulat ng mga kahulugan ng hakbang at implementasyon upang maging berde ang mga senaryong ito. Kapag pumasa ang lahat ng senaryo — handa na ang functionality. Ang pamamaraang ito, na inilarawan sa aklat ni Gojko Adzic na “Specification by Example” (2011), ay ginagawang isang executable artifact ang mga kinakailangan.
Mga Madalas Itanong
Sa istruktura — oo, ito ay parehong tatlong-bahaging pattern. Ang pagkakaiba ay nasa madla: Given-When-Then ay nakatuon sa wika ng negosyo at ginagamit sa BDD kasama ang Gherkin, habang ang Arrange-Act-Assert ay isang teknikal na format para sa mga unit test. Ang pagpili ay depende sa konteksto at koponan.
Walang limitasyon, ngunit inirerekomenda ang hindi hihigit sa 3–5 pagsusuri bawat Then. Kung mas marami ang pagsusuri — malamang na sinusuri ng senaryo ang labis sa isang aksyon. Hatiin ito sa maraming senaryo na may iba't ibang Then.
Hindi. Ang pattern ay maaaring gamitin sa anumang testing framework, sa pamamagitan lamang ng paghahati ng pagsubok sa tatlong bloke gamit ang mga komento o mga blangkong linya. Ang Gherkin ay kailangan lamang kapag ang mga senaryo ay isinusulat sa format na .feature file para sa Cucumber o SpecFlow.
Inirerekomenda na ilipat ang mga paulit-ulit na precondition sa Background (Gherkin) o @Before methods (JUnit). Kung kumplikado ang mga precondition, gamitin ang Builder pattern para sa paglikha ng data ng pagsubok. Ito ay nagpapanatili sa Given na maikli at nababasa.
Hindi. Ang When — ay isang mandatoryong bloke na naglalarawan ng aksyon. Kung susuriin lamang ng senaryo ang estado nang walang aksyon (halimbawa, “kapag nag-load ang application, dapat i-cache ang data”), inilalarawan ng When ang trigger: “kapag inilunsad ang application”.
Buod
Gagawa kami ng mobile application na turnkey
Gumagawa ang IT Sectr ng mga iOS at Android application para sa mga startup at negosyo mula noong 2017. Magpapayo kami sa iyo at magmumungkahi ng pinakamahusay na solusyon.
Basahin din