BDD از فایل .feature شروع نمی‌شود؛ از یک سؤال حل‌نشده شروع می‌شود. اگر Product، Developer و Tester دربارهٔ «بازپرداخت تکراری» برداشت‌های متفاوتی دارند، نوشتن ده Scenario با Cucumber این اختلاف را پنهان می‌کند، نه حل. ابتدا Rule و Example را کشف کنید؛ بعد آن‌ها را خوانا Formulate کنید؛ فقط مثال‌های ارزشمند و پایدار را Automate کنید.

این راهنما BDD با Cucumber را از گفت‌وگوی کسب‌وکار تا Gherkin و Step Definition آموزش می‌دهد. مثال اصلی یک بازپرداخت فروشگاه ایرانی است و نشان می‌دهد چگونه سناریوی رفتارمحور بنویسیم، Cucumber.js را اجرا کنیم، State هر Scenario را ایزوله نگه داریم و از ضدالگوهای UI script، Stepهای تکراری و «مستندات زندهٔ مرده» دور بمانیم.

BDD چیست و چه ربطی به Cucumber دارد؟

Behavior-Driven Development شیوه‌ای برای ساخت درک مشترک دربارهٔ رفتار مطلوب سیستم با مثال‌های واقعی است. مستندات رسمی BDD در Cucumber سه Practice را به‌ترتیب معرفی می‌کند:

  1. Discovery: Ruleها، مثال‌ها و سؤال‌های ناشناخته را در گفت‌وگو کشف کنید.
  2. Formulation: مثال‌های توافق‌شده را دقیق، خوانا و قابل‌آزمون بیان کنید.
  3. Automation: Specification ارزشمند را به سیستم وصل و رفتار واقعی را بررسی کنید.

Cucumber ابزار مرحلهٔ Automation است، نه خود BDD. می‌توان BDD بدون Cucumber داشت و می‌توان Cucumber داشت اما هیچ Discovery و فهم مشترکی نداشت. اگر تیم فقط Testهای قدیمی را به Given/When/Then ترجمه کند، Syntax عوض شده ولی رفتارمحوری ایجاد نشده است.

هدف BDD چیست؟

  • ابهام را پیش از پیاده‌سازی با مثال آشکار کند؛
  • زبان دامنه را میان Product، Business، Development و Test همگرا کند؛
  • Ruleهای کسب‌وکار را از جزئیات UI/کد جدا کند؛
  • Scope یک Change را با مثال‌های ضروری کوچک کند؛
  • سؤال‌های بی‌پاسخ و تصمیم‌گیرندهٔ آن‌ها را مرئی کند؛
  • برای رفتارهای مهم، Regression قابل‌فهم بسازد؛
  • Specification و کد را با Review و Automation نزدیک نگه دارد.

BDD کیفیت، هزینه یا رضایت را تضمین نمی‌کند. ارزش آن به کیفیت Discovery، پایداری Rule، طراحی Automation و مشارکت واقعی خوانندگان بستگی دارد.

چرخه Discovery → Formulation → Automation

چرخه BDD شامل Discovery، Formulation و Automation با Cucumber

Discovery؛ چه رفتاری و چرا؟

یک Change کوچک و نزدیک را بردارید. افراد دارای سه Perspective لازم‌اند: Business/Product، Development و Test. نام «Three Amigos» به معنای دقیقاً سه نفر یا جلسهٔ اجباری نیست؛ هدف حضور Perspectiveها و تصمیم‌گیرندهٔ مناسب است.

پرسش شروع:

کاربر می‌خواهد بخشی از مبلغ سفارش پرداخت‌شده را پس بگیرد؛ سیستم در Retry، مبلغ مرزی و Callback دیرهنگام چگونه رفتار می‌کند؟

راهنمای تحلیل نیازمندی‌ها برای شناخت Stakeholder، Oracle، داده و محدودیت‌ها مکمل Discovery است.

Formulation؛ چه باید بکند؟

مثال‌هایی را که تیم پذیرفته است با زبان دامنه و Outcome مشاهده‌پذیر بنویسید. Formulation جلسهٔ ترجمهٔ Test case به Gherkin نیست؛ Editing مشترک برای حذف ابهام و جزئیات تصادفی است.

Automation؛ واقعاً چه می‌کند؟

Cucumber متن Step را به Step Definition متصل می‌کند. Definition از Driver دامنه/API/UI استفاده و Assertion می‌کند. Automation باید روی کوچک‌ترین مرز قابل‌اعتماد اجرا شود؛ BDD الزام نمی‌کند همهٔ Scenarioها از Browser عبور کنند.

این ترتیب با Shift-left Testing هم‌راستاست: Example زودتر از کد Feedback می‌دهد، سپس Test خودکار Behavior را پس از هر Change بررسی می‌کند.

Example Mapping با Rule، Example و Question

نوع کارت بازپرداخت
Story/Outcome بازپرداخت امن و قابل‌پیگیری برای سفارش پرداخت‌شده
Rule مجموع بازپرداخت نباید از مبلغ پرداخت معتبر بیشتر شود
Example پرداخت ۱٬۰۰۰٬۰۰۰ IRR؛ Refund اول ۲۵۰٬۰۰۰؛ Refund دوم ۷۵۰٬۰۰۰ → هر دو پذیرفته
Example مرزی پس از آن Refund یک IRR → رد
Question کارمزد یا تغییر نرخ ارز در سقف وارد می‌شود؟
Out of scope بازپرداخت بین‌بانکی چندروزه در Story جدا

Rule را از Example استخراج کنید؛ سپس Example مخالف و مرزی پیدا کنید. سؤال بی‌پاسخ را Scenario ساختگی نکنید. Owner و موعد تصمیم را ثبت کنید. Discovery خوب گاهی باعث می‌شود Story کوچک یا متوقف شود؛ این شکست نیست، Feedback زودهنگام است.

Gherkin چیست؟

Gherkin زبان ساخت‌یافتهٔ Feature file است. مرجع رسمی Gherkin Keywordهای اصلی را تعریف می‌کند:

Keyword نقش
Feature Capability/دامنهٔ کلی؛ هر فایل یک Feature
Rule یک Rule کسب‌وکار و مثال‌های مرتبط
Scenario / Example یک مثال مشخص از رفتار
Given Context/State مرتبط
When Event یا Action اصلی
Then Outcome مشاهده‌پذیر
Background Context کوتاه و مشترک پیش از هر Scenario
Scenario Outline + Examples یک Rule با چند مجموعه دادهٔ معنادار
Data Table / Doc String دادهٔ ساختاریافته یا متن چندخطی
Tags Metadata و انتخاب Scope اجرا

And و But برای خوانایی‌اند؛ Cucumber هنگام Match کردن Step Definition معنای فنی متفاوتی برای Given/When/Then/And/But قائل نمی‌شود. معنا را جمله و جایگاه آن می‌سازد.

یک Feature خوب برای بازپرداخت

Feature: بازپرداخت سفارش پرداخت‌شده
  برای جلوگیری از اثر مالی تکراری
  درخواست بازپرداخت باید با Ruleهای مبلغ و Idempotency پردازش شود

  Rule: مجموع بازپرداخت از مبلغ پرداخت معتبر بیشتر نمی‌شود

    Scenario: بازپرداخت بخشی از مبلغ پرداخت
      Given سفارش "O-1405-101" به مبلغ 1000000 IRR پرداخت شده است
      When بازپرداخت 250000 IRR با کلید "R-101" درخواست می‌شود
      Then بازپرداخت به مبلغ 250000 IRR پذیرفته می‌شود
      And مانده قابل بازپرداخت سفارش 750000 IRR است

    Scenario: تکرار همان درخواست اثر مالی دوباره نمی‌سازد
      Given درخواست بازپرداخت "R-101" قبلاً پذیرفته شده است
      When همان درخواست بازپرداخت دوباره ارسال می‌شود
      Then همان نتیجه قبلی برگردانده می‌شود
      And برای "R-101" فقط یک اثر مالی وجود دارد

    Scenario: مبلغ بیش از مانده رد می‌شود
      Given مانده قابل بازپرداخت سفارش 750000 IRR است
      When بازپرداخت 750001 IRR درخواست می‌شود
      Then درخواست با دلیل "exceeds_refundable_amount" رد می‌شود

چرا این Scenarioها رفتارمحورند؟

  • از «روی دکمه کلیک کن» یا CSS selector خبری نیست.
  • Rule و Outcome کسب‌وکار روشن‌اند.
  • عددها Example واقعی و مرزی می‌سازند.
  • IRR صریح است و با تومان اشتباه نمی‌شود.
  • Idempotency با اثر مالی سنجیده می‌شود، نه فقط HTTP ۲۰۰.
  • پیام فنی/دامنهٔ قابل‌پایدارشدن در Oracle آمده است.

اگر Refund Stateهای متعدد دارد، مدل آن را پیش از سناریو با تست انتقال حالت روشن کنید.

Scenario ضعیف و نسخه بهتر

ضدالگوی UI script

Scenario: Refund
  Given I open the orders page
  And I click the first row
  And I click the blue refund button
  And I type "250000" in the amount input
  When I click submit
  Then I see a green toast

این متن Layout و Widget را مستند می‌کند، اما Rule و Outcome مالی را نمی‌گوید. با تغییر رنگ دکمه Specification می‌شکند و ممکن است Toast سبز باشد ولی Ledger دوبار نوشته شود.

نسخهٔ رفتارمحور

Scenario: بازپرداخت جزئی سفارش پرداخت‌شده
  Given یک سفارش پرداخت‌شده با مانده قابل بازپرداخت 1000000 IRR
  When کارشناس مجاز بازپرداخت 250000 IRR را ثبت می‌کند
  Then مانده قابل بازپرداخت 750000 IRR می‌شود
  And یک رکورد بازپرداخت قابل‌پیگیری ایجاد می‌شود

Automation می‌تواند این Scenario را در API/Component layer اجرا کند و یک یا دو E2E جدا مسیر UI حیاتی را بسنجد.

قواعد نوشتن Given، When و Then

Given؛ Context کافی، نه Setup فنی

Given باید State مرتبط را بگوید: «سفارش پرداخت شده است». جزئیات ساخت جدول، Login token، Endpoint و Cleanup در Glue/Driver می‌ماند. Given طولانی نشانهٔ Scope بزرگ یا زبان دامنهٔ ضعیف است.

When؛ Event اصلی

ترجیحاً یک When اصلی داشته باشید. چند When پشت سر هم غالباً چند رفتار را در یک Scenario مخلوط می‌کند. اگر Journey واقعاً چند Event دارد، Outcomeهای میانی و دلیل Business را روشن کنید.

Then؛ Outcome مشاهده‌پذیر

Then نباید Implementation را Assert کند: «متد X فراخوانی شد» Specification کسب‌وکار نیست. نتیجه می‌تواند State، Event، Response، Ledger یا پیام کاربر باشد. یک Oracle لایهٔ مناسب انتخاب کنید.

Rule، Background و Scenario Outline را درست استفاده کنید

Rule برای سازمان‌دهی Business rule

یک Feature بزرگ را با Ruleهای مشخص تقسیم کنید: «سقف مبلغ»، «اختیار نقش»، «Idempotency». Scenarioها زیر Rule باید آن را مثال بزنند، نه Featureهای پراکنده را.

Background کوتاه و قابل‌حفظ

Background قبل از هر Scenario اجرا می‌شود. مستندات رسمی توصیه می‌کند Context پیچیده و نامرتبط را آنجا پنهان نکنید و آن را کوتاه نگه دارید. Database cleanup، Browser launch و WireMock lifecycle معمولاً Hook/Support فنی‌اند؛ «کاربر فروشندهٔ مجاز است» ممکن است Background خوانا باشد.

Scenario Outline فقط برای Variation معنادار

Scenario Outline: مبلغ نامعتبر بازپرداخت رد می‌شود
  Given مانده قابل بازپرداخت 750000 IRR است
  When بازپرداخت <amount> IRR درخواست می‌شود
  Then درخواست با دلیل "<reason>" رد می‌شود

  Examples:
    | amount | reason                    |
    |      0 | amount_must_be_positive   |
    |     -1 | amount_must_be_positive   |
    | 750001 | exceeds_refundable_amount |

Examples table را به Cartesian product صدها Row تبدیل نکنید. Equivalence partition و Boundaryهای توضیح‌دهنده را نگه دارید؛ دادهٔ حجیم بهتر است در تست پایین‌تر Data-driven باشد.

Data Table و Doc String

Data Table وقتی خوب است که Business واقعاً یک مجموعهٔ ساختاریافته را می‌خواند:

Given سفارش شامل اقلام زیر است
  | sku   | quantity | unit_price_irr |
  | A-101 | 2        | 150000         |
  | B-220 | 1        | 400000         |

Dump دیتابیس، JSON عظیم یا Payload فنی را داخل Feature نریزید. Doc String برای متن معنادار دامنه مانند Template پیام مناسب است؛ Fixture حجیم را Versioned و ارجاع‌پذیر نگه دارید.

Gherkin فارسی و RTL

Cucumber Localization فارسی را پشتیبانی می‌کند. در فهرست رسمی زبان‌ها، با Header زیر می‌توان Keywordهای فارسی را فعال کرد:

# language: fa
وِیژگی: بازپرداخت سفارش
  Rule: سقف بازپرداخت
    مثال: مبلغ بیشتر از مانده
      با فرض مانده قابل بازپرداخت 750000 IRR است
      هنگامی بازپرداخت 750001 IRR درخواست می‌شود
      آنگاه درخواست رد می‌شود

در Localization فعلی، Rule برای فارسی همچنان همان Keyword انگلیسی است. تیم می‌تواند Keywordهای انگلیسی و جمله‌های فارسی را برای سازگاری بهتر Editor انتخاب کند؛ مهم ثبات Repository است.

نکات فارسی

  • Encoding را UTF-۸ و Direction نمایش Editor را آزمایش کنید.
  • اعداد Example را ترجیحاً ASCII نگه دارید یا ParameterType برای ۱۲۳/۱۲۳ ثبت کنید؛ فرض نکنید {int} همه شکل‌های رقم را می‌پذیرد.
  • Normalization «ی/ی»، «ک/ک» و نیم‌فاصله را در Domain driver روشن کنید.
  • IRR/IRT را جدا بنویسید و تبدیل را Step پنهان نکنید.
  • کلید Idempotency، Token، شماره واقعی و دادهٔ شخصی را در Feature commit نکنید.
  • اگر Translation اصطلاح دامنه را مبهم می‌کند، اصطلاح پایدار انگلیسی را در Glossary نگه دارید.

نصب Cucumber.js

برای پروژهٔ Node.js از نسخهٔ نگهداری‌شدهٔ Node و نسخهٔ سازگار Cucumber استفاده کنید. README رسمی Cucumber.js Package و Command پایه را نشان می‌دهد:

npm install --save-dev @cucumber/cucumber
npx cucumber-js

نسخهٔ Package و Node را در Lockfile/CI Pin کنید. Command، Module system و TypeScript loader ممکن است میان نسخه‌ها تغییر کند؛ مستندات همان Version را بررسی کنید.

ساختار پیشنهادی

features/
  refund.feature
  step_definitions/
    refund.steps.js
  support/
    hooks.js
    world.js
test-support/
  drivers/
    refund-driver.js

Feature زبان کسب‌وکار است؛ Step Definition Glue نازک؛ Driver تعامل فنی با API/Component/DB stub را کپسوله می‌کند.

Step Definition چیست؟

مستندات Step Definition آن را Method/Function دارای Expression می‌داند که به Stepهای Gherkin متصل می‌شود. Cucumber Expressions خواناتر از Regex پیچیده‌اند:

const assert = require('node:assert/strict')
const { Given, When, Then } = require('@cucumber/cucumber')

Given(
  'سفارش {string} به مبلغ {int} {word} پرداخت شده است',
  async function (orderId, amount, currency) {
    await this.refundDriver.createPaidOrder({ orderId, amount, currency })
    this.orderId = orderId
  }
)

When(
  'بازپرداخت {int} {word} با کلید {string} درخواست می‌شود',
  async function (amount, currency, idempotencyKey) {
    this.response = await this.refundDriver.requestRefund({
      orderId: this.orderId,
      amount,
      currency,
      idempotencyKey
    })
  }
)

Then(
  'مانده قابل بازپرداخت سفارش {int} {word} است',
  async function (expectedAmount, currency) {
    const order = await this.refundDriver.getOrder(this.orderId)
    assert.equal(order.refundableAmount, expectedAmount)
    assert.equal(order.currency, currency)
  }
)

در Cucumber.js اگر State از this/World استفاده می‌کنید، Arrow function ننویسید چون this را Lexical bind می‌کند. Step باید Assertion واقعی داشته باشد؛ مستندات رسمی می‌گوید صرف return false Step را Fail نمی‌کند، باید Error/Assertion رخ دهد.

معماری Step Definition قابل‌نگهداری

لایه مسئولیت نباید
Feature Rule و Example دامنه Selector، SQL، timeout فنی
Step definition Parameter → Driver call → Assertion Business logic یا workflow حجیم
Task/Domain driver عملیات معنادار مانند requestRefund به متن Gherkin وابسته شود
Adapter API/UI/DB stub/queue client Oracle کسب‌وکار را جعل کند
World State همان Scenario Global state مشترک بین Scenarioها

تست API در بسیاری از رفتارهای کسب‌وکار سریع‌تر و پایدارتر از UI است؛ راهنمای تست API Contract، authorization و Idempotency را پوشش می‌دهد.

Stepهای خوب و بد

بد بهتر دلیل
I click “#refund-blue” کارشناس مجاز بازپرداخت را ثبت می‌کند Intent، نه selector
the API returns 200 بازپرداخت پذیرفته و قابل‌پیگیری است Outcome دامنه
database row count is 1 درخواست تکراری یک اثر مالی دارد Invariant
I wait 5 seconds پردازش بازپرداخت تکمیل می‌شود Poll/event با timeout در Driver
user A exists فروشنده مجاز بازپرداخت دارد Role معنادار

Step را به‌خاطر «Reuse» بیش از حد عمومی نکنید. عبارت I perform action {string} on entity {string} زبان دامنه را از بین می‌برد. Reuse نتیجهٔ Vocabulary مشترک است، نه هدف مستقل.

Ambiguous و Duplicate Step Definition

اگر بیش از یک Expression یک Step را Match کند، Cucumber آن را Ambiguous گزارش می‌کند. راهکار:

  • Vocabulary دامنه را استاندارد کنید؛
  • Expressionهای بیش‌ازحد عمومی را محدود کنید؛
  • Step catalog را Search/Review کنید؛
  • ParameterType معنادار بسازید؛
  • Glue را بر اساس Domain سازمان دهید، نه Feature fileهای تصادفی؛
  • Duplicate را با Rename/Migration هماهنگ حذف کنید.

Regex هوشمند ولی ناخوانا هزینهٔ نگهداری می‌سازد. Cucumber Expressions Typeهای داخلی و Custom را برای Match خواناتر فراهم می‌کند.

State، World و استقلال Scenario

اصل رسمی Cucumber دربارهٔ State روشن است: بین Scenarioها State به اشتراک نگذارید. هر Scenario باید مستقل، قابل‌اجرای تنها و قابل‌موازی‌شدن باشد.

  • Global/static variable نداشته باشید؛
  • World فقط عمر همان Scenario را داشته باشد؛
  • Database را با Namespace/transaction/fixture ایزوله Seed کنید؛
  • Cookie/session هر Scenario جدا باشد؛
  • Scenarioها به ترتیب فایل وابسته نباشند؛
  • Cleanup فقط دادهٔ همان Test run را حذف کند؛
  • Retry Scenario اول را پنهان نکند.

راهنمای رسمی State نیز از اشتراک State میان Scenarioها منع می‌کند. طراحی دادهٔ Seed/Reset و دادهٔ مصنوعی در مدیریت داده تست آمده است.

Hooks؛ Setup فنی، نه رفتار پنهان

Before/After برای Browser، Driver، DB cleanup، Screenshot و Attachment فنی مناسب‌اند. اما Hook برای خوانندهٔ Feature نامرئی است. اگر Context برای فهم رفتار مهم است، آن را Given/Background بیان کنید.

Hookهای Tag-based می‌توانند Setup متفاوت بسازند، ولی زیادشدن آن‌ها ترتیب و State پنهان می‌سازد. Lifecycle، ترتیب، timeout و failure cleanup را Test کنید.

BDD در چه سطحی Automate شود؟

رفتار مرز پیشنهادی
محاسبه سقف Refund Unit/property tests؛ لازم نیست همه در Cucumber باشند
Idempotency و state/ledger Component/API + DB ایزوله
Contract درگاه Consumer/provider contract یا Stub رسمی
Journey کارشناس چند E2E حیاتی
ظاهر/focus/RTL UI/accessibility tests
Reconciliation زیر بار Integration/performance lane

BDD جای Test design، Exploration و لایه‌های دیگر را نمی‌گیرد. اتوماسیون تست باید براساس ارزش، پایداری و TCO انتخاب شود.

Tags و اجرای CI

@payment @refund @component
Feature: بازپرداخت سفارش پرداخت‌شده

  @smoke
  Scenario: بازپرداخت جزئی معتبر
    ...

  @wip
  Scenario: مغایرت مبلغ Callback
    ...

Tag را Metadata معنی‌دار نگه دارید: Domain، risk، execution layer یا temporary workflow. ضدالگوها:

  • Tag هر Sprint/Person؛
  • @smoke روی صدها Scenario؛
  • @wip بدون Owner/expiry؛
  • اجرای UI همهٔ Featureها روی هر Commit؛
  • استفاده از Tag برای پنهان‌کردن Testهای دائماً Fail.

Lane پیشنهادی:

رویداد Scope خروجی
PR Feature/Rule مرتبط + Component سریع Feedback تشخیصی
Merge Contract/Integration گسترده‌تر Artifact confidence
Nightly E2E و Matrix کند Triage با Owner
Release Journey حیاتی و policy Risk decision، نه تضمین

Living Documentation چه زمانی واقعاً زنده است؟

Feature file خودکار به مستند معتبر تبدیل نمی‌شود. Living documentation نیاز دارد:

  • Rule و Example با Business/Product Review شوند؛
  • Automation روی رفتار واقعی اجرا شود؛
  • Feature مرده/منسوخ حذف یا Archive شود؛
  • Report برای مخاطب قابل‌دسترسی و Searchable باشد؛
  • Version/Build و آخرین نتیجه مشخص باشد؛
  • Undefined/Pending/Ambiguous Scenario پذیرفتهٔ خاموش نباشد؛
  • Feature از UI detail و Fixture noise پاک بماند.

سبز بودن فقط یعنی Step Definitionها بدون Error اجرا شدند؛ Oracle ضعیف می‌تواند سند غلط را سبز نگه دارد.

BDD، TDD، ATDD و Specification by Example

رویکرد سؤال غالب خروجی
BDD رفتار ارزشمند و Rule مشترک چیست؟ Discovery + example + executable spec
TDD کوچک‌ترین رفتار کد و Design بعدی چیست؟ Red/Green/Refactor در سطح پیاده‌سازی
ATDD چه مثال پذیرشی Change را قابل‌قبول می‌کند؟ Acceptance examples پیش از Implementation
Specification by Example چگونه Rule را با مثال دقیق و زنده کنیم؟ مثال‌های مشترک و مستندشده
Cucumber چگونه Gherkin را به Automation وصل کنیم؟ Runner، glue، report

مرزها هم‌پوشانی دارند و تیم‌ها اصطلاح‌ها را متفاوت به‌کار می‌برند. BDD جای TDD نیست؛ Cucumber نیز الزاماً Acceptance level نیست. همان Rule می‌تواند Cucumber Component test و چند Unit test زیرین داشته باشد.

چه زمانی Cucumber انتخاب خوبی نیست؟

  • هیچ‌کس خارج از Automation code Featureها را نمی‌خواند یا Review نمی‌کند؛
  • Domain بسیار فنی و Unit/API test مستقیم خواناتر است؛
  • Rule هنوز ناپایدار و محصول در Spike/Discovery اولیه است؛
  • تیم فقط می‌خواهد UI scriptهای موجود را بازنویسی کند؛
  • دادهٔ ترکیبی بسیار حجیم در Testهای پایین‌تر بهتر پوشش می‌گیرد؛
  • هزینهٔ Glue/Runtime/Report از ارزش Communication بیشتر است.

در این حالت Discovery و Example mapping را نگه دارید، ولی Automation را با ابزار ساده‌تر انجام دهید. BDD به Cucumber وابسته نیست.

مثال کامل Workflow تیم

۱. پیش از Refinement

Product Story کوچک، Outcome و Known rules را آماده می‌کند؛ تصمیم‌های باز فهرست می‌شوند.

۲. Discovery سی‌دقیقه‌ای

Product، Developer و Tester Rule/Example/Question می‌سازند؛ Security/Operations در Risk لازم وارد می‌شوند. Story بزرگ شکسته می‌شود.

۳. Formulation مشترک

دو یا سه Example مهم به Gherkin رفتارمحور تبدیل و در Pull request جدا Review می‌شوند. Duplicate vocabulary بررسی می‌شود.

۴. Automation-first

Scenario اول Undefined/Fail می‌شود؛ Step Definition نازک و Driver دامنه ساخته می‌شود؛ Implementation تا Pass شدن Behavior توسعه می‌یابد. Testهای پایین‌تر برای Ruleهای ترکیبی اضافه می‌شوند.

۵. Exploration و NFR

Exampleهای کشف‌شده Seed تست اکتشافی، Accessibility، Security و Performance می‌شوند؛ همه به Cucumber تبدیل نمی‌شوند.

۶. CI و Documentation

Scenario مرتبط در PR، Suite بزرگ‌تر در Merge/Nightly و Report Versioned منتشر می‌شود. Failure Owner و Artifact دارد.

۷. Review و یادگیری

اگر Production Rule جدیدی آشکار کرد، اول Discovery/Example به‌روزرسانی می‌شود، سپس Regression مناسب ساخته می‌شود. این حلقه با تست چابک و Whole-team quality سازگار است.

متریک‌های مفید BDD/Cucumber

متریک پرسش دام
Question-to-decision time Discovery ابهام را واقعاً حل می‌کند؟ تعداد سؤال به‌عنوان KPI
Scenario review participation مخاطب Business/Product می‌خواند؟ حضور اجباری نمایشی
Undefined/Pending/Ambiguous aging Specification ناقص بی‌مالک مانده؟ حذف برای سبزکردن
Execution p95 و flaky rate Feedback قابل‌اعتماد و به‌موقع است؟ Retry پنهان
Duplicate/unused steps Vocabulary و Glue سالم‌اند؟ هدف صفر بدون Context
Living-doc freshness Feature منسوخ یا بی‌نتیجه داریم؟ Timestamp بدون Review
Recurring rule misunderstanding Exampleها Learning ساخته‌اند؟ سرزنش نقش‌ها

Scenario count، Step reuse percentage و «تعداد Featureهای خودکار» Outcome نیستند و قابل‌بازی‌اند. متریک‌های تست نرم‌افزار را به تصمیم و Guardrail وصل کنید.

اشتباه‌های رایج BDD با Cucumber

  • Automation قبل از Discovery: اختلاف فهم در کد Glue دفن می‌شود.
  • Gherkin = Test case prose: Given/When/Then رفتارمحوری ایجاد نمی‌کند.
  • UI script: Feature با Selector و Click شکننده می‌شود.
  • Then فنی: HTTP ۲۰۰ یا Row count جای Outcome دامنه می‌نشیند.
  • Background بلند: Context بیرون صفحه و نامرئی می‌شود.
  • Scenario Outline عظیم: جدول داده جای Rule/Example را می‌گیرد.
  • Step بسیار عمومی: Vocabulary از بین می‌رود و Ambiguity بالا می‌رود.
  • Business logic در Glue: Test و محصول دو پیاده‌سازی متفاوت می‌سازند.
  • State مشترک: ترتیب Scenario و اجرای موازی Test را Flaky می‌کند.
  • Hook پنهان: Context مهم برای خواننده نامرئی است.
  • همه‌چیز Cucumber: Unit/Property/Performance/Exploration نادیده می‌روند.
  • Living docs تضمینی: Feature منسوخ ولی سبز باقی می‌ماند.
  • Secret در Example: دادهٔ واقعی وارد Git و Report می‌شود.

چک‌لیست نهایی BDD و Cucumber

  • Discovery پیش از Formulation و Automation انجام شده است.
  • Rule، Example، Question و Out-of-scope جدا هستند.
  • مخاطب Business/Product متن Feature را Review می‌کند.
  • Scenarioها از زبان دامنه و Outcome قابل‌مشاهده استفاده می‌کنند.
  • جزئیات UI، SQL، Token و Setup فنی در Feature نیست.
  • Given Context، When Event و Then Outcome روشن دارند.
  • Background کوتاه و Scenarioها مستقل‌اند.
  • Outline فقط Variationهای معنادار را پوشش می‌دهد.
  • Step Definition نازک و Driver/Adapter جداست.
  • Assertion Error واقعی می‌سازد و Oracle مستقل است.
  • World/داده برای هر Scenario ایزوله و Cleanup محدود است.
  • Tag، Hook، Pending و Retry Owner/Policy دارند.
  • فارسی/RTL/رقم/واحد پول در Parser و Domain تست شده‌اند.
  • Report Version/Build و Freshness قابل‌مشاهده دارد.
  • Scenario فقط وقتی Automate می‌شود که ارزش Regression/Communication دارد.

سوالات متداول BDD با Cucumber

BDD به زبان ساده چیست؟

BDD شیوهٔ همکاری برای کشف و بیان رفتار مطلوب سیستم با مثال‌های واقعی است. چرخهٔ آن Discovery، Formulation و Automation است؛ هدف اصلی فهم مشترک و نرم‌افزار ارزشمند است، نه صرفاً تولید Test خودکار.

تفاوت BDD، Gherkin و Cucumber چیست؟

BDD فرایند/Practice همکاری و توسعه است؛ Gherkin زبان ساخت‌یافتهٔ Feature file؛ Cucumber ابزاری است که Stepهای Gherkin را به کد Automation وصل و اجرا می‌کند. استفاده از Cucumber به‌تنهایی به معنای اجرای BDD نیست.

آیا می‌توان Gherkin را فارسی نوشت؟

بله. Cucumber Localization فارسی و Header # language: fa را پشتیبانی می‌کند. Keywordهای فارسی رسمی را از نسخهٔ مستندات بررسی کنید؛ Encoding/RTL و اعداد فارسی را نیز در Editor و ParameterType آزمایش کنید.

آیا هر Scenario باید از UI اجرا شود؟

خیر. مرز Automation را از Risk انتخاب کنید. بسیاری از Ruleهای کسب‌وکار در Component/API سریع‌تر و پایدارترند؛ چند Journey حیاتی می‌تواند E2E باشد و Ruleهای محاسباتی Testهای Unit/Property جدا داشته باشند.

چرا Cucumber Scenario سبز است ولی محصول غلط کار می‌کند؟

سبزشدن فقط نشان می‌دهد Stepها بدون Error پایان یافته‌اند. Oracle ضعیف، Assertion ناقص، Fake غیرنماینده یا بررسی HTTP ۲۰۰ به‌جای Outcome می‌تواند False confidence بسازد. Then را به Invariant واقعی و Evidence مستقل وصل کنید.

منابع و یادداشت بازبینی

چرخهٔ BDD، Gherkin/Rule/Background/Outline، Localization فارسی، Cucumber Expressions، Step Definition، Assertion، Hook و Scenario state با مستندات رسمی Cucumber و Cucumber.js تطبیق داده شده‌اند. آخرین بازبینی محتوایی: ۱۵ مرداد ۱۴۰۵. API و Configuration ابزار ممکن است با نسخه تغییر کنند؛ Package/Node را Pin و مستندات همان Release را مرجع کنید.

جمع‌بندی: BDD زمانی ارزش دارد که مثال گفت‌وگو را بهتر کند، نه وقتی Gherkin لایه‌ای روی Automation قدیمی باشد. Rule و سؤال را در Discovery پیدا کنید، Example را بدون جزئیات تصادفی بنویسید، Glue را نازک و Scenario را مستقل نگه دارید و فقط Specificationهایی را Automate کنید که برای فهم یا Regression ارزش پایدار دارند.

دیدگاهتان را بنویسید