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 در سال ۲۰۰۶ به عنوان بخشی از روش‌شناسی Behavior-Driven Development تدوین شد. این الگو مشکل توصیف‌های بدون ساختار سناریوهای تست را حل می‌کند که اغلب شامل ترکیبی از پیش‌شرط‌ها، اقدامات و بررسی‌ها به ترتیب دلخواه هستند.

ایده اصلی الگو تفکیک مسئولیت‌ها بین سه بلوک است. هر بلوک دقیقاً مسئول یک جنبه از سناریو است: وضعیت قبل، رویداد در حین و بررسی بعد از آن. این کار سناریو را خوانا، قابل بررسی و قابل خودکارسازی می‌کند. بر اساس تحقیق توسعه‌دهندگان فریم‌ورک Cucumber (۲۰۲۴)، سناریوهایی که به طور دقیق از الگوی Given-When-Then پیروی می‌کنند، ۴۲٪ زمان کمتری برای درک توسط یک عضو جدید تیم نیاز دارند.

ریشه الگو

Dan North ایده ساختار سه‌بخشی را از formulation of tests در TDD و روش‌شناسی Test-by-Example (ایجاد شده توسط Brian Marick) اقتباس کرد. ماریک پیشنهاد کرد که نیازمندی‌ها از طریق مثال‌هایی (examples) توصیف شوند که همزمان به عنوان تست نیز عمل می‌کنند. Given-When-Then این ایده را رسمی کرد و مثال‌های بدون ساختار را به یک الگوی قابل تکرار تبدیل نمود.

حوزه کاربرد

الگوی Given-When-Then نه تنها در سناریوهای BDD در Gherkin، بلکه در تست‌های واحد معمولی در JUnit، XCTest و سایر فریم‌ورک‌ها نیز کاربرد دارد. کامنت‌هایی در کد که تست را به سه بلوک تقسیم می‌کنند، یک روش رایج برای بهبود خوانایی پایگاه تست است. Google این رویکرد را در کتاب خود “Software Engineering at Google” (۲۰۲۰) توصیه می‌کند.

ساختار سه بلوک

هر بلوک 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 برای سناریوهایی که با مشتری یا تحلیلگر بحث می‌شوند بهینه است: معیارهای پذیرش ویژگی‌ها، سناریوهای استفاده، بررسی‌های رگرسیون. نحو Gherkin امکان نوشتن چنین سناریوهایی را بدون دانش برنامه‌نویسی فراهم می‌کند.

چه زمانی از Arrange-Act-Assert استفاده کنیم

Arrange-Act-Assert — انتخاب طبیعی برای تست‌های واحد است که یک متد یا کلاس خاص را بررسی می‌کنند. قالب AAA به فریم‌ورک‌های اضافی نیاز ندارد و در هر زبان برنامه‌نویسی کار می‌کند. برای توسعه iOS، Apple AAA را در مستندات XCTest (۲۰۲۴) توصیه می‌کند.

مثال‌هایی از سناریوها در Kotlin

بیایید به مثال‌های عملی Given-When-Then در Kotlin برای یک برنامه Android نگاه کنیم. مثال اول — تست سبد خرید با استفاده از MockK. مثال دوم — تست منطق اعلان‌های push.

مثال ۱: سبد خرید

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

مثال ۲: اعلان‌های 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)
    }
}

مثال ۳: سناریوی 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 کاربر ایوانف با موجودی ۵۰۰ روبل” — “Given کاربر با موجودی کافی”. داده‌های خاص به Scenario Outline با جدول Examples منتقل می‌شوند. این کار سناریو را جهانی و قابل استفاده مجدد می‌کند.

  • Then را به عنوان عبارات قابل اندازه‌گیری بنویسید — “کاربر باید صفحه ورود را ببیند”، نه “کاربر باید هدایت شود”
  • برای مراحل هم‌نوع از And استفاده کنید — اگر چند Given نیاز است، آنها را از طریق And ترکیب کنید، Given دوم ایجاد نکنید
  • سطوح انتزاع را مخلوط نکنید — Given-When-Then باید در یک سطح باشد: یا تجاری یا فنی، نه درهم
  • دلیل سناریو را مستند کنید — یک کامنت در ابتدای فایل .feature با توضیح قانون کسب‌وکار به زمینه کمک می‌کند

Given-When-Then در خط لوله CI/CD

ادغام سناریوهای Given-When-Then در خط لوله یکپارچه‌سازی مداوم آنها را از مستندات به محافظی در برابر رگرسیون‌ها تبدیل می‌کند. هر درخواست merge در یک پروژه موبایل به طور خودکار سناریوهای BDD را اجرا می‌کند و در صورت شکست حداقل یک سناریو، ادغام را مسدود می‌کند.

اجرای خودکار سناریوها

سناریوهای BDD در Cucumber برای Android از طریق وظیفه Gradle ./gradlew cucumber اجرا می‌شوند. برای iOS (Quick/Nimble) — از طریق xcodebuild test. در سیستم‌های CI (GitHub Actions, GitLab CI, Bitrise) تست‌های BDD روی شبیه‌سازها یا دستگاه‌های واقعی اجرا می‌شوند. گزارش در قالب HTML تولید می‌شود که برای مدیران قابل فهم است: سناریوهای سبز — قبول، قرمز — شکست با ذکر مرحله.

مستندات زنده در مخزن

فایل‌های .feature در مخزن در کنار کد ذخیره می‌شوند و code review می‌شوند. تحلیلگر قبل از شروع توسعه یک درخواست merge با سناریوهای جدید ایجاد می‌کند (BDD-first). توسعه‌دهنده step definitions و پیاده‌سازی را می‌نویسد تا این سناریوها سبز شوند. وقتی همه سناریوها عبور می‌کنند — قابلیت آماده است. این رویکرد، که در کتاب Gojko Adzic “Specification by Example” (۲۰۱۱) توصیف شده است، نیازمندی‌ها را به یک مصنوع قابل اجرا تبدیل می‌کند.

سوالات متداول

Given-When-Then همان Arrange-Act-Assert است؟

از نظر ساختار — بله، این همان الگوی سه‌بخشی است. تفاوت در مخاطب است: Given-When-Then به زبان کسب‌وکار گرایش دارد و در BDD با Gherkin استفاده می‌شود، در حالی که Arrange-Act-Assert یک قالب فنی برای تست‌های واحد است. انتخاب به زمینه و تیم بستگی دارد.

چند بررسی می‌تواند در بلوک Then باشد؟

محدودیتی وجود ندارد، اما توصیه می‌شود حداکثر ۳–۵ بررسی برای هر 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 از سال 2017 برنامه‌های iOS و Android را برای استارتاپ‌ها و کسب‌وکارها ایجاد می‌کند. ما به شما مشاوره می‌دهیم و بهترین راه‌حل را پیشنهاد خواهیم کرد.

بحث درباره پروژه

همچنین بخوانید