Given-When-Then, test senaryolarını tanımlamak için yapısal bir kalıptır ve BDD tarafından domain-driven design'dan alınarak Behaviour-Driven Development için uyarlanmıştır. Biçim, senaryoyu üç mantıksal bölüme ayırır: ön koşullar (Given), eylem (When) ve beklenen sonuç (Then). Martin Fowler'a (2023) göre, Given-When-Then yalnızca bir test biçimi değil, uygulama başlamadan önce gereksinim analizini ve senaryo tasarımını disipline eden bir düşünme aracıdır.
Önemli Noktalar
Given-When-Then, ilk olarak Dan North tarafından 2006 yılında Behavior-Driven Development metodolojisinin bir parçası olarak formüle edilen bir davranış tanımlama kalıbıdır. Kalıp, genellikle rastgele sırada ön koşullar, eylemler ve doğrulamaların bir karışımını içeren yapılandırılmamış test senaryosu tanımları sorununu çözer.
Kalıbın ana fikri, üç blok arasında sorumlulukların ayrılmasıdır. Her blok, senaryonun tam olarak bir yönünden sorumludur: önceki durum, sırasındaki olay ve sonraki doğrulama. Bu, senaryoyu okunabilir, doğrulanabilir ve otomatikleştirilebilir hale getirir. Cucumber çerçevesi geliştiricilerinin bir araştırmasına (2024) göre, Given-When-Then kalıbını sıkı bir şekilde takip eden senaryolar, yeni bir ekip üyesi tarafından anlaşılması için %42 daha az zaman gerektirir.
Dan North, üç parçalı yapı fikrini TDD'deki test formülasyonundan ve Test-by-Example metodolojisinden (Brian Marick tarafından oluşturulmuştur) ödünç almıştır. Marick, aynı anda test görevi gören örnekler (examples) aracılığıyla gereksinimlerin tanımlanmasını önermiştir. Given-When-Then bu fikri resmileştirerek yapılandırılmamış örnekleri tekrarlanabilir bir kalıba dönüştürmüştür.
Given-When-Then kalıbı yalnızca Gherkin'deki BDD senaryolarında değil, aynı zamanda JUnit, XCTest ve diğer çerçevelerle yapılan sıradan birim testlerinde de uygulanır. Testi üç bloğa bölen koddaki yorumlar, test tabanının okunabilirliğini artırmak için yaygın bir uygulamadır. Google, «Software Engineering at Google» (2020) kitabında bu yaklaşımı önermektedir.
Given-When-Then'in her bloğunun kesin olarak tanımlanmış bir anlamı ve doldurma kuralları vardır. Bu kuralların ihlali, otomatikleştirilmesi veya anlaşılması zor senaryolara yol açar.
Given bloğu, test edilen eylemi gerçekleştirmeden önce sistemin durumunu tanımlar. Şunları içerir: mevcut nesneler (kullanıcı, sipariş, ayarlar), aktif durumlar (kimliği doğrulanmış, ağa bağlı) ve verilerin başlangıç değerleri. Her Given doğrulanabilir olmalıdır — sistem durumu Given ile eşleşmiyorsa, senaryo atlanmalı veya test ortamı önceden hazırlanmalıdır.
When bloğu, test edilen davranışı başlatan tek olayı tanımlar. Bu bir metot çağrısı, düğmeye tıklama, bildirim veya sunucudan yanıt alma olabilir. Temel kural senaryo başına bir When'dir. Bir eylem dizisini doğrulamak gerekiyorsa, bir When zinciri değil, ayrı senaryolar oluşturun.
// Given: test verilerini oluşturuyoruz
val user = User(email = "test@example.com", balance = 500.0)
val product = Product(price = 150.0)
// When: eylemi gerçekleştiriyoruz
val result = PurchaseUseCase().buy(user, product)
// Then: sonucu doğruluyoruz
assertEquals(PurchaseResult.Success, result)
assertEquals(350.0, user.balance)
Then bloğu, sistemin beklenen duruma geçtiğini doğrular. Bu şunları içerir: dönen değerler, nesnelerin durum değişiklikleri, harici hizmet çağrıları (mock doğrulaması yoluyla) ve kullanıcı arayüzü değişiklikleri. Her Then bloğu birden çok doğrulama içerebilir, ancak tümü tek bir eylemle ilgilidir.
Given-When-Then ve Arrange-Act-Assert (AAA), aynı üç parçalı kalıbın iki varyasyonudur, ancak farklı hedef kitleleri vardır. Farklılıklarını anlamak, belirli bir görev için doğru biçimi seçmeye yardımcı olur.
| Yön | Given-When-Then | Arrange-Act-Assert |
|---|---|---|
| Köken | BDD, iş analizi | Birim testi |
| Dil | Doğal (Gherkin) | Kod (Kotlin, Swift, Java) |
| Kitle | Tüm ekip + müşteri | Geliştiriciler |
| Ayrıntı düzeyi | Üst düzey | Ayrıntılı |
| Otomasyon | Cucumber, SpecFlow | JUnit, XCTest, Mockito |
Given-When-Then kalıbı, müşteri veya analist ile tartışılan senaryolar için idealdir: özellik kabul kriterleri, kullanım durumları, regresyon kontrolleri. Gherkin sözdizimi, programlama bilgisi olmadan bu senaryoların yazılmasına olanak tanır.
Arrange-Act-Assert, belirli bir metodu veya sınıfı doğrulayan birim testleri için doğal seçimdir. AAA biçimi ek çerçeveler gerektirmez ve herhangi bir programlama dilinde çalışır. iOS geliştirme için Apple, XCTest belgelerinde (2024) AAA'yı önermektedir.
Bir Android uygulaması için Kotlin'de Given-When-Then'in pratik örneklerine bakalım. İlk örnek, MockK kullanarak alışveriş sepeti testidir. İkincisi, push bildirimi mantığı testidir.
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)
}
}
İkinci örnek, eşzamansız kod ile Given-When-Then'i gösterir. Burada Given, Firebase Cloud Messaging durumunu belirler, When — push bildirimi alma, Then — işlemin doğrulanması.
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)
}
}
Üçüncü örnek, kabul testleri bağlamında Given-When-Then'i gösteren Gherkin'de bir BDD senaryosudur:
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'in etkili bir şekilde uygulanması, birkaç kanıtlanmış uygulamaya uyulmasını gerektirir. Bunlar, senaryoların okunabilirliğini, bakımını ve otomasyonunu sağlar.
Katı kural: bir senaryo — bir eylem. Birden çok When dizisini doğrulamak gerekiyorsa, öncekinin sonucunun bir sonrakinin ön koşulu haline geldiği birden çok senaryo oluşturun. Bu, senaryoyu atomik ve anlaşılır kılar.
Given özü tanımlamalıdır, somut sayıları değil. «Given kullanıcı Ivanov, bakiyesi 500 ruble» yerine — «Given yeterli bakiyesi olan kullanıcı». Somut veriler, Examples tablosu içeren Scenario Outline'a taşınır. Bu, senaryoyu evrensel ve yeniden kullanılabilir kılar.
Given-When-Then senaryolarının sürekli entegrasyon boru hattına entegrasyonu, onları belgelerden regresyonlara karşı korumaya dönüştürür. Bir mobil projedeki her birleştirme isteği otomatik olarak BDD senaryolarını çalıştırır ve en az bir senaryo başarısız olursa birleştirmeyi engeller.
Android için Cucumber ile BDD senaryoları, Gradle görevi ./gradlew cucumber aracılığıyla çalıştırılır. iOS (Quick/Nimble) için — xcodebuild test aracılığıyla. CI sistemlerinde (GitHub Actions, GitLab CI, Bitrise), BDD testleri öykünücülerde veya gerçek cihazlarda yürütülür. Rapor, yöneticiler için anlaşılabilir HTML biçiminde oluşturulur: yeşil senaryolar — geçti, kırmızı — adımı belirten başarısızlık.
.feature dosyaları, kodun yanında depoda saklanır ve kod incelemesinden geçer. Analist, geliştirme başlamadan önce (BDD-first) yeni senaryolarla bir birleştirme isteği oluşturur. Geliştirici, bu senaryoları yeşil yapmak için adım tanımları ve uygulama yazar. Tüm senaryolar geçtiğinde — işlevsellik hazırdır. Gojko Adzic'in «Specification by Example» (2011) kitabında açıklanan bu yaklaşım, gereksinimleri yürütülebilir bir yapıta dönüştürür.
Sıkça sorulan sorular
Yapısal olarak evet, aynı üç parçalı kalıptır. Fark kitleyledir: Given-When-Then iş diline yöneliktir ve BDD'de Gherkin ile kullanılırken, Arrange-Act-Assert birim testleri için teknik bir biçimdir. Seçim, bağlama ve ekibe bağlıdır.
Sınır yoktur, ancak her Then için 3–5'ten fazla doğrulama olmaması önerilir. Daha fazla doğrulama varsa, senaryo muhtemelen tek bir eylemde çok fazla şeyi kontrol ediyordur. Bunu farklı Then'lere sahip birden çok senaryoya bölün.
Hayır. Kalıp, herhangi bir test çerçevesinde kullanılabilir, sadece testi yorumlarla veya boş satırlarla üç bloğa bölerek. Gherkin yalnızca senaryolar Cucumber veya SpecFlow için .feature dosya biçiminde yazılıyorsa gereklidir.
Tekrarlayan ön koşulların Background'a (Gherkin) veya @Before metotlarına (JUnit) çıkarılması önerilir. Ön koşullar karmaşıksa, test verileri oluşturmak için Builder kalıbını kullanın. Bu, Given'i kısa ve okunabilir tutar.
Hayır. When, eylemi tanımlayan zorunlu bir bloktur. Senaryo yalnızca eylem olmadan durumu doğruluyorsa (örneğin, «uygulama yüklenirken veriler önbelleğe alınmalıdır»), When tetikleyiciyi tanımlar: «uygulama başlatıldığında».
Özet
Anahtar teslim bir mobil uygulama geliştireceğiz
IT Sectr, 2017'den beri girişimler ve işletmeler için iOS ve Android uygulamaları oluşturmaktadır. Size danışmanlık yapacak ve en iyi çözümü önereceğiz.
Ayrıca okuyun