سه شرط ساده را تصور کنید: مشتری ویژه است یا نه، مبلغ سبد از حد مشخص بیشتر است یا نه و کد تخفیف معتبر است یا نه. همین سه شرط هشت ترکیب می‌سازند. اگر تست‌ها را فقط بر اساس حدس یا چند مسیر خوش‌بینانه بنویسیم، احتمالاً یکی از قوانین قیمت‌گذاری جا می‌افتد. تست جدول تصمیم این منطق چندشرطی را به مدلی شفاف و قابل پوشش تبدیل می‌کند.

در این راهنما، ساخت Decision Table را مرحله‌به‌مرحله یاد می‌گیرید، یک جدول کامل برای تخفیف و ارسال فروشگاه می‌سازید، آن را بدون از دست‌دادن منطق کوچک می‌کنید و از هر قانون Test Case استخراج می‌کنید. همچنین تفاوت علامت «مهم نیست» با ترکیب «ناممکن»، معیار پوشش و خطاهای رایج را بررسی می‌کنیم.

خلاصه سریع: در جدول تصمیم، هر ستون یک Rule است؛ یعنی یک ترکیب از Conditionها و Actionهای مورد انتظار. هدف پوشش، اجرای همه ستون‌های شدنی جدول است، نه صرفاً امتحان‌کردن هر شرط به‌تنهایی.

تست جدول تصمیم چیست؟

تست جدول تصمیم یا Decision Table Testing یک تکنیک تست مبتنی بر مشخصات است که نشان می‌دهد ترکیب‌های مختلف شرایط باید به چه خروجی‌ها یا اقدام‌هایی منجر شوند. این تکنیک برای قوانین «اگر/آنگاه»، سیاست‌های قیمت‌گذاری، اعتبارسنجی، مجوز دسترسی، محاسبه کارمزد، بیمه، مالیات و گردش‌های تأیید بسیار مناسب است.

Decision Table در گروه تکنیک‌های تست جعبه سیاه قرار می‌گیرد، زیرا تست‌کیس‌ها از رفتار مورد انتظار و قواعد کسب‌وکار استخراج می‌شوند، نه از ساختار داخلی کد. البته توسعه‌دهنده هم می‌تواند همین مدل را برای Unit Test به کار ببرد.

این تکنیک را با Decision/Branch Coverage اشتباه نکنید. «تست جدول تصمیم» ترکیب قوانین را از Specification مدل می‌کند؛ «پوشش Decision یا Branch» یک معیار ساختاری برای مسیرهای کنترل کد است که در تست جعبه سفید بررسی می‌شود.

چه زمانی از Decision Table استفاده کنیم؟

جدول تصمیم زمانی ارزش بالایی دارد که خروجی فقط به یک ورودی وابسته نیست، بلکه از تعامل چند شرط ساخته می‌شود. نشانه‌های مناسب عبارت‌اند از:

  • نیازمندی شامل چندین عبارت if، unless، only if، except یا «در صورتی که» است؛
  • قانون‌های قیمت، تخفیف، ارسال، کارمزد یا سطح دسترسی با هم تعامل دارند؛
  • برای یک ترکیب مشخص، چند Action باید هم‌زمان اتفاق بیفتد؛
  • ذی‌نفعان درباره اولویت یا استثنای قوانین برداشت یکسانی ندارند؛
  • باگ‌ها در ترکیب وضعیت‌ها رخ می‌دهند، نه در یک مقدار منفرد؛
  • لازم است پوشش قوانین به‌صورت قابل شمارش گزارش شود.

برای یک فیلد عددی منفرد، معمولاً تقسیم‌بندی هم‌ارزی و تحلیل مقدار مرزی انتخاب مستقیم‌تری است. برای رفتار وابسته به ترتیب رویدادها، State Transition مناسب‌تر است. در عمل این تکنیک‌ها مکمل یکدیگرند: جدول تصمیم مشخص می‌کند کدام ترکیب را تست کنیم و EP/BVA مقدار نماینده هر شرط را می‌سازد.

اجزای جدول تصمیم

یک Decision Table استاندارد چهار بخش مفهومی دارد:

بخش کارکرد نمونه
Condition Stub فهرست شرط‌هایی که روی تصمیم اثر دارند «مشتری ویژه است؟»
Condition Entry مقدار هر شرط در یک قانون T، F، مقدار یا بازه
Action Stub فهرست خروجی‌ها یا اقدام‌های ممکن «ارسال رایگان اعمال شود»
Action Entry مشخص می‌کند Action در آن قانون رخ می‌دهد یا نه X یا خانه خالی

هر ستون شامل Condition Entryها و Action Entryهای مرتبط، یک قانون یا Rule است. برای نام‌گذاری قابل رهگیری از R1، R2 و مانند آن استفاده کنید؛ سپس شناسه Rule را داخل Test Case و گزارش اجرا نگه دارید.

علائم T، F، خط تیره و N/A چه معنایی دارند؟

  • T یا Y: شرط برقرار است.
  • F یا N: شرط برقرار نیست.
  • – یا Don’t Care: مقدار شرط برای نتیجه این Rule اثری ندارد؛ هر مقدار معتبر آن پذیرفتنی است.
  • N/A یا Infeasible: این ترکیب از نظر دامنه یا منطق سیستم شدنی نیست.
  • X در Action: اقدام باید رخ دهد؛ خانه خالی یعنی نباید رخ دهد.

Don’t Care و N/A یکی نیستند. خط تیره یعنی چند مقدار متفاوت یک نتیجه یکسان می‌سازند و می‌توان آن قوانین را ادغام کرد. N/A یعنی اصلاً نمی‌توان آن ترکیب را در سیستم ساخت. یکی کاهش معتبر قوانین است؛ دیگری باید با دلیل شدنی‌نبودن مستند شود.

جدول محدود و جدول گسترده

Limited-entry Decision Table

در جدول Limited-entry، Conditionها و Actionها معمولاً بولی‌اند: درست یا غلط. اگر n شرط بولی مستقل داشته باشیم، جدول کامل حداکثر 2^n Rule دارد. سه شرط، ۸ قانون و ده شرط، ۱۰۲۴ قانون می‌سازند.

Extended-entry Decision Table

در جدول Extended-entry، یک شرط می‌تواند چند مقدار گسسته، Partition یا بازه داشته باشد؛ مثلاً نوع مشتری «عادی/ویژه/همکار» یا مبلغ سفارش در سه بازه. تعداد ترکیب‌های جدول کامل، حاصل‌ضرب تعداد مقادیر شرط‌هاست، نه الزاماً توان دو.

اگر شرط سن عددی است، بهتر است ابتدا با EP/BVA بازه‌ها و مرزهای معنادار را تعریف کنید و سپس نام Partitionها را در جدول بیاورید. قرار دادن هر عدد ممکن در Decision Table هم غیرضروری است و هم مدل را غیرقابل نگهداری می‌کند.

آموزش ساخت جدول تصمیم؛ مثال فروشگاه ایرانی

نیازمندی زیر را در نظر بگیرید:

اگر کد تخفیف معتبر باشد، تخفیف کد اعمال می‌شود و تخفیف وفاداری با آن جمع نمی‌شود. اگر کد معتبر نباشد و مشتری ویژه باشد، ۵٪ تخفیف وفاداری اعمال می‌شود. برای سبد حداقل ۲٬۰۰۰٬۰۰۰ ریال، ارسال رایگان است؛ این قانون مستقل از نوع تخفیف عمل می‌کند.

سه Condition و چهار Action داریم:

  • C1: مشتری ویژه است؟
  • C2: مبلغ سبد حداقل ۲٬۰۰۰٬۰۰۰ ریال است؟
  • C3: کد تخفیف معتبر است؟
  • A1: تخفیف کد اعمال شود.
  • A2: تخفیف وفاداری ۵٪ اعمال شود.
  • A3: ارسال رایگان شود.
  • A4: هیچ تخفیفی اعمال نشود.

مرحله ۱: ساخت جدول کامل

شرط/اقدام R1 R2 R3 R4 R5 R6 R7 R8
C1: مشتری ویژه؟ T T T T F F F F
C2: مبلغ به حد ارسال رایگان رسیده؟ T T F F T T F F
C3: کد معتبر؟ T F T F T F T F
A1: تخفیف کد X X X X
A2: تخفیف وفاداری ۵٪ X X
A3: ارسال رایگان X X X X
A4: بدون تخفیف X X

این جدول یک ابهام مهم را آشکار می‌کند: «کد نامعتبر» شامل نداشتن کد هم می‌شود یا فقط کدی که وارد شده و رد شده است؟ آیا باید برای کد ردشده پیام خطا نشان دهیم؟ Decision Table نیازمندی را کامل نمی‌کند؛ ابهام را قابل مشاهده می‌کند تا Product Owner پاسخ دهد.

مرحله ۲: بررسی سازگاری و کامل‌بودن

پیش از ساده‌سازی، چهار پرسش بپرسید:

  • Completeness: آیا هر ترکیب شدنی Rule دارد؟
  • Consistency: آیا دو قانون قابل اعمال، Actionهای متناقض ندارند؟
  • Feasibility: آیا هر ترکیب واقعاً در دامنه قابل ساخت است؟
  • Correctness: آیا Actionها همان رفتار مورد انتظار کسب‌وکارند؟

بررسی این چهار مورد بهتر است بخشی از تحلیل نیازمندی توسط تستر باشد، نه فعالیتی که پس از پیاده‌سازی آغاز شود.

مرحله ۳: ساده‌سازی با Don’t Care

وقتی C3 معتبر است، ویژه‌بودن مشتری روی نوع تخفیف اثری ندارد؛ بنابراین جفت قوانین R1/R5 و R3/R7 قابل ادغام‌اند. اما C2 را نمی‌توان حذف کرد، چون ارسال رایگان را تغییر می‌دهد.

شرط/اقدام M1 M2 M3 M4 M5 M6
C1: مشتری ویژه؟ – – T T F F
C2: مبلغ به حد ارسال رایگان رسیده؟ T F T F T F
C3: کد معتبر؟ T T F F F F
A1: تخفیف کد X X
A2: تخفیف وفاداری ۵٪ X X
A3: ارسال رایگان X X X
A4: بدون تخفیف X X

جدول کوچک‌شده شش Rule دارد، اما هر هشت ترکیب جدول کامل را نمایندگی می‌کند. ساده‌سازی درست باید رفتار را حفظ کند. دو ستون را فقط به این دلیل که Action مشترک دارند ادغام نکنید؛ همه Conditionهای دیگر باید یکسان باشند و Condition متفاوت واقعاً روی نتیجه بی‌اثر باشد.

چگونه از هر Rule تست‌کیس استخراج کنیم؟

برای پوشش هر Rule حداقل یک Test Case بسازید. Rule انتزاعی است؛ Test Case باید مقدار واقعی، پیش‌شرط، مراحل و نتیجه قابل مشاهده داشته باشد. نمونه M3:

شناسه DT-DISCOUNT-M3
هدف تخفیف وفاداری و ارسال رایگان برای مشتری ویژه بدون کد معتبر
پیش‌شرط حساب ویژه فعال؛ کالاها مجاز برای تخفیف؛ نشانی در محدوده ارسال
داده سبد ۲٬۰۰۰٬۰۰۰ ریال؛ بدون کد یا کد نامعتبر طبق قرارداد
Expected ۵٪ تخفیف وفاداری، هزینه ارسال صفر و عدم اعمال تخفیف کد
Evidence ریز محاسبه سفارش، Response API و وضعیت ذخیره‌شده

اگر M1 برای مشتری ویژه و عادی با خط تیره ادغام شده، از نظر Coverage اجرای یکی از مقدارهای معتبر کافی است؛ اما اگر ریسک نقش مشتری بالاست، می‌توانید هر دو مقدار را تست کنید. «حداقل پوشش تکنیک» همیشه با «پوشش کافی بر اساس ریسک» یکی نیست.

برای تبدیل Ruleها به سند اجرایی استاندارد، از قالب مقاله نوشتن تست‌کیس حرفه‌ای استفاده کنید.

پوشش تست جدول تصمیم چگونه محاسبه می‌شود؟

طبق بخش Decision Table Testing در سرفصل رسمی ISTQB CTFL v4.۰.۱، Coverage Itemها ستون‌های دارای ترکیب شدنی‌اند. فرمول پوشش چنین است:

Decision Table Coverage =
تعداد Ruleهای شدنی اجراشده ÷ کل Ruleهای شدنی × 100

اگر جدول خلاصه شش Rule شدنی داشته باشد و پنج مورد اجرا شوند، پوشش 5/6 = 83.3% است. ستون‌های ناممکن از مخرج حذف می‌شوند، اما باید دلیل ناممکن بودنشان ثبت شود. پوشش ۱۰۰٪ نیز فقط می‌گوید همه Ruleهای مدل اجرا شده‌اند؛ درست یا کامل بودن خود مدل را تضمین نمی‌کند.

مثال دوم؛ چرا جدول ورود قدیمی می‌تواند خطرناک باشد؟

یک مثال آموزشی رایج می‌گوید برای «نام کاربری نامعتبر» و «رمز اشتباه» دو پیام متفاوت نشان دهید. این رفتار ممکن است به مهاجم کمک کند وجود حساب را حدس بزند. نیازمندی امن‌تر می‌تواند برای هر دو حالت پیام عمومی یکسان داشته باشد و جزئیات را فقط در Log امن ثبت کند.

شرط/اقدام L1 L2 L3
حساب فعال و شناخته‌شده؟ T T F
رمز/عامل احراز معتبر؟ T F –
ایجاد Session X
نمایش پیام عمومی شکست X X
افزایش شمارنده کنترل‌شده تلاش X طبق سیاست

این جدول هنوز برای Rate Limit، MFA، حساب قفل‌شده، بازیابی رمز و سیاست حریم خصوصی کافی نیست. نکته این است که مثال تست نباید رفتار ناامن را به‌عنوان خروجی درست تثبیت کند.

جدول تصمیم و سایر تکنیک‌های طراحی تست

تکنیک پرسش اصلی نمونه کاربرد
Equivalence Partitioning کدام گروه‌های ورودی رفتار مشابه دارند؟ مبلغ معتبر، منفی یا بیش از سقف
Boundary Value Analysis رفتار اطراف مرزها چگونه است؟ ۱٬۹۹۹٬۹۹۹، ۲٬۰۰۰٬۰۰۰ و ۲٬۰۰۰٬۰۰۱ ریال
Decision Table ترکیب شرط‌ها چه Actionی می‌سازد؟ عضویت × مبلغ × اعتبار کد
State Transition رویداد و ترتیب، State را چگونه تغییر می‌دهد؟ فعال، تعلیق و قفل حساب
Use Case/Scenario مسیر تعامل بازیگر با سیستم چیست؟ خرید تا پرداخت و تحویل

برای مثال فروشگاه، Decision Table تخفیف را تعیین می‌کند، BVA مقدارهای اطراف ۲٬۰۰۰٬۰۰۰ ریال را انتخاب می‌کند و State Transition تغییر وضعیت سفارش را می‌سنجد. ترکیب هدفمند تکنیک‌ها از تکرار بی‌هدف تست جلوگیری می‌کند.

مدیریت انفجار ترکیبیاتی

رشد تعداد Ruleها یک هشدار است، نه مجوز حذف تصادفی ستون‌ها. این راهکارها را به‌ترتیب بررسی کنید:

  1. شرط‌های بی‌اثر را حذف کنید: هر داده‌ای Condition نیست؛ فقط عواملی را نگه دارید که تصمیم را تغییر می‌دهند.
  2. Partition بسازید: مقدارهای هم‌رفتار را پیش از ورود به جدول گروه‌بندی کنید.
  3. ترکیب ناممکن را مستند کنید: N/A را با دلیل دامنه‌ای یا فنی علامت بزنید.
  4. قوانین هم‌ارز را Collapse کنید: فقط وقتی Don’t Care واقعاً رفتار را تغییر نمی‌دهد.
  5. منطق مستقل را جدا کنید: جدول قیمت‌گذاری را با جدول مجوز یا حمل‌ونقل قاطی نکنید، مگر تعامل آن‌ها موضوع تست باشد.
  6. ریسک را اعمال کنید: اگر هنوز جدول بزرگ است، قوانین بحرانی را بر اساس احتمال و اثر اولویت دهید.
  7. از Pairwise آگاهانه استفاده کنید: پوشش جفت‌ها جای پوشش کامل Business Ruleهای الزامی را نمی‌گیرد.

اتوماسیون تست‌های Decision Table

جدول تصمیم برای Data-Driven Testing مناسب است: هر Rule یک ردیف داده و Oracle مورد انتظار می‌شود. می‌توانید Condition Entryها را به Fixture یا Parameter و Actionها را به Assertion تبدیل کنید.

[
  {
    "rule": "M3",
    "premium": true,
    "cartTotal": 2000000,
    "couponValid": false,
    "expectedDiscountType": "LOYALTY",
    "expectedShipping": 0
  }
]

با این حال، Spreadsheet را منبع حقیقت جدا از نیازمندی رها نکنید. Rule ID، نسخه قانون و مرجع Requirement باید کنار داده بماند. تغییر عمدی قیمت‌گذاری باید هم مدل و هم تست را در یک Review به‌روز کند. برای ارزیابی ارزش و نگهداری این تست‌ها، راهنمای انتخاب تست مناسب برای اتوماسیون را ببینید.

در اجرای خودکار، نتیجه فقط Pass/Fail نیست. شکست باید Rule، Conditionهای واقعی، Action مورد انتظار، مقدار واقعی و نسخه قوانین را گزارش کند تا تیم بتواند اختلاف Requirement، Test Data یا پیاده‌سازی را تشخیص دهد.

خطاهای رایج در Decision Table Testing

  • شرط مبهم: «مشتری معتبر است؟» چند مفهوم هویت، وضعیت و مجوز را مخلوط می‌کند.
  • ترکیب ورودی و نتیجه: Condition باید قابل ارزیابی و Action باید خروجی قابل مشاهده باشد.
  • فرض استقلال بدون بررسی: حاصل 2^n فقط برای n شرط بولی جدول کامل است؛ بعضی ترکیب‌ها ممکن است شدنی نباشند.
  • استفاده اشتباه از خط تیره: «نمی‌دانیم» یا «تست نکرده‌ایم» Don’t Care نیست.
  • حذف Ruleهای عجیب: ترکیب نادر ممکن است همان ریسک بحرانی باشد.
  • تست‌نکردن عدم وقوع Action: علاوه بر «تخفیف اعمال شد»، باید «تخفیف دیگر اعمال نشد» را Assert کنید.
  • تمرکز فقط بر UI: محاسبه ذخیره‌شده، Response API و رویداد مالی نیز باید کنترل شوند.
  • گزارش پوشش بدون مدل: درصدی که جدول و Ruleهای شدنی آن مشخص نیستند قابل اتکا نیست.
  • عدم بازبینی با کسب‌وکار: جدول منظم می‌تواند منطق اشتباه را هم بسیار منظم نمایش دهد.

چک‌لیست بازبینی جدول تصمیم

  • دامنه تصمیم و Requirement مرجع مشخص است.
  • Conditionها مستقل، قابل ارزیابی و بدون هم‌پوشانی مبهم‌اند.
  • Actionها نتیجه قابل مشاهده و قابل Assert دارند.
  • برای جدول کامل، تعداد ترکیب‌های مورد انتظار محاسبه شده است.
  • هر Rule شدنی یک نتیجه تعریف‌شده دارد.
  • Ruleهای ناممکن با N/A و دلیل مستند شده‌اند.
  • Don’t Care فقط برای Condition واقعاً بی‌اثر استفاده شده است.
  • جدول از نظر Completeness، Consistency، Feasibility و Correctness بازبینی شده است.
  • برای هر Rule انتخاب‌شده دست‌کم یک Test Case قابل تکرار وجود دارد.
  • مقادیر مرزی Conditionهای عددی جداگانه پوشش داده شده‌اند.
  • هم وقوع و هم عدم وقوع Actionهای حساس Assert می‌شود.
  • Rule ID تا Requirement، Test Case و Result قابل رهگیری است.
  • درصد Coverage فقط بر Ruleهای شدنی محاسبه شده است.
  • تغییر Business Rule باعث Review جدول و تست‌های وابسته می‌شود.

جمع‌بندی

تست جدول تصمیم، منطق چندشرطی را از متن پراکنده به مجموعه‌ای قابل بازبینی و قابل اندازه‌گیری از Ruleها تبدیل می‌کند. ارزش اصلی آن فقط تولید تست‌کیس نیست؛ هنگام ساخت جدول، شکاف، تناقض، اولویت نامشخص و ترکیب ناممکن زودتر دیده می‌شود.

برای شروع، یک قانون واقعی با دو یا سه Condition انتخاب کنید، جدول کامل را بسازید، Ruleهای ناممکن را با دلیل جدا کنید، سپس فقط ادغام‌های بی‌خطر را انجام دهید. هر ستون شدنی را به یک Test Case با داده و Expected Result واقعی تبدیل و نتیجه را در مرحله اجرای تست با Rule ID ثبت کنید.

سوالات متداول درباره تست جدول تصمیم

تست جدول تصمیم چیست؟

تکنیکی مبتنی بر مشخصات است که ترکیب Conditionها و Actionهای متناظر را به شکل Ruleهای ستونی مدل می‌کند. هر Rule شدنی مبنای حداقل یک تست‌کیس قرار می‌گیرد.

برای سه شرط چند Rule داریم؟

اگر هر سه شرط بولی و مستقل باشند، جدول کامل حداکثر 2^3 = 8 Rule دارد. در جدول چندمقداری، تعداد ترکیب‌ها حاصل‌ضرب تعداد مقادیر هر Condition است. Ruleهای ناممکن حذف یا N/A می‌شوند.

تفاوت Don’t Care و N/A چیست؟

Don’t Care با علامت «–» یعنی مقدار آن Condition نتیجه Rule را تغییر نمی‌دهد. N/A یعنی ترکیب مورد نظر اصولاً شدنی نیست. ادغام با Don’t Care پوشش چند ترکیب معتبر است؛ N/A از دامنه ترکیب‌های قابل اجرا خارج می‌شود.

پوشش ۱۰۰٪ جدول تصمیم چگونه به دست می‌آید؟

وقتی همه ستون‌های دارای ترکیب شدنی دست‌کم یک‌بار اجرا شوند. این درصد، پوشش Ruleهای همان مدل است و تضمین نمی‌کند Condition یا Action مهمی از مدل جا نیفتاده باشد.

آیا هر Rule دقیقاً یک Test Case می‌شود؟

حداقل یک Test Case برای هر Rule لازم است، اما ریسک ممکن است بیش از یکی بخواهد؛ مثلاً برای مقدارهای مرزی، نقش‌های متفاوت یا چند مقدار معتبر یک Don’t Care. برعکس، یک تست End-to-End ممکن است چند Rule را در مراحل مختلف لمس کند، ولی رهگیری نتیجه هر Rule باید روشن بماند.

منبع فنی

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