یک نیازمندی به ظاهر ساده را تصور کنید: «بازپرداخت سفارش پرداختشده، اگر درخواستکننده مجاز باشد و مهلت بازپرداخت نگذشته باشد، خودکار انجام شود؛ مگر اینکه کالا ارسال شده و تأیید فروشنده وجود نداشته باشد.» چند تست لازم است؟ کدام شرط واقعاً در نتیجه اثر دارد؟ اگر سفارش پرداخت نشده اما همه شرطهای دیگر برقرار باشند چه؟ آیا پیام رد کافی است یا باید نبود Side effect مالی را هم بررسی کرد؟
گراف علت و معلول (Cause–Effect Graphing یا CEG) زبان طبیعی را به یک مدل Boolean از شرطها، خروجیها و محدودیتها تبدیل میکند. ارزش اصلی آن «رسم شکل» نیست؛ وادارکردن تیم به تعریف دقیق Rule، کشف ترکیب ناممکن، بررسی Exhaustiveness و ساخت یک مبنای قابل ردگیری برای جدول تصمیم و تستکیس است. این مقاله با یک مثال کامل نشان میدهد چگونه CEG را بسازیم، اعتبارسنجی کنیم و بدون ادعای پوشش تضمینی به تست اجرایی تبدیل کنیم.
پاسخ کوتاه: گراف علت و معلول چیست؟
CEG یک تکنیک طراحی تست مبتنی بر Specification است که در آن:
- Cause یک شرط ورودی یا پیششرط قابل ارزیابی به True/False است؛
- Effect یک خروجی، اقدام یا تغییر وضعیت قابل مشاهده است؛
- رابطهها با AND، OR و NOT یا معادلههای منطقی بیان میشوند؛
- Constraint ترکیبهای ناممکن یا قواعد وابستگی را محدود میکند؛
- مدل پس از بازبینی به Decision Table یا ورودی یک روش تولید تست تبدیل میشود.
«علت» در این نام به معنی علت ریشهای باگ یا اثبات رابطه علّی در دنیای واقعی نیست؛ صرفاً شرطی است که در Specification به نتیجه منطقی مرتبط شده است.
CEG با چه چیزهایی اشتباه میشود؟
CEG با Fishbone Diagram فرق دارد
نمودار استخوانماهی برای ایدهپردازی درباره علتهای احتمالی یک مسئله یا Root cause analysis استفاده میشود. Cause–Effect Graph در تست نرمافزار، روابط Boolean ورودی و خروجیِ موردانتظار را مدل میکند. یکی برای Investigation است و دیگری برای Test design مبتنی بر Rule.
CEG اثبات Causality نیست
اگر مدل میگوید C1 AND C2 → E1، فقط قرارداد موردانتظار سیستم را بیان کردهایم. این مدل ثابت نمیکند C1 در جهان واقعی علت علمی E1 است و همچنین Root cause پیادهسازی معیوب را پیدا نمیکند.
CEG خودش تست اجرا نمیکند
گراف بهتنهایی Test data، Setup، Action، Oracle جزئی، Cleanup یا Coverage criterion کامل نمیسازد. باید روش استخراج Test را انتخاب و هر Rule را به داده و انتظار اجرایی تبدیل کرد.
چه زمانی CEG انتخاب مناسبی است؟
- نتیجه به چند شرط Boolean وابسته است؛
- نیازمندی با «اگر»، «و»، «یا»، «مگر»، «فقط در صورتی که» و استثنا نوشته شده است؛
- چند Effect از زیرعبارتهای مشترک استفاده میکنند؛
- ترکیبهای ناممکن، Requires یا Mutual exclusion داریم؛
- تیم درباره اولویت پیامها یا رفتار یک ترکیب اختلاف دارد؛
- Traceability از Rule به Test برای تصمیم مالی، مجوز یا Workflow مهم است؛
- یک جدول تصمیم مستقیم، به دلیل رابطههای تودرتو دشوار فهمیده میشود.
چه زمانی آن را انتخاب نکنیم؟
- یک شرط ساده با دو نتیجه داریم و جدول کوچک واضحتر است؛
- خطر اصلی روی مقدار مرزی پیوسته است، نه منطق ترکیبی؛
- رفتار به توالی Event و State history وابسته است؛
- Race، Retry، Timeout یا Concurrency محور اصلی نقص است؛
- خروجی احتمالاتی یا عددی است و Booleanکردن آن اطلاعات مهم را حذف میکند؛
- Specification آنقدر مبهم است که هنوز Rule قابل توافق نداریم؛
- گراف قرار است صدها Cause را یکجا نمایش دهد و مالک دامنهای ندارد.
پیشنیاز: Test basis را آماده کنید
از User story تنها شروع نکنید. Rule ممکن است بین چند منبع پخش شده باشد:
- Acceptance criteria و مثالهای کسبوکار؛
- قوانین دامنه و Policy نسخهدار؛
- API contract، Schema و Error catalog؛
- Workflow یا State diagram؛
- Incidentهای گذشته و رفتار Legacy؛
- الزام قراردادی، مالی یا حریم خصوصی؛
- مشاهده رفتار فعلی که شاید با Specification اختلاف دارد.
در راهنمای تحلیل نیازمندیها سؤالهای لازم برای Scope، Oracle، داده و Testability آمده است. اگر منابع متناقضاند، پیش از مدلسازی «مالک تصمیم» و نسخه معتبر Rule را تعیین کنید.
واژگان دقیق مدل
| عنصر | تعریف عملی | نمونه |
|---|---|---|
| Cause | شرط Boolean قابل مشاهده یا قابل ساخت | C1: سفارش در وضعیت Paid است |
| Effect | خروجی/اقدام قابل مشاهده و قابل Assert | E1: Refund خودکار ایجاد میشود |
| Intermediate | زیرعبارت نامدار برای سادهکردن منطق | I1: پیششرطهای پایه معتبرند |
| Constraint | قید روی ترکیبهای feasible یا رابطه Effectها | C5 فقط وقتی ممکن است که C4 برقرار باشد |
| Rule | یک ترکیب Condition با Actionهای متناظر | Paid+Owner+Within+Shipped+No approval → Manual |
| Test | یک Instance اجرایی از Rule با داده و Oracle | سفارش مصنوعی R-۱۰۴ با وضعیت مشخص |
Cause خوب چگونه نوشته میشود؟
نام Cause باید مثبت، اتمیک و قابل ارزیابی باشد. «کاربر معتبر است» مبهم است؛ آیا منظور Authentication، مالکیت سفارش یا محدودنبودن حساب است؟ آن را به شرطهای مستقل و قابل ردگیری تقسیم کنید. دو منفی مانند «کاربر غیرغیرمجاز نیست» احتمال خطا را بالا میبرد.
Effect باید مشاهدهپذیر باشد
«سیستم درست کار میکند» Effect نیست. نتیجه را به اقدام دامنهای، وضعیت، پاسخ API، پیام و نبود Side effect تبدیل کنید. Effect داخلی فقط وقتی مفید است که از API، Event، State یا Log کنترلشده قابل مشاهده باشد.
عملگرهای منطقی CEG
AND
Effect فقط وقتی فعال است که همه ورودیهای لازم True باشند:
I1 = C1 AND C2 AND C3
OR
حداقل یکی از شرطها برای فعالشدن نتیجه کافی است:
E3 = NOT C1 OR NOT C2 OR NOT C3
NOT
شرط یا زیرعبارت را معکوس میکند. پرانتز را صریح بنویسید؛ NOT (C1 AND C2) با (NOT C1) AND C2 یکسان نیست.
گره میانی
اگر زیرعبارت تکرار میشود، آن را نامگذاری کنید:
I1 = C1 AND C2 AND C3
E1 = I1 AND (NOT C4 OR C5)
E2 = I1 AND C4 AND NOT C5
گره میانی Readability را بهتر میکند، اما Cause تازهای از دامنه نیست و نباید بهعنوان ورودی مستقل Test data تعبیر شود.
Constraintها: نماد کافی نیست
کتابها و ابزارها ممکن است برای Constraint از برچسبهای E، I، O، R و M استفاده کنند. تعریف رایج چنین است:
| قید | معنای رایج | بیان صریح |
|---|---|---|
| Exclusive | حداکثر یکی True است | NOT (C1 AND C2) |
| Inclusive | حداقل یکی True است | C1 OR C2 OR C3 |
| One and only one | دقیقاً یکی True است | At-least-one AND At-most-one |
| Requires | True بودن A، B را لازم میکند | A → B یا NOT A OR B |
| Masking | یک Effect بر Effect دیگر اولویت/پوشانندگی دارد | Rule دقیق اولویت را بنویسید |
چون Convention ابزارها همیشه یکسان نیست، کنار نماد، عبارت Boolean و جمله دامنهای را ثبت کنید. قید باید «ناممکن یا ممنوع در مدل» را بیان کند؛ آن را فقط برای کوچککردن Suite اضافه نکنید.
Constraint با Negative test فرق دارد
اگر UI اجازه نمیدهد دو روش تحویل همزمان انتخاب شوند، ترکیب از جریان معتبر حذف میشود؛ اما API شاید هنوز چنین درخواست ناسازگاری را دریافت کند. در این حالت یک Negative test صریح برای رد امن لازم است. Infeasible در یک Interface لزوماً Infeasible در کل سیستم نیست.
فرآیند کامل از Requirement تا Test
- Scope و Test basis معتبر را تعیین کنید.
- جملهها را به Cause و Effect اتمیک تبدیل کنید.
- رابطهها را با AND/OR/NOT و گره میانی مدل کنید.
- Constraintهای feasible و اولویت Effectها را صریح بنویسید.
- Reachability، تناقض، Exhaustiveness و استقلال Effectها را بازبینی کنید.
- روش استخراج Test و Coverage criterion را انتخاب کنید.
- گراف را به Decision Table کامل یا فشرده تبدیل کنید.
- برای Conditionهای عددی، Partition و Boundary data بسازید.
- هر Rule را به Setup، Action، Oracle و Cleanup تبدیل کنید.
- Model، Requirement، Rule، Test و Defect را نسخهدار و Traceable نگه دارید.
مثال کامل: سیاست بازپرداخت فروشگاه ایرانی
نسخه Rule مورد توافق تیم:
درخواست بازپرداخت فقط برای سفارش Paid، درخواستکننده مجاز و داخل مهلت Policy بررسی میشود. اگر کالا هنوز ارسال نشده باشد، بازپرداخت خودکار است. اگر کالا ارسال شده باشد، وجود تأیید فروشنده بازپرداخت خودکار را مجاز میکند؛ در غیر این صورت درخواست به بررسی دستی میرود. شکست هر پیششرط پایه باید درخواست را بدون Side effect مالی رد کند. تأیید فروشنده فقط برای سفارش ارسالشده قابل ثبت است.
این Rule نمونه آموزشی است؛ Policy واقعی باید مبلغ، نوع کالا، مصرفشدن خدمت، پرداخت چندبخشی، اختلاف، مالیات و Settlement را نیز تعیین کند.
گام ۱: Causeها و Effectها را استخراج کنید
Causeها
| ID | شرط True | منبع/نکته |
|---|---|---|
| C1 | وضعیت پرداخت سفارش Paid است | Order/Payment state |
| C2 | درخواستکننده مالک سفارش یا Role مجاز است | Authorization policy |
| C3 | درخواست داخل مهلت بازپرداخت است | Policy version و زمان مرجع |
| C4 | کالا ارسال شده است | Shipment state |
| C5 | تأیید معتبر فروشنده ثبت شده است | فقط برای C4=True feasible |
Effectها
| ID | نتیجه True | Oracle حداقلی |
|---|---|---|
| E1 | Refund خودکار ایجاد میشود | یک Refund و یک Ledger effect؛ پاسخ موفق |
| E2 | درخواست در صف بررسی دستی قرار میگیرد | یک Review case؛ بدون Refund مالی |
| E3 | درخواست رد میشود | Reason code مشخص؛ بدون Refund و Review |
عبارت «درخواستکننده مجاز» هنوز باید با ماتریس Role×Action×Resource ownership جزئی شود. برای این آموزش آن را یک Cause میگیریم، اما Test data باید Owner و Role را مشخص کند.
گام ۲: رابطههای Boolean را بسازید
I1 = C1 AND C2 AND C3
E1 = I1 AND (NOT C4 OR C5)
E2 = I1 AND C4 AND NOT C5
E3 = NOT C1 OR NOT C2 OR NOT C3
آیا Effectها Exhaustive هستند؟
برای هر ترکیب feasible باید دقیقاً یکی از E1، E2 یا E3 فعال شود. اگر I1=False، E3 فعال است. اگر I1=True، دو حالت Shipment داریم: C4=False به E1 میرسد؛ C4=True با C5=True به E1 و با C5=False به E2 میرسد. پس مدل در Scope تعریفشده خروجی دارد.
آیا Effectها Mutually exclusive هستند؟
E3 فقط وقتی یکی از پیششرطهای I1 شکست خورده است؛ E1 و E2 به I1 نیاز دارند، پس با E3 همزمان نمیشوند. E1 در شاخه shipped به C5 و E2 به NOT C5 نیاز دارد، پس آن دو نیز همزمان نیستند. این Proof کوچک باید در Review ثبت شود؛ اعتماد به شکل کافی نیست.
گام ۳: Constraint را اعمال کنید
قانون دامنه میگوید تأیید فروشنده برای سفارش ارسالنشده وجود ندارد:
C5 → C4
Equivalent: NOT C5 OR C4
Invalid combination: C5=True AND C4=False
این یک Requires constraint است. اگر داده Legacy واقعاً میتواند Approval بدون Shipment بسازد، ترکیب را «ناممکن» اعلام نکنید؛ آن را یک تست ناسازگاری داده یا Migration در نظر بگیرید. Constraint باید با معماری و داده واقعی Review شود.
گام ۴: مدل را پیش از تولید تست اعتبارسنجی کنید
بازبینی دامنهای
- آیا Paid بودن به معنی Captured است یا Authorized نیز پذیرفته میشود؟
- مهلت از زمان پرداخت، تحویل یا ثبت درخواست محاسبه میشود؟
- Approval تاریخ انقضا، Scope کالا یا Signer مجاز دارد؟
- Manual review واقعاً نباید Refund بسازد؟
- اگر Order چند Shipment دارد، C4 چگونه تعریف میشود؟
- Reason code رد برای C1/C2/C3 متفاوت است یا یکسان؟
بازبینی ساختاری
- Cause یا Effect بدون اتصال نداریم؛
- هر Effect دستکم یک ترکیب feasible دارد؛
- هر Cause در حداقل یک Rule روی نتیجه اثر میگذارد، یا دلیل Context بودنش روشن است؛
- Constraintها با هم تناقض و مدل Unsatisfiable نمیسازند؛
- اثرها در صورت الزام، Exhaustive و Mutually exclusive هستند؛
- پرانتز و اولویت عملگرها مبهم نیست؛
- نمونههای Known-good و Known-bad با خروجی مدل سازگارند.
پژوهش منتشرشده درباره ابزارهای CEG نیز بر دشواری ساخت Specification دقیق و اعتبارسنجی عناصر گراف تأکید دارد؛ برای مطالعه روش و notation میتوانید مقاله New Graphical Software Tool for Creating Cause-Effect Graph Specifications را ببینید.
گام ۵: گراف را به جدول تصمیم تبدیل کنید
برای خوانایی، جدول را با Ruleهای فشرده میسازیم. علامت – یعنی مقدار Condition برای Action این Rule مهم نیست؛ N/A یعنی طبق Constraint feasible نیست. در Ruleهای دارای «–»، فقط ترکیبهای feasible منظورند.
| Condition / Action | R1 | R2 | R3 | R4 | R5 | R6 |
|---|---|---|---|---|---|---|
| C1: Paid | T | T | T | F | T | T |
| C2: Authorized owner | T | T | T | – | F | T |
| C3: Within policy | T | T | T | – | – | F |
| C4: Shipped | F | T | T | – | – | – |
| C5: Merchant approval | N/A | T | F | – | – | – |
| E1: Auto refund | X | X | ||||
| E2: Manual review | X | |||||
| E3: Reject | X | X | X |
چرا سه Rule رد داریم؟
R4 نخستین پیششرط C1 را False میکند، R5 با C1=True شکست C2 را جدا میکند و R6 با C1/C2=True شکست C3 را جدا میکند. این ساختار هر شرط پایه را در یک Rule قابل تشخیص میکند و Reason code متفاوت را نیز میتوان Assert کرد.
آیا این جدول Full است؟
خیر؛ جدول فشرده است. Full table برای پنج Cause حداکثر ۳۲ ترکیب خام دارد و Constraint تعدادی را infeasible میکند. Ruleهای دارای «–» چند ترکیب با Action یکسان را ادغام کردهاند. نسخه Full برای Verification ماشینی مفید است؛ نسخه فشرده برای Review و اجرای پایه خواناتر است.
ISTQB CTFL 4.0.1 جدول تصمیم را بر پایه Condition، Action و Rule توضیح میدهد، «–» را irrelevant و N/A را infeasible میداند و Coverage را نسبت ستونهای feasible اجراشده تعریف میکند. راهنمای گامبهگام داخلی در آموزش تست جدول تصمیم در دسترس است.
گام ۶: Ruleها را به Test Case اجرایی تبدیل کنید
| Test | داده/شرایط | انتظار اصلی |
|---|---|---|
| T-R1 | Paid، Owner، داخل مهلت، ارسالنشده، بدون Approval | یک Auto refund؛ بدون Review |
| T-R2 | Paid، Owner، داخل مهلت، ارسالشده، Approval معتبر | یک Auto refund؛ بدون Review |
| T-R3 | Paid، Owner، داخل مهلت، ارسالشده، بدون Approval | یک Manual review؛ بدون Refund |
| T-R4 | Not paid، سایر دادهها feasible | Reject با PAYMENT_NOT_ELIGIBLE؛ بدون Side effect |
| T-R5 | Paid، درخواستکننده غیرمالک/بیمجوز | Reject یا پاسخ ضد Enumeration طبق Security policy |
| T-R6 | Paid، Owner، خارج مهلت | Reject با POLICY_WINDOW_EXPIRED؛ بدون Side effect |
Oracle چندلایه
برای T-R3 فقط دیدن پیام «در حال بررسی» کافی نیست:
- HTTP status و Response schema درست است؛
- Review case دقیقاً یکبار با Order ID صحیح ساخته میشود؛
- هیچ Refund، Ledger debit یا پیام موفقیت پرداخت ایجاد نمیشود؛
- Event مناسب منتشر و داده حساس حذف میشود؛
- Retry همان درخواست Duplicate case نمیسازد؛
- UI وضعیت قابل پیگیری و متن فارسی روشن نمایش میدهد.
ساختار Setup، Action، Expected result و Cleanup در راهنمای نوشتن تستکیس آمده است.
Boolean model را به داده واقعی نگاشت کنید
Causeهای Boolean اغلب از دامنههای چندمقداری ساخته میشوند. پیش از نگاشت، Partition و Boundary را تعیین کنید.
نمونه C3: داخل مهلت
اگر Policy میگوید «تا هفت روز پس از تحویل، inclusive»، فقط True/False کافی نیست. دستکم این دادهها را بسازید:
- یک زمان معمول داخل مهلت؛
- دقیقاً روی مرز هفت روز طبق Timezone مرجع؛
- یک Tick یا ثانیه پس از مرز؛
- زمان پیش از تحویل یا Clock skew نامعتبر؛
- تغییر روز در نیمهشب و Calendar نمایش فارسی در UI.
CEG میگوید C3 چگونه با شروط دیگر ترکیب میشود؛ تقسیمبندی همارزی و تحلیل مقدار مرزی نمونههای True/False را دقیق میکند. یک Rule فشرده ممکن است بیش از یک Test برای مرزهای پرریسک داشته باشد.
Coverage در CEG دقیقاً چیست؟
عبارت «گراف کامل است» Coverage قابل اندازهگیری نیست. معیار را پیش از اجرا انتخاب کنید:
- Effect coverage: هر Effect دستکم یکبار True میشود؛ بسیار ضعیف برای منطق پیچیده.
- Feasible rule coverage: همه ستونهای feasible جدول تصمیم اجرا میشوند.
- Cause value coverage: هر Cause در صورت feasible بودن True و False میشود.
- Condition influence: تستها نشان میدهند تغییر یک Condition میتواند Effect هدف را تغییر دهد؛ نیازمند روش تولید مشخص.
- Boolean fault-oriented criteria: مانند BOR یا روشهای دقیقتر؛ باید کلاس خطای هدف و الگوریتم روشن باشد.
- Risk coverage: Journey، Rule مالی، Authorization و Incident regressionهای نامگذاریشده اجرا میشوند.
پژوهش IBM درباره CEG-BOR تضمین را به تشخیص کلاسهای مشخصی از خطاهای عملگر Boolean در راهبرد BOR محدود میکند. این نتیجه را نباید به «CEG همه باگها را تضمین میکند» تعمیم داد. Coverage مدل نیز Coverage پیادهسازی، داده، State، Performance یا Security نیست.
روشهای استخراج Test از گراف
جدول تصمیم کامل
همه ترکیبهای feasible Causeها را محاسبه و Effectها را Forward-evaluate کنید. شفاف و قابل Verify است، اما با افزایش Causeها نمایی رشد میکند.
جدول تصمیم فشرده
Ruleهای با Action یکسان را با Don’t-care ادغام کنید. خوانایی بهتر میشود، اما باید ثابت کنید ادغام معنای Rule را تغییر نداده و ترکیب infeasible پنهان نشده است.
روشهای Fault-oriented
BOR، MUMCUT، MC/DC-like criteria و روشهای پژوهشی برای Boolean expression هدفهای متفاوتی دارند. انتخاب آنها نیازمند Tooling، دانش و Definition of coverage است. صرفاً نوشتن «هر Effect یک بار» جای این معیارها را نمیگیرد.
Risk-based selection
وقتی Full rule coverage گران است، Ruleهای مالی/مجوزی، Incidentهای قبلی و Change area را اجباری نگه دارید و بقیه را با Risk کاهش دهید. تصمیم حذف باید ثبت شود؛ «شش تست داریم» بدون فهرست Ruleهای پوششندادهشده شفاف نیست.
CEG یا Decision Table؟
| معیار | Cause–Effect Graph | Decision Table |
|---|---|---|
| نقطه قوت | نمایش وابستگی، زیرعبارت مشترک و Constraint | نمایش فشرده Rule و استخراج مستقیم Case |
| واحد اصلی | Node و رابطه Boolean | Condition/Action و ستون Rule |
| Coverage | باید روش تولید/معیار جدا تعریف شود | Feasible rule coverage تعریف مستقیم دارد |
| مقیاس | گراف بزرگ بهسرعت شلوغ میشود | ستونها با Conditions رشد نمایی دارند |
| بهترین کاربرد | فهم و Review منطق تودرتو | Ruleهای قابل شمارش و Test execution |
این دو رقیب نیستند. اگر Rule کوچک است، مستقیم جدول تصمیم بسازید. اگر منطق چند Effect و Constraint تودرتو دارد، ابتدا CEG برای فهم و سپس Decision Table برای Coverage و Test case مفید است.
تکنیکهای مکمل CEG
Static testing
ساخت گراف پیش از کدنویسی نوعی Work product review را تقویت میکند: تناقض، Effect بیصاحب و اصطلاح مبهم زود دیده میشود. روشهای Review در راهنمای تست استاتیک تشریح شدهاند.
State transition
CEG ایستا میگوید کدام ترکیب شرط به چه نتیجهای میرسد. برای مسیر Pending→Approved، callback تکراری، Cancel پس از Shipment یا Retry دیررس از تست انتقال حالت استفاده کنید.
Pairwise
Pairwise برای پوشش Interactionهای feasible بین Factorها مفید است، اما Rule و Oracle را از CEG استخراج نمیکند. CEG میتواند Constraint و رابطههای دامنه را روشن کند؛ سپس در فضای Configuration کمخطر از Pairwise و Mixed-strength استفاده شود.
Exploratory testing
مدل فقط چیزهایی را پوشش میدهد که تیم در Specification دیده است. یک Charter بر مبنای Ruleهای پرریسک—مانند دو تب، Retry، تغییر مجوز و تأخیر Event—Gap مدل را جستوجو میکند. الگوی Session در راهنمای تست اکتشافی ساختاریافته آمده است.
ابزار و قالب مستندسازی
برای مدل کوچک
یک صفحه شامل واژهنامه Cause/Effect، معادلات Boolean، Constraintها و جدول تصمیم کافی است. Diagram باید قابل Diff و نسخهگذاری باشد؛ تصویر بدون متن منبع حقیقت خوبی نیست.
برای مدل متوسط
- شناسه پایدار برای Cause، Effect، Rule و Test؛
- فایل متنی Mermaid/Graphviz یا مدل قابل Export؛
- Truth table تولیدشده از Expression و بررسی Constraint؛
- Version control، Code review و Artifact CI؛
- جدول Traceability از Requirement تا Rule/Test/Defect.
برای مدل بزرگ
گراف را بر اساس Decision domain یا Effect تقسیم کنید. Interface بین زیرمدلها را مشخص و از SAT/BDD یا ابزار تخصصی برای Feasibility استفاده کنید. مقاله SoftwareX درباره ابزار متنباز ETF-RI-CEG-Advanced نمونهای از تولید Suite feasible و محاسبه معیارهاست؛ پیش از استفاده، نسخه، License، قابلیت Export و سازگاری مدل ابزار با notation تیم را در یک PoC بررسی کنید.
اتوماسیون CEG و جدول تصمیم
Ruleها را میتوان به CSV/JSON تبدیل و با Data builder اجرا کرد:
[
{
"rule": "R3",
"paid": true,
"authorized": true,
"withinPolicy": true,
"shipped": true,
"merchantApproval": false,
"expected": "MANUAL_REVIEW"
}
]
for (const rule of refundRules) {
test(rule.rule, async () => {
const order = await buildOrderFromRule(rule);
const result = await requestRefund(order, rule);
assertOutcome(result, rule.expected);
await assertNoUnexpectedFinancialSideEffects(order, rule.expected);
});
}
خطر Duplicate oracle
اگر تست همان تابع Boolean Production را کپی کند، خطای مشترک میتواند هر دو را سبز نگه دارد. Expected outcome را از جدول Reviewشده بخوانید، Assertion دامنهای مستقل بنویسید و برای Ruleهای حیاتی Mutation یا نمونههای Contradictory اجرا کنید.
تولید خودکار، Review را حذف نمیکند
Generator میتواند ترکیب feasible بسازد، اما Cause گمشده، Constraint غلط یا Effect غیرقابل مشاهده را اصلاح نمیکند. Model change باید Diff و تأیید Domain owner داشته باشد.
نقشهای تیم در یک جلسه CEG
- Domain/Product: Rule، استثنا و اولویت Effect را تأیید میکند؛
- Developer/Architect: Feasibility، State، API و Side effect را روشن میکند؛
- Tester: Condition، Constraint، Gap، Coverage و Testability را مدل میکند؛
- Security/Compliance: Authorization، Privacy و الزام حساس را بازبینی میکند؛
- Operations/Support: رفتار Legacy، Incident و Observability را اضافه میکند.
جلسه را روی یک Rule پرریسک و حداکثر ۳۰ تا ۶۰ دقیقه محدود کنید. خروجی باید سؤالهای باز با مالک و موعد داشته باشد، نه فقط یک شکل زیبا.
نگهداری و Traceability
| Artifact | شناسه نمونه | پیوند |
|---|---|---|
| Requirement/Policy | REF-POL-7.2 | منبع Rule و نسخه |
| Cause | C3 | Within policy |
| Effect | E2 | Manual review |
| Decision rule | R3 | C1..C5 → E2 |
| Automated/manual test | T-R3 | Instance اجرایی |
| Defect | BUG-241 | شکست Rule یا Gap مدل |
با تغییر Policy، اول مدل و Ruleها را Diff کنید، سپس Testها را بهروزرسانی کنید. اگر Test بدون Rule یا Rule بدون Test باقی ماند، Pipeline یا Review باید هشدار دهد.
معیارهای مفید
- Feasible rules اجراشده / کل feasible rules در Scope؛
- Cause و Effectهای بدون Trace به Requirement؛
- Ruleهای بدون Oracle اجرایی یا بدون Test data؛
- Constraintهای تأییدنشده یا سؤالهای دامنهای باز؛
- Defectهای ناشی از Rule گمشده، Model error یا Implementation error؛
- زمان Review و تغییر مدل در برابر تعداد Ruleهای پایدار؛
- تعداد Ruleهای پرریسک بدون Automation/Regression؛
- Mutation score برای Boolean logic فقط اگر روش و دامنه روشن است.
تعداد Node یا تعداد Test KPI کیفیت نیست. گراف بزرگتر میتواند فقط نشانه Scope نامناسب باشد. «کاهش Test case» نیز Outcome قطعی CEG نیست؛ روش Coverage و ساختار منطق تعیین میکند Suite چند Case دارد.
اشتباههای رایج
- برابر دانستن Cause با Root cause یا Causality علمی؛
- استخراج شرطهای مبهم و چندمفهومی از متن؛
- Booleanکردن زودهنگام مقدارهای عددی و جاانداختن Boundary؛
- فرض اینکه هر Cause مستقل از بقیه قابل True/False شدن است؛
- افزودن Constraint فقط برای کمکردن ترکیبها؛
- مخلوطکردن Intermediate node با ورودی قابل کنترل؛
- Effect غیرقابل مشاهده مانند «پردازش صحیح»؛
- نادیدهگرفتن نبود Side effect در مسیر رد و خطا؛
- رسم گراف بدون معادله، Legend و نسخه Requirement؛
- تبدیل دستی به جدول ناقص و ناسازگار؛
- استفاده نادرست از «–» برای ترکیب infeasible؛
- ادعای Coverage جامع بدون معیار تولید تست؛
- اعتماد به Effect coverage برای منطق حساس؛
- استفاده از CEG برای Sequence، Race یا Performance بدون مدل مکمل؛
- یک گراف عظیم برای کل محصول بدون تقسیم دامنه؛
- کپی همان منطق Production در Oracle خودکار؛
- بهروزرسانی Test بدون Diff مدل و Policy.
چکلیست بازبینی گراف علت و معلول
- Scope و نسخه Test basis مشخص است.
- هر Cause مثبت، اتمیک و قابل ساخت/مشاهده است.
- هر Effect قابل Assert و دارای Side effect روشن است.
- AND/OR/NOT با پرانتز و Intermediateهای نامدار ثبت شدهاند.
- هر نماد Constraint یک جمله و عبارت منطقی صریح دارد.
- ترکیب ناممکن در تمام Interfaceها واقعاً ناممکن است یا Negative test دارد.
- Effectهای لازم Reachable، Exhaustive و در صورت نیاز Mutually exclusive هستند.
- نمونههای Known-good/known-bad با Forward evaluation تأیید شدهاند.
- روش تولید Test و Coverage criterion نامگذاری شده است.
- Decision table شامل feasible، irrelevant و infeasible درست است.
- Conditionهای عددی با EP/BVA به داده واقعی نگاشت شدهاند.
- هر Rule Setup، Action، Oracle و Cleanup دارد.
- Boundary، State، Concurrency، Security و Exploratory مکمل بررسی شدهاند.
- Requirement→Cause/Effect→Rule→Test→Defect قابل ردگیری است.
- Model و Artifactها نسخهدار، قابل Diff و دارای مالکاند.
پرسشهای متداول
آیا Cause–Effect Graphing در ISTQB CTFL ۴.۰.۱ تکنیک مستقل آزمون است؟
CTFL ۴.۰.۱ تکنیک Decision Table را با Coverage مشخص آموزش میدهد، اما CEG را بهعنوان یکی از چهار تکنیک Black-box فصل Foundation فهرست نمیکند. CEG همچنان یک روش شناختهشده Specification-based است؛ آن را با ادعای «الزام فعلی CTFL» معرفی نکنید و Coverage استخراجشده را جدا تعریف کنید.
آیا هر ستون جدول تصمیم دقیقاً یک Test case است؟
برای Rule coverage معمولاً حداقل یک Test هر ستون feasible را اجرا میکند. اما یک Rule دارای Range، Boundary، Role یا داده متفاوت ممکن است چند Test لازم داشته باشد. ستون، Rule منطقی است؛ Test case یک Instance اجرایی با داده و Oracle است.
تفاوت Exclusive و One-and-only-one چیست؟
Exclusive معمولاً «حداکثر یکی» است و اجازه میدهد همه False باشند؛ One-and-only-one «دقیقاً یکی» است و علاوه بر انحصار، حداقل یکی را لازم میکند. چون notation ابزارها فرق دارد، عبارت Boolean را کنار نماد بنویسید.
آیا CEG تعداد تستها را همیشه کاهش میدهد؟
خیر. ممکن است ترکیبهای فراموششده را اضافه کند یا با جدول فشرده تعدادی Rule را ادغام کند. تعداد نهایی به Causeها، Constraintهای واقعی، Coverage criterion، Boundaryها و ریسک بستگی دارد. هدف اصلی، منطق قابل توضیح و پوشش قابل اندازهگیری است.
برای گراف بزرگ چه کار کنیم؟
Scope را بر اساس Decision domain یا Effect تقسیم کنید، Interface زیرمدلها را ثبت کنید و از ابزار بررسی Feasibility/Truth table استفاده کنید. اگر مدل هنوز بزرگ است، شاید Decision table، State model، DMN یا Rule engine artifact منبع مناسبتری باشد.
جمعبندی
گراف علت و معلول وقتی ارزشمند است که متن مبهم را به قرارداد Boolean قابل بحث تبدیل کند: Causeهای اتمیک، Effectهای مشاهدهپذیر، Constraintهای صادقانه و رابطههای قابل Verify. سپس باید روش استخراج Test و Coverage روشن—اغلب جدول تصمیم feasible—انتخاب شود. در مثال بازپرداخت، پنج Cause و یک Constraint به سه Effect انحصاری و شش Rule خوانا تبدیل شدند، اما Boundary زمان، State، Retry و Security همچنان به تکنیکهای مکمل نیاز دارند. CEG تضمین همه باگها نیست؛ ابزاری برای مدلسازی بهتر Rule، کشف Gap و ساخت تستهایی است که دقیقاً میدانیم چه منطقی را پوشش میدهند.

