وقتی صحبت از تست نرم افزار میشود، معمولاً با سه سؤال متفاوت روبهرو هستیم:
- چه چیزی را تست کنیم؟ → Test Type
- در چه سطحی تست کنیم؟ → Test Level
- چطور تستها را طراحی کنیم؟ → Test Technique
تفاوت سؤال سوم با دو مورد دیگر بسیار مهم است.
فرض کنید در یک فروشگاه اینترنتی، نیازمندی زیر را داریم:
کاربر میتواند برای خرید خود مبلغی بین ۱۰۰ هزار تا ۵ میلیون تومان وارد کند.
یک تستر میتواند دهها مقدار مختلف وارد کند؛ اما آیا لازم است همه اعداد بین ۱۰۰ هزار تا ۵ میلیون را تست کنیم؟
قطعاً نه.
اینجاست که Test Technique یا تکنیک تست اهمیت پیدا میکند.
تکنیک تست به تستر کمک میکند بهجای انتخاب تصادفی تست کیسها، از یک روش منطقی و سیستماتیک برای شناسایی ورودیها، شرایط و سناریوهای مهم استفاده کند.
برای مثال، با استفاده از Boundary Value Analysis میتوانیم بهجای تست تعداد زیادی مقدار، روی نقاط مرزی تمرکز کنیم:
- ۹۹,۹۹۹
- ۱۰۰,۰۰۰
- ۱۰۰,۰۰۱
- ۴,۹۹۹,۹۹۹
- ۵,۰۰۰,۰۰۰
- ۵,۰۰۰,۰۰۱
به این ترتیب، تکنیک تست میتواند کمک کند با تعداد مناسبی Test Case، تمرکز بیشتری روی شرایط مهم و مستعد Defect داشته باشیم.
Test Technique دقیقاً چه کاری انجام میدهد؟
به زبان ساده، Test Technique یک روش برای طراحی تست است.
تستر با توجه به نوع اطلاعاتی که در اختیار دارد، میتواند از تکنیکهای مختلفی استفاده کند.
این اطلاعات ممکن است شامل موارد زیر باشد:
- Requirements
- Business Rules
- Use Cases
- وضعیتها و Stateهای سیستم
- ساختار داخلی Code
- تجربه قبلی تستر
- رفتارهای شناختهشدهای که معمولاً باعث ایجاد Defect میشوند
برای مثال، اگر Requirement شامل یک محدوده عددی باشد، Equivalence Partitioning و Boundary Value Analysis میتوانند انتخابهای مناسبی باشند.
اگر رفتار سیستم به Stateهای مختلف وابسته باشد، State Transition Testing میتواند مفید باشد.
اگر چند Business Rule با یکدیگر ترکیب شده باشند، Decision Table Testing میتواند به شناسایی Combinationهای مهم کمک کند.
و اگر تستر بر اساس تجربه خود نقاطی را که احتمال Defect در آنها بیشتر است شناسایی کند، میتوان از Error Guessing استفاده کرد.
بنابراین یک Test Technique صرفاً مشخص نمیکند «چه چیزی را تست کنیم»، بلکه کمک میکند Test Conditionها و Test Caseهای مناسب را به شکل هدفمند طراحی کنیم.
چرا استفاده از تکنیکهای تست مهم است؟
بدون استفاده از تکنیکهای مناسب، طراحی تست میتواند به دو مشکل متضاد منجر شود:
۱.تست بیش از حد
تستر تلاش میکند تعداد بسیار زیادی ورودی و سناریو را بررسی کند و در نتیجه زمان و منابع زیادی مصرف میشود.
۲.تست ناکافی
تستر فقط چند مقدار یا سناریوی ساده را بررسی میکند و بسیاری از حالتهای مهم، مخصوصاً Boundaryها، Combinationها و شرایط غیرعادی، از قلم میافتند.
Test Techniques تلاش میکنند بین این دو حالت تعادل ایجاد کنند.
هدف این نیست که بیشترین تعداد Test Case را تولید کنیم؛ هدف این است که با Test Caseهای مناسب، پوشش مؤثر و احتمال بیشتری برای کشف Defectهای مهم داشته باشیم.
یک Test Technique بهتنهایی کافی نیست
در پروژههای واقعی معمولاً قرار نیست برای هر Feature فقط از یک تکنیک استفاده کنیم.
ممکن است برای یک Feature، چند تکنیک در کنار یکدیگر استفاده شوند.
مثلاً در یک سیستم پرداخت میتوانیم:
- با Equivalence Partitioning ورودیهای معتبر و نامعتبر را مشخص کنیم.
- با Boundary Value Analysis مقادیر مرزی را بررسی کنیم.
- با Decision Table Testing ترکیب شرایط مختلف پرداخت را بررسی کنیم.
- با Error Guessing سراغ خطاهایی برویم که بر اساس تجربه احتمال وقوع بیشتری دارند.
- و در صورت نیاز با Exploratory Testing رفتارهایی را بررسی کنیم که در Requirements بهطور کامل پیشبینی نشدهاند.
بنابراین Test Techniques را بهتر است بهعنوان ابزارهای فکری برای طراحی بهتر تست ببینیم، نه مجموعهای از قوانین خشک که همیشه باید به یک شکل اجرا شوند.
Test Technique، Test Type و Test Level چه تفاوتی دارند؟
در Software Testing اصطلاحات زیادی برای توصیف تستها استفاده میشود و گاهی این اصطلاحات بهجای یکدیگر به کار میروند.
اما Test Level، Test Type و Test Technique سه مفهوم متفاوت هستند.
برای درک بهتر، میتوانیم آنها را با سه سؤال ساده از هم تفکیک کنیم:
| مفهوم | سؤال اصلی | مثال |
|---|---|---|
| Test Level سطح تست | در چه سطحی از سیستم تست میکنیم؟ | Component, Integration, System, Acceptance |
| Test Type انواع تست | چه جنبهای از سیستم را بررسی میکنیم؟ | Functional, Performance, Usability |
| Test Technique تکنیک تست | تستها را چگونه طراحی میکنیم؟ | Boundary Value Analysis, Decision Table |
بنابراین:
Test Level درباره سطح تست، Test Type درباره جنبه یا هدف تست و Test Technique درباره روش طراحی تست است.
یک مثال واقعی
فرض کنید در یک فروشگاه اینترنتی، قابلیت ورود به حساب کاربری (Login) را داریم.
میتوانیم این قابلیت را در سطح System Testing بررسی کنیم.
در اینجا Test Level مشخص شده است:
System Testing
حالا تصمیم میگیریم رفتار صحیح Login را بررسی کنیم؛ مثلاً:
- ورود با اطلاعات معتبر
- ورود با Password اشتباه
- ورود با Username نامعتبر
- قفل شدن حساب پس از چند تلاش ناموفق
در اینجا نوع تست یا Test Type میتواند Functional Testing باشد.
اما سؤال بعدی این است:
Test Caseهای مربوط به این قابلیت را چگونه طراحی کنیم؟
اینجاست که Test Technique وارد میشود.
مثلاً برای یک Password که قوانین مشخصی درباره طول آن دارد، میتوانیم از Equivalence Partitioning یا Boundary Value Analysis استفاده کنیم.
بنابراین یک تست میتواند همزمان ویژگیهای مختلفی داشته باشد:
Login Feature
│
├── Test Level
│ └── System Testing
│
├── Test Type
│ └── Functional Testing
│
└── Test Technique
└── Boundary Value Analysis
این سه مفهوم رقیب یکدیگر نیستند؛ بلکه ابعاد متفاوتی از یک فعالیت تست را توصیف میکنند.
آیا Test Technique همان Test Type است؟
خیر.
برای مثال:
- Functional Testing یک Test Type است.
- Boundary Value Analysis یک Test Technique است.
ممکن است در یک Functional Test از Boundary Value Analysis استفاده کنیم.
همچنین ممکن است در تست یک API، که از نظر Test Type میتواند Functional باشد، برای طراحی Test Caseها از Equivalence Partitioning استفاده کنیم.
پس نمیتوان گفت:
Boundary Value Analysis یک نوع تست است.
عبارت دقیقتر این است:
Boundary Value Analysis یک Test Technique برای طراحی تست است.
آیا Test Technique همان Test Level است؟
باز هم خیر.
مثلاً Integration Testing یک Test Level است.
اما در Integration Testing نیز میتوان از تکنیکهای مختلفی برای طراحی تست استفاده کرد.
برای مثال، اگر یک Integration بین Order Service و Payment Service داشته باشیم، میتوانیم Business Ruleهای مربوط به پرداخت را با Decision Table Testing بررسی کنیم.
Test Level
Integration Testing
+
Test Type
Functional Testing
+
Test Technique
Decision Table Testing
این ترکیب کاملاً ممکن است.
یک مدل ذهنی ساده
برای اینکه این سه مفهوم را همیشه از هم تشخیص دهید، این مدل را به خاطر بسپارید:
┌─────────────────────────────────────┐
│ Test Level │
│ Where are we testing? │
│ │
│ Component → Integration → System │
│ → Acceptance│
└─────────────────────────────────────┘
│
↓
┌─────────────────────────────────────┐
│ Test Type │
│ What are we testing? │
│ │
│ Functional / Performance / Usability│
│ Security / Compatibility / ... │
└─────────────────────────────────────┘
│
↓
┌─────────────────────────────────────┐
│ Test Technique │
│ How do we design tests? │
│ │
│ Equivalence Partitioning │
│ Boundary Value Analysis │
│ Decision Table / State Transition │
│ Error Guessing / Exploratory ... │
└─────────────────────────────────────┘
البته این نمودار به معنی آن نیست که این سه مفهوم همیشه بهصورت یک زنجیره خطی اجرا میشوند؛ هدف آن فقط نشان دادن تفاوت نقش آنها است.
Test Techniques در ISTQB چگونه دستهبندی میشوند؟
حالا که تفاوت Test Level، Test Type و Test Technique را مشخص کردیم، میتوانیم سراغ طبقهبندی تکنیکهای تست برویم.
در چارچوب ISTQB، تکنیکهای تست را میتوان بر اساس منبع اطلاعاتی که برای طراحی تست استفاده میکنند، در سه گروه اصلی بررسی کرد:
- Black-box Test Techniques
- White-box Test Techniques
- Experience-based Test Techniques
تفاوت اصلی این سه گروه در این است که تستر برای طراحی تست، به چه نوع اطلاعاتی تکیه میکند.
۱. Black-box Test Techniques
در Black-box Testing تستر بیشتر بر رفتار قابل مشاهده سیستم و اطلاعاتی مانند Requirements، Specifications، Business Rules و Use Caseها تمرکز میکند.
در این رویکرد، برای طراحی Test Case لازم نیست حتماً بدانیم Code داخلی سیستم چگونه نوشته شده است.
تکنیکهای مهم این گروه عبارتاند از:
- Equivalence Partitioning
- Boundary Value Analysis
- Decision Table Testing
- State Transition Testing
- Use Case Testing
برای مثال، اگر Requirement بگوید:
سن کاربر برای ثبتنام باید بین ۱۸ تا ۶۰ سال باشد.
تستر میتواند بدون بررسی Code داخلی، با استفاده از Equivalence Partitioning ورودیها را به گروههای مختلف تقسیم کند یا با Boundary Value Analysis روی مقادیر مرزی تمرکز کند.
بنابراین تمرکز اصلی این تکنیکها روی این سؤال است:
سیستم در برابر ورودیها و شرایط مختلف چه رفتاری باید داشته باشد؟
۲. White-box Test Techniques
در White-box Testing تستر از اطلاعات مربوط به ساختار داخلی سیستم، منطق برنامه یا Code برای طراحی و ارزیابی تست استفاده میکند.
در اینجا دیگر فقط رفتار قابل مشاهده سیستم اهمیت ندارد؛ بلکه ساختار داخلی و مسیرهای اجرای برنامه نیز مورد توجه قرار میگیرند.
از تکنیکهای مهم این گروه میتوان به موارد زیر اشاره کرد:
- Statement Testing
- Branch Testing
- Statement Coverage
- Branch Coverage
برای مثال، فرض کنید بخشی از Code شامل یک شرط باشد:
if payment_successful:
confirm_order()
else:
show_error()
تستر میتواند بررسی کند که آیا تستها هر دو مسیر را اجرا کردهاند یا خیر:
payment_successful = True
↓
confirm_order()
payment_successful = False
↓
show_error()
در اینجا دیگر صرفاً نمیپرسیم:
«آیا Login یا Payment درست کار میکند؟»
بلکه میپرسیم:
«آیا بخشهای مهمی از ساختار و منطق داخلی برنامه توسط تستها اجرا و بررسی شدهاند؟»
۳. Experience-based Test Techniques
در Experience-based Testing، تجربه، دانش و شهود تستر نقش مهمی در طراحی تست دارد.
تستر بر اساس تجربه پروژههای قبلی، شناخت رفتار کاربران، Defectهای قبلی و الگوهای رایج خطا، تصمیم میگیرد چه مواردی ارزش تست بیشتری دارند.
تکنیکهای مهم این گروه عبارتاند از:
- Error Guessing
- Exploratory Testing
- Checklist-based Testing
برای مثال، یک تستر باتجربه ممکن است هنگام تست فرم ثبتنام، علاوه بر سناریوهای مشخصشده در Requirements، مواردی مثل اینها را هم بررسی کند:
- ارسال فیلد خالی
- ورود Space در ابتدا یا انتهای مقدار
- وارد کردن کاراکترهای خاص
- وارد کردن مقدار بسیار طولانی
- ارسال چندباره فرم
- استفاده از داده تکراری
- قطع ارتباط هنگام ارسال اطلاعات
این انتخابها ممکن است مستقیماً از یک Requirement استخراج نشده باشند؛ بلکه حاصل تجربه و شناخت تستر از نقاط مستعد Defect باشند.
آیا این سه گروه کاملاً از هم جدا هستند؟
خیر.
در یک پروژه واقعی، معمولاً تستر از ترکیبی از این تکنیکها استفاده میکند.
برای مثال، هنگام تست یک قابلیت Password Reset ممکن است:
Black-box: با استفاده از Equivalence Partitioning و Boundary Value Analysis، ورودیهای معتبر و نامعتبر را بررسی کنیم.
White-box: در صورت دسترسی به Code، Branchهای مهم منطق Password Reset را بررسی کنیم.
Experience-based: با استفاده از Error Guessing، مواردی مانند Token منقضیشده، استفاده مجدد از Token، چند درخواست همزمان یا ورود دادههای غیرمنتظره را بررسی کنیم.
پس این سه گروه را نباید بهعنوان سه روش کاملاً رقیب در نظر گرفت.
در واقع، یک تستر حرفهای بسته به هدف تست، اطلاعات در دسترس، ریسک سیستم، زمان و شرایط پروژه میتواند از چند تکنیک مختلف در کنار یکدیگر استفاده کند.
خلاصه سه گروه
| گروه | منبع اصلی طراحی تست | نمونه تکنیکها |
|---|---|---|
| Black-box | Requirements و رفتار مورد انتظار | Equivalence Partitioning، Boundary Value Analysis، Decision Table |
| White-box | ساختار و منطق داخلی سیستم | Statement Testing، Branch Testing |
| Experience-based | تجربه و دانش تستر | Error Guessing، Exploratory Testing، Checklist-based |
تکنیکهای تست جعبه سیاه (Black-box Test Techniques)
در Black-box Testing تمرکز اصلی تستر روی رفتار قابل مشاهده سیستم و خروجی آن در برابر ورودیها و شرایط مختلف است.
تستر برای طراحی تست الزاماً نیازی به دانستن جزئیات Code یا ساختار داخلی سیستم ندارد. در عوض، میتواند از منابعی مانند موارد زیر استفاده کند:
- Requirements
- Business Rules
- Specifications
- User Stories
- Acceptance Criteria
- Use Cases
- رفتار مورد انتظار سیستم
به همین دلیل، Black-box Test Techniques در بسیاری از پروژههای Software Testing کاربرد گستردهای دارند.
مهمترین تکنیکهایی که در این گروه بررسی میکنیم عبارتاند از:
- Equivalence Partitioning
- Boundary Value Analysis
- Decision Table Testing
- State Transition Testing
- Use Case Testing
البته این تکنیکها فقط مجموعهای از روشهای جدا از هم نیستند. در یک پروژه واقعی ممکن است برای یک Feature از چند تکنیک بهصورت همزمان استفاده شود.
۱. Equivalence Partitioning چیست؟
Equivalence Partitioning (EP) یا تقسیمبندی همارزی تکنیکی است که در آن ورودیهای ممکن به گروههایی تقسیم میشوند که انتظار میرود سیستم در برابر اعضای هر گروه، رفتار مشابهی داشته باشد.
ایده اصلی ساده است:
اگر چند مقدار از دید رفتار سیستم معادل یکدیگر باشند، لازم نیست همه آنها را تست کنیم؛ میتوانیم نمایندهای از هر گروه انتخاب کنیم.
فرض کنید یک سیستم فقط به کاربران ۱۸ تا ۶۰ ساله اجازه ثبتنام میدهد.
میتوانیم ورودیها را به سه Partition تقسیم کنیم:
| Partition | محدوده | وضعیت |
|---|---|---|
| Partition 1 | کمتر از ۱۸ | Invalid |
| Partition 2 | ۱۸ تا ۶۰ | Valid |
| Partition 3 | بیشتر از ۶۰ | Invalid |
حالا به جای اینکه صدها مقدار مختلف را تست کنیم، میتوانیم از Representative Value استفاده کنیم:
- ۱۵ → نماینده گروه Invalid
- ۳۰ → نماینده گروه Valid
- ۷۰ → نماینده گروه Invalid
در این حالت با فقط سه Test Case میتوانیم هر سه Partition اصلی را پوشش دهیم.
چرا Equivalence Partitioning مفید است؟
اگر بدون استفاده از تکنیکهای تست بخواهیم تمام مقادیر ممکن را بررسی کنیم، تعداد Test Caseها میتواند بسیار زیاد شود.
برای مثال، اگر یک فیلد عددی بتواند مقادیر زیادی دریافت کند، تست کردن تکتک آنها معمولاً نه عملی است و نه لزوماً مفید.
Equivalence Partitioning کمک میکند:
- تعداد Test Caseها کاهش پیدا کند.
- ورودیها به شکل سیستماتیک انتخاب شوند.
- از تستهای تکراری جلوگیری شود.
- احتمال فراموش شدن گروههای مهم کاهش پیدا کند.
اما یک نکته مهم وجود دارد:
Equivalence Partitioning به معنی انتخاب تصادفی چند مقدار نیست.
تستر ابتدا باید منطق سیستم را بفهمد و Partitionهایی را پیدا کند که انتظار میرود رفتار متفاوتی داشته باشند.
یک مثال کاربردیتر
فرض کنید یک فروشگاه اینترنتی برای مبلغ سفارش، قوانین زیر را دارد:
- کمتر از ۱۰۰ هزار تومان → نامعتبر
- از ۱۰۰ هزار تا ۵ میلیون تومان → معتبر
- بیشتر از ۵ میلیون تومان → نامعتبر
Partitionها:
کمتر از 100,000
↓
Invalid
100,000 تا 5,000,000
↓
Valid
بیشتر از 5,000,000
↓
Invalid
برای طراحی Test Case میتوانیم مثلاً انتخاب کنیم:
| Test Case | Input | Expected Result |
|---|---|---|
| TC-01 | 50,000 | Invalid |
| TC-02 | 500,000 | Valid |
| TC-03 | 8,000,000 | Invalid |
این تستها تمام Partitionهای شناساییشده را نمایندگی میکنند.
Equivalence Partitioning چه چیزی را به ما نمیگوید؟
یک اشتباه رایج این است که تصور کنیم اگر Partitionها را پوشش دادیم، دیگر نیازی به بررسی نقاط خاص نداریم.
اما ممکن است Defect دقیقاً در مرز بین دو Partition اتفاق بیفتد.
در مثال بالا، مقادیر زیر اهمیت ویژهای دارند:
- ۹۹,۹۹۹
- ۱۰۰,۰۰۰
- ۱۰۰,۰۰۱
- ۴,۹۹۹,۹۹۹
- ۵,۰۰۰,۰۰۰
- ۵,۰۰۰,۰۰۱
اینجاست که Boundary Value Analysis اهمیت پیدا میکند.
بنابراین در بسیاری از سناریوها، Equivalence Partitioning و Boundary Value Analysis در کنار یکدیگر استفاده میشوند.
۲. Boundary Value Analysis چیست؟
Boundary Value Analysis (BVA) یا تحلیل مقادیر مرزی تکنیکی است که روی مرزهای بین Partitionها تمرکز میکند.
دلیل اهمیت Boundaryها این است که Defectها میتوانند در نقاطی رخ دهند که رفتار سیستم از یک وضعیت به وضعیت دیگر تغییر میکند.
برای همان مثال:
مبلغ سفارش باید بین ۱۰۰,۰۰۰ و ۵,۰۰۰,۰۰۰ تومان باشد.
به جای تست مقادیر تصادفی، روی Boundaryها تمرکز میکنیم:
99,999 ← زیر مرز 100,000 ← مرز پایین 100,001 ← بالای مرز ... 4,999,999 ← زیر مرز 5,000,000 ← مرز بالا 5,000,001 ← بالای مرز
به این ترتیب، Test Caseها دقیقاً اطراف نقاطی قرار میگیرند که برای بررسی رفتار Boundary اهمیت دارند.
تفاوت Equivalence Partitioning و Boundary Value Analysis
این دو تکنیک بسیار به یکدیگر مرتبط هستند، اما یکسان نیستند.
Equivalence Partitioning میپرسد:
ورودیها را چگونه به گروههای رفتاری تقسیم کنیم؟
Boundary Value Analysis میپرسد:
مرزهای این گروهها کجا هستند و چه مقادیری در اطراف این مرزها باید تست شوند؟
Equivalence Partitioning
↓
Invalid | Valid | Invalid
↓
Boundary Value Analysis
↓
99,999 | 100,000 | 100,001
بنابراین میتوان این دو تکنیک را در کنار یکدیگر به کار برد تا هم Partitionها و هم Boundaryهای مهم پوشش داده شوند.
Decision Table Testing چیست؟
Decision Table Testing یا تست جدول تصمیم یکی از تکنیکهای مهم Black-box Testing است که زمانی کاربرد ویژهای پیدا میکند که رفتار سیستم به ترکیبی از چند شرط (Condition) و قانون کسبوکار (Business Rule) وابسته باشد.
در چنین شرایطی، تست کردن هر شرط بهصورت جداگانه ممکن است کافی نباشد؛ زیرا گاهی ترکیب چند شرط است که رفتار نهایی سیستم را تعیین میکند.
برای مثال، فرض کنید یک فروشگاه اینترنتی چنین قانونی دارد:
اگر کاربر عضو VIP باشد و مبلغ سفارش حداقل ۱ میلیون تومان باشد، ۲۰٪ تخفیف دریافت میکند.
در اینجا رفتار سیستم فقط به یک شرط وابسته نیست:
- آیا کاربر VIP است؟
- آیا مبلغ سفارش به حد مشخص رسیده است؟
اگر هر دو شرط برقرار باشند، تخفیف اعمال میشود.
حالا اگر چند شرط و چند Rule داشته باشیم، تعداد ترکیبهای ممکن افزایش پیدا میکند و احتمال فراموش شدن برخی حالتها بیشتر میشود.
Decision Table دقیقاً برای مدیریت چنین شرایطی مفید است.
ساختار Decision Table
یک Decision Table معمولاً از چهار بخش اصلی تشکیل میشود:
- Conditions → شرایط
- Condition Values → مقادیر یا وضعیت هر شرط
- Actions → اقدام یا نتیجه مورد انتظار
- Rules → ترکیب مشخصی از شرایط که یک نتیجه را تعیین میکند
برای مثال، فرض کنید شرایط زیر را داریم:
- کاربر VIP است یا خیر.
- مبلغ سفارش حداقل ۱ میلیون تومان است یا خیر.
جدول تصمیم میتواند به شکل زیر باشد:
| Condition / Rule | Rule 1 | Rule 2 | Rule 3 | Rule 4 |
|---|---|---|---|---|
| کاربر VIP است؟ | Yes | Yes | No | No |
| مبلغ ≥ ۱ میلیون؟ | Yes | No | Yes | No |
| Action: اعمال تخفیف | Yes | No | No | No |
حالا هر ستون یک Rule یا ترکیب مشخص از شرایط را نشان میدهد.
در نتیجه میتوان برای هر Rule، حداقل یک Test Case طراحی کرد.
چرا Decision Table اهمیت دارد؟
فرض کنید تستر فقط این دو حالت را بررسی کند:
- کاربر VIP + سفارش بالای ۱ میلیون
- کاربر غیر VIP + سفارش کمتر از ۱ میلیون
ممکن است دو حالت دیگر را فراموش کند:
- کاربر VIP + سفارش کمتر از ۱ میلیون
- کاربر غیر VIP + سفارش بالای ۱ میلیون
در یک سیستم واقعی، همین حالتهای به ظاهر ساده میتوانند باعث ایجاد Defect شوند.
Decision Table کمک میکند ترکیبهای مختلف شرایط را بهصورت سیستماتیک ببینیم و Test Caseهای موردنیاز را از روی آن استخراج کنیم.
Decision Table فقط برای دو شرط نیست
قدرت واقعی Decision Table زمانی بیشتر مشخص میشود که تعداد Conditionها افزایش پیدا کند.
فرض کنید تخفیف به این سه عامل وابسته باشد:
- کاربر VIP است؟
- مبلغ سفارش حداقل ۱ میلیون تومان است؟
- کد تخفیف معتبر دارد؟
هر Condition میتواند دو وضعیت داشته باشد:
3 Conditions
↓
2 × 2 × 2
↓
8 Combinations
یعنی در حالت ساده، ۸ ترکیب ممکن خواهیم داشت.
اگر تعداد Conditionها بیشتر شود، تعداد Combinationها نیز بهسرعت افزایش پیدا میکند.
اینجاست که Decision Table به تستر کمک میکند تا فضای حالتها را به شکل ساختاریافته بررسی کند.
آیا همیشه باید تمام Combinationها را تست کنیم؟
لزوماً نه.
در یک پروژه واقعی ممکن است برخی Combinationها:
- از نظر Business Rule غیرممکن باشند.
- رفتار یکسانی داشته باشند.
- ارزش تست بسیار کمی داشته باشند.
- یا به دلیل محدودیت زمان و ریسک، در اولویت پایینتری قرار بگیرند.
بنابراین Decision Table ابتدا فضای تصمیمها و Combinationها را آشکار میکند و سپس تیم تست میتواند بر اساس Risk، اهمیت Business، محدودیت زمانی و امکانپذیری حالتها درباره Test Coverage تصمیم بگیرد.
این نکته مهم است؛ چون هدف Decision Table صرفاً تولید تعداد زیادی Test Case نیست.
هدف اصلی، جلوگیری از نادیده گرفتن Combinationهای مهم در Business Rules است.
Decision Table در چه سیستمهایی کاربرد زیادی دارد؟
این تکنیک در Featureهایی که Business Logic پیچیده دارند بسیار مفید است، مانند:
- سیستمهای پرداخت
- سیستمهای تخفیف
- احراز هویت و Authorization
- محاسبه قیمت
- سیستمهای بیمه
- سیستمهای بانکی
- قوانین ارسال سفارش
- محاسبه مالیات
- سیستمهای اعتبارسنجی
- Pricing و Subscription
هر جا که نتیجه سیستم به ترکیب چند شرط وابسته باشد، Decision Table میتواند یکی از گزینههای مناسب برای طراحی تست باشد.
State Transition Testing چیست؟
State Transition Testing یا تست انتقال وضعیت یکی از تکنیکهای مهم Black-box Testing است که زمانی کاربرد دارد که رفتار سیستم به State فعلی (وضعیت فعلی) و رویدادهایی که باعث تغییر آن وضعیت میشوند، وابسته باشد.
در بسیاری از سیستمها، یک ورودی مشخص همیشه نتیجه یکسانی ندارد؛ نتیجه میتواند به وضعیت فعلی سیستم یا کاربر بستگی داشته باشد.
برای مثال، فرض کنید یک حساب کاربری میتواند در وضعیتهای مختلفی قرار داشته باشد:
Active │ │ چند ورود ناموفق ↓ Locked │ │ باز شدن توسط Administrator ↓ Active
اگر کاربر در وضعیت Active باشد، ورود با Password صحیح میتواند موفق باشد.
اما اگر همان کاربر در وضعیت Locked باشد، حتی Password صحیح نیز ممکن است اجازه ورود ایجاد نکند.
بنابراین برای طراحی تست، فقط Input مهم نیست؛ بلکه باید بدانیم سیستم در چه Stateای قرار دارد.
State، Event و Transition چه هستند؟
برای درک State Transition Testing، سه مفهوم اصلی را باید بشناسیم:
State
وضعیت فعلی سیستم یا یک Entity در یک لحظه مشخص.
مثلاً:
- Active
- Locked
- Pending
- Paid
- Shipped
- Cancelled
Event
رویدادی که میتواند باعث تغییر وضعیت شود.
- ورود ناموفق
- پرداخت موفق
- لغو سفارش
- تأیید Administrator
Transition
تغییر سیستم از یک State به State دیگر در نتیجه یک Event.
Pending │ │ Payment Successful ↓ Paid
در این مثال:
- Pending = State اولیه
- Payment Successful = Event
- Paid = State جدید
- تغییر Pending → Paid = Transition
یک مثال ساده: وضعیت سفارش
فرض کنید وضعیت یک Order در فروشگاه اینترنتی میتواند به شکل زیر تغییر کند:
Payment
Successful
↓
Pending → Paid → Shipped → Delivered
│ │
│ └── Payment Failed
↓
Cancelled
البته در یک سیستم واقعی ممکن است Stateها و Transitionهای بسیار بیشتری وجود داشته باشند.
حالا تستر فقط نباید Stateهای مختلف را ببیند؛ بلکه باید بررسی کند آیا Transitionهای مجاز و غیرمجاز نیز درست مدیریت میشوند یا خیر.
تست Transitionهای مجاز
فرض کنید Order در وضعیت Paid قرار دارد.
یک Transition مجاز میتواند این باشد:
Paid ↓ Shipped
تستر باید بررسی کند که با Event مناسب، سیستم واقعاً به State جدید منتقل میشود.
مثلاً:
وقتی پرداخت موفق شده و سفارش آماده ارسال است، وضعیت Order باید از Paid به Shipped تغییر کند.
تست Transitionهای غیرمجاز
بخش مهمتر ماجرا بررسی Transitionهایی است که نباید اتفاق بیفتند.
Cancelled
↓
Paid
اگر یک Order قبلاً Cancel شده باشد، آیا سیستم اجازه میدهد دوباره به Paid برگردد؟
در بسیاری از سیستمها پاسخ باید خیر باشد.
بنابراین تستر میتواند چنین سناریویی طراحی کند:
یک Order را Cancel کن و سپس تلاش کن پرداخت آن را انجام دهی.
Expected Result:
سیستم نباید اجازه Transition غیرمجاز را بدهد و وضعیت Order نباید به Paid تغییر کند.
State Transition Diagram
برای سیستمهایی که Stateهای زیادی دارند، استفاده از State Transition Diagram میتواند به درک بهتر رفتار سیستم کمک کند.
Login Failed
│
↓
Attempt 1
│
Login Failed
↓
Attempt 2
│
Login Failed
↓
Locked
│
Admin Unlock
↓
Active
در چنین سیستمی میتوان Test Caseهایی طراحی کرد که نهتنها Stateهای مختلف، بلکه مسیرهای انتقال بین آنها را بررسی کنند.
State Transition Testing در چه سیستمهایی کاربرد دارد؟
این تکنیک مخصوصاً برای سیستمهایی مناسب است که رفتارشان به وضعیت فعلی وابسته است، مانند:
- Order Management
- Payment Systems
- User Account Management
- Authentication
- Subscription Systems
- Workflow Systems
- Booking Systems
- Approval Processes
- Ticketing Systems
- سیستمهای بانکی و مالی
برای مثال، در یک سیستم Subscription ممکن است وضعیتها چنین باشند:
Trial ↓ Active ↓ Expired ↓ Renewed
هر Transition میتواند شرایط و قوانین خاص خود را داشته باشد و بنابراین میتواند موضوع تست قرار گیرد.
State Transition Testing چه چیزی را بهتر از تست معمولی نشان میدهد؟
فرض کنید فقط بگوییم:
«کاربر نمیتواند با Account قفلشده وارد سیستم شود.»
این یک Test Case مشخص است.
اما State Transition Testing سؤال گستردهتری مطرح میکند:
Account چگونه به وضعیت Locked میرسد، از Locked چگونه خارج میشود و در هر State چه Eventهایی مجاز یا غیرمجاز هستند؟
در نتیجه، این تکنیک کمک میکند رفتار سیستم در طول زمان و در مسیرهای مختلف بررسی شود، نه فقط رفتار آن در یک لحظه مشخص.
State Transition Testing و ترکیب با سایر تکنیکها
این تکنیک نیز لزوماً بهتنهایی استفاده نمیشود.
برای مثال، در یک سیستم Login میتوانیم:
- با State Transition Testing تغییر وضعیت Account را بررسی کنیم.
- با Equivalence Partitioning انواع Username و Password را دستهبندی کنیم.
- با Boundary Value Analysis تعداد تلاشهای ناموفق مجاز را بررسی کنیم.
- با Error Guessing سناریوهای غیرعادی مانند Refresh، چند Login همزمان یا Sessionهای قدیمی را بررسی کنیم.
این ترکیب نشان میدهد که در پروژه واقعی، Test Techniques میتوانند مکمل یکدیگر باشند.
Use Case Testing چیست؟
Use Case Testing یکی از تکنیکهای Black-box Testing است که برای طراحی Test Caseها بر اساس نحوه تعامل کاربر یا Actor با سیستم استفاده میشود.
در این تکنیک، بهجای اینکه فقط ورودیها و خروجیهای منفرد سیستم را بررسی کنیم، یک جریان کامل از تعامل با سیستم را در نظر میگیریم.
برای مثال، در یک فروشگاه اینترنتی، Use Case زیر را در نظر بگیرید:
خرید یک محصول توسط کاربر
یک جریان معمولی میتواند شامل مراحل زیر باشد:
Login ↓ Search Product ↓ Add to Cart ↓ Checkout ↓ Enter Address ↓ Select Payment Method ↓ Complete Payment ↓ Order Confirmation
این جریان یک Business Scenario کامل را شکل میدهد و میتوان از آن برای طراحی Test Case استفاده کرد.
Use Case چه اطلاعاتی در اختیار تستر قرار میدهد؟
یک Use Case معمولاً شامل اطلاعاتی مانند موارد زیر است:
- Actor
- هدف کاربر
- Preconditions
- Main Flow
- Alternative Flow
- Exception Flow
- Postconditions
این اطلاعات میتوانند منابع ارزشمندی برای طراحی تست باشند.
برای مثال:
Use Case: خرید محصول
Actor: Customer
Precondition: کاربر وارد حساب خود شده است.
Main Flow:
- کاربر محصول را انتخاب میکند.
- محصول را به Cart اضافه میکند.
- وارد Checkout میشود.
- روش پرداخت را انتخاب میکند.
- پرداخت را انجام میدهد.
- سفارش ثبت میشود.
تستر میتواند این جریان را به یک یا چند Test Scenario و Test Case تبدیل کند.
تست Main Flow
اولین چیزی که معمولاً بررسی میشود، Main Success Scenario یا Happy Path است.
Login ↓ Select Product ↓ Add to Cart ↓ Checkout ↓ Successful Payment ↓ Order Created
Expected Result:
سفارش با موفقیت ایجاد شود و کاربر پیام تأیید سفارش را دریافت کند.
این تست بررسی میکند که مسیر اصلی کسبوکار بدون مشکل کار میکند.
اما تستر نباید به همین مسیر اکتفا کند.
تست Alternative Flow
در سیستم واقعی همیشه همه کاربران مسیر اصلی را طی نمیکنند.
برای مثال، کاربر ممکن است در Checkout روش پرداخت متفاوتی انتخاب کند یا محصول موجود نباشد.
بنابراین باید Alternative Flowها نیز بررسی شوند.
Checkout │ ├── Credit Card │ ├── Bank Transfer │ └── Wallet
هر مسیر میتواند شرایط و Expected Result متفاوتی داشته باشد.
تست Exception Flow
یکی از نقاط قوت Use Case Testing توجه به Exception Flow است.
Checkout ↓ Payment │ ├── Success → Order Created │ └── Failure → Payment Failed
در حالت Payment Failure باید بررسی کنیم:
- آیا Order ایجاد میشود؟
- آیا مبلغ دوباره از حساب کاربر کم میشود؟
- آیا Cart همچنان حفظ میشود؟
- آیا پیام مناسب به کاربر نمایش داده میشود؟
- آیا کاربر میتواند دوباره پرداخت را انجام دهد؟
این سناریوها ممکن است در Main Flow دیده نشوند، اما از نظر Business بسیار مهم باشند.
یک مثال کاملتر
فرض کنید Use Case ما Password Recovery باشد.
Main Flow:
Enter Email
↓
Request Reset Link
↓
Receive Email
↓
Open Link
↓
Set New Password
↓
Password Changed
حالا تستر میتواند Flowهای مختلف را بررسی کند.
Alternative / Exception Flows:
Invalid Email
↓
Show Error
Expired Reset Link
↓
Reject Request
Already Used Link
↓
Reject Request
Weak Password
↓
Show Validation Error
در اینجا Use Case Testing کمک میکند تستر فقط Happy Path را بررسی نکند و مسیرهای جایگزین و خطا را نیز از دل جریان کسبوکار استخراج کند.
Use Case Testing با End-to-End Testing یکی نیست
این دو مفهوم ممکن است به دلیل شباهت زیاد با یکدیگر اشتباه گرفته شوند.
Use Case Testing یک Test Technique برای طراحی تست بر اساس تعاملات و جریانهای Use Case است.
اما End-to-End Testing رویکردی برای بررسی یک جریان کامل در سیستم یا بین اجزای مختلف آن است.
بنابراین ممکن است یک E2E Test بر اساس یک Use Case طراحی شده باشد، اما این دو اصطلاح مترادف نیستند.
برای مثال:
Use Case: خرید محصول
میتواند مبنای طراحی یک E2E Test قرار بگیرد:
Login ↓ Search ↓ Add to Cart ↓ Checkout ↓ Payment ↓ Order Confirmation
اما Use Case Testing به خودِ روش استخراج و طراحی تست از Use Case اشاره دارد.
Use Case Testing در چه سیستمهایی مفید است؟
این تکنیک در سیستمهایی که جریانهای کسبوکاری مشخص و قابل تعریف دارند، کاربرد زیادی دارد؛ از جمله:
- فروشگاههای اینترنتی
- سیستمهای بانکی
- سامانههای رزرو
- سیستمهای بیمه
- سامانههای ثبت سفارش
- سیستمهای احراز هویت
- سیستمهای مدیریت Workflow
- سیستمهای SaaS
- اپلیکیشنهای مبتنی بر User Journey
هرجا بتوان تعامل Actor → System → Result را به شکل یک جریان تعریف کرد، Use Case Testing میتواند به طراحی تست کمک کند.
نکته مهم درباره Use Case Testing
Use Case Testing فقط به معنی «تست کردن مسیر اصلی Use Case» نیست.
یک تستر خوب باید علاوه بر Main Flow، به موارد زیر نیز توجه کند:
Main Flow + Alternative Flow + Exception Flow
زیرا بسیاری از Defectهای مهم دقیقاً در مسیرهایی اتفاق میافتند که کمتر استفاده میشوند یا در شرایط خاص فعال میشوند.
تکنیکهای تست جعبه سفید (White-box Test Techniques)
در Black-box Testing، برای طراحی تست بیشتر بر Requirements، Business Rules، Use Caseها و رفتار مورد انتظار سیستم تکیه داریم.
اما در White-box Testing، تستر یا توسعهدهنده میتواند از اطلاعات مربوط به ساختار داخلی نرمافزار و منطق اجرای Code نیز برای طراحی یا ارزیابی تست استفاده کند.
بنابراین سؤال اصلی تا حدی تغییر میکند:
آیا بخشهای مهم منطق و ساختار داخلی برنامه توسط تستها اجرا و بررسی شدهاند؟
برای مثال، فرض کنید کد زیر را داریم:
if user.is_active:
allow_login()
else:
reject_login()
در Black-box Testing ممکن است صرفاً بررسی کنیم:
کاربر فعال میتواند Login کند و کاربر غیرفعال نمیتواند.
اما در White-box Testing، ساختار Code نیز برای طراحی یا ارزیابی تست مورد توجه قرار میگیرد. برای مثال، میخواهیم مطمئن شویم هر دو مسیر اجرای شرط، یعنی حالت True و False، توسط تستها اجرا شدهاند.
White-box Test Techniques چه مواردی را بررسی میکنند؟
در این حوزه، دو مفهوم مهم عبارتاند از:
- Statement Testing
- Branch Testing
برای ارزیابی میزان پوشش نیز از معیارهایی مانند موارد زیر استفاده میشود:
- Statement Coverage
- Branch Coverage
این مفاهیم به یکدیگر مرتبط هستند، اما نباید آنها را کاملاً یکسان در نظر گرفت. Statement Testing و Branch Testing بر طراحی و اجرای تست بر اساس ساختار برنامه تمرکز دارند، در حالی که Statement Coverage و Branch Coverage معیارهایی برای اندازهگیری میزان پوشش ساختار Code هستند.
۱. Statement Testing
Statement Testing تکنیکی است که بررسی میکند آیا Statementهای قابل اجرای برنامه توسط Test Caseها اجرا شدهاند یا خیر.
برای مثال:
if user.is_active:
allow_login()
else:
reject_login()
log_login_attempt()
در این کد، سه Statement قابل اجرای مهم داریم:
allow_login()reject_login()log_login_attempt()
اگر Test Caseهای ما فقط مسیر کاربر فعال را اجرا کنند:
user.is_active = True
↓
allow_login()
↓
log_login_attempt()
در این حالت Statement مربوط به reject_login() هرگز اجرا نشده است.
بنابراین تستها تمام Statementهای قابل اجرای این بخش از Code را پوشش نمیدهند.
Statement Coverage چیست؟
Statement Coverage معیاری است که نشان میدهد چه درصدی از Statementهای قابل اجرای Code توسط Test Caseها اجرا شدهاند.
بهصورت ساده:
Statement Coverage =
Executed Statements
────────────────────── × 100
Total Executable Statements
مثلاً اگر از ۱۰ Statement قابل اجرا، تستها ۹ مورد را اجرا کنند:
Statement Coverage = 90%
اما یک نکته بسیار مهم وجود دارد:
Statement Coverage بالا به معنی نبود Defect نیست.
ممکن است تمام Statementها اجرا شوند، اما برخی ترکیبهای منطقی، Branchهای مهم یا سناریوهای کسبوکار همچنان بهدرستی تست نشده باشند.
۲. Branch Testing
Branch Testing روی شاخههای تصمیمگیری در Code تمرکز میکند.
مثلاً:
if payment_successful:
confirm_order()
else:
show_payment_error()
این تصمیم دو Branch دارد:
Condition
│
┌──────┴──────┐
True False
│ │
↓ ↓
confirm_order() show_payment_error()
برای اجرای هر دو Branch، حداقل باید دو وضعیت متفاوت تست شوند:
Test Case 1: Payment موفق → اجرای Branch مربوط به True
Test Case 2: Payment ناموفق → اجرای Branch مربوط به False
Branch Coverage چیست؟
Branch Coverage نشان میدهد چه درصدی از Branchهای قابل بررسی در ساختار تصمیمگیری Code توسط تستها اجرا شدهاند.
مثلاً اگر در یک بخش از Code چهار Branch قابل بررسی داشته باشیم و تستها سه مورد را اجرا کنند:
Branch Coverage = 75%
Branch Coverage میتواند اطلاعات بیشتری درباره پوشش مسیرهای تصمیمگیری برنامه ارائه دهد؛ با این حال، آن هم بهتنهایی تضمینکننده کیفیت کامل تست نیست.
تفاوت Statement Coverage و Branch Coverage
فرض کنید کد زیر را داریم:
if user.is_active:
allow_login()
log_login_attempt()
اگر فقط این تست را اجرا کنیم:
user.is_active = True
ممکن است Statementهای قابل اجرای موجود در مسیر True اجرا شوند، اما Branch مربوط به حالت False اصلاً اجرا نشده باشد.
به همین دلیل:
اجرای یک Statement لزوماً به معنی بررسی تمام Branchها و مسیرهای تصمیمگیری مرتبط با آن نیست.
| مفهوم | سؤال اصلی |
|---|---|
| Statement Testing | آیا Statementهای قابل اجرا اجرا شدهاند؟ |
| Branch Testing | آیا Branchهای تصمیمگیری مختلف اجرا شدهاند؟ |
| Statement Coverage | چه درصدی از Statementهای قابل اجرا اجرا شدهاند؟ |
| Branch Coverage | چه درصدی از Branchهای قابل بررسی اجرا شدهاند؟ |
آیا ۱۰۰٪ Coverage یعنی نرمافزار کاملاً تست شده است؟
خیر.
این یکی از مهمترین نکاتی است که باید درباره White-box Testing در نظر داشته باشیم.
فرض کنید تیم توسعه اعلام کند:
«Code Coverage ما ۱۰۰٪ است، پس نرمافزار کاملاً تست شده است.»
این نتیجهگیری درست نیست.
Coverage نشان میدهد چه بخشهایی از Code توسط تستها اجرا یا پوشش داده شدهاند؛ اما بهتنهایی نشان نمیدهد:
- Requirements بهدرستی پیادهسازی شدهاند یا خیر.
- Expected Result درست تعریف شده است یا خیر.
- Business Rules بهدرستی تست شدهاند یا خیر.
- کیفیت Test Caseها چقدر است.
- رفتار سیستم از دید کاربر صحیح است یا خیر.
- Performance یا Security مناسب است یا خیر.
- تمام سناریوهای مهم کسبوکار پوشش داده شدهاند یا خیر.
بنابراین Coverage باید بهعنوان یک معیار کمکی برای ارزیابی پوشش تست در نظر گرفته شود، نه یک تضمین برای کیفیت نرمافزار.
White-box و Black-box مکمل یکدیگر هستند
این دو رویکرد را نباید جایگزین یکدیگر در نظر گرفت.
برای مثال، در یک قابلیت Payment:
Black-box Techniques بررسی میکنند:
آیا سیستم طبق Requirements و Business Rules رفتار صحیحی دارد؟
White-box Techniques بررسی میکنند:
آیا مسیرها و منطق مهم داخلی Code توسط تستها اجرا شدهاند؟
به همین دلیل، در یک پروژه حرفهای ممکن است هر دو رویکرد در کنار یکدیگر استفاده شوند.
Requirements
│
├───────────────┐
↓ ↓
Black-box White-box
Testing Testing
│ │
↓ ↓
Behavior Code Structure
│ │
└───────┬───────┘
↓
Better Test Coverage
تکنیکهای تست مبتنی بر تجربه (Experience-based Test Techniques)
تا اینجا دو گروه مهم را بررسی کردیم:
- Black-box Test Techniques → تمرکز بر Requirements و رفتار مورد انتظار سیستم
- White-box Test Techniques → تمرکز بر ساختار و منطق داخلی Code
اما همیشه همه چیز را نمیتوان فقط از روی Requirement یا Code مشخص کرد.
گاهی یک تستر باتجربه با شناختی که از سیستم، کاربران، پروژه، Defectهای قبلی و الگوهای رایج خطا دارد، میتواند نقاطی را پیدا کند که ممکن است در مستندات بهوضوح مشخص نشده باشند.
اینجاست که Experience-based Test Techniques اهمیت پیدا میکنند.
سه تکنیک مهم این گروه عبارتاند از:
- Error Guessing
- Exploratory Testing
- Checklist-based Testing
۱. Error Guessing چیست؟
Error Guessing یا حدس خطا تکنیکی است که در آن تستر بر اساس تجربه و دانش خود، موقعیتهایی را پیشبینی میکند که احتمال دارد باعث ایجاد Defect شوند.
در این روش، تستر الزاماً یک الگوریتم مشخص برای تولید Test Case ندارد؛ بلکه از خودش میپرسد:
اگر قرار باشد این Feature خراب شود، احتمالاً کجا و چگونه خراب میشود؟
مثلاً هنگام تست یک فرم ثبتنام، یک تستر باتجربه ممکن است موارد زیر را بررسی کند:
- فیلدهای خالی
- مقدار بسیار طولانی
- Space در ابتدا یا انتهای Input
- کاراکترهای خاص
- داده تکراری
- ورود مقدار با Format اشتباه
- ارسال چندباره فرم
- Refresh کردن صفحه در زمان ارسال
- قطع اتصال هنگام Submit
بسیاری از این موارد ممکن است در یک Requirement ساده بهصورت مستقیم نوشته نشده باشند، اما تجربه تستر به او میگوید که این نقاط میتوانند محل مناسبی برای پیدا کردن Defect باشند.
Error Guessing از کجا میآید؟
تجربه تستر میتواند از منابع مختلفی شکل گرفته باشد:
- تجربه پروژههای قبلی
- Defectهای قبلی همان سیستم
- Defectهای مشابه در پروژههای دیگر
- شناخت رفتار کاربران
- شناخت تکنولوژی مورد استفاده
- شناخت نقاط پیچیده سیستم
- تجربه تیم توسعه
- الگوهای رایج Failure
برای مثال، اگر در نسخه قبلی یک سیستم، مشکل Duplicate Transaction وجود داشته است، تستر ممکن است در نسخه جدید نیز سناریوهایی مانند موارد زیر را با دقت بیشتری بررسی کند:
- کلیک دوباره روی دکمه پرداخت
- ارسال مجدد Request
این همان استفاده از تجربه برای پیشبینی محل احتمالی Defect است.
۲. Exploratory Testing چیست؟
Exploratory Testing یا تست اکتشافی رویکردی است که در آن Test Design، Test Execution و Learning تا حد زیادی بهصورت همزمان انجام میشوند.
یعنی تستر صرفاً یک مجموعه Test Case از قبل نوشتهشده را اجرا نمیکند؛ بلکه در حین تست، یافتههای جدید میتوانند مسیر تستهای بعدی را شکل دهند.
Explore
↓
Learn
↓
Form a Hypothesis
↓
Test
↓
Observe
↓
Learn More
↓
Test Again
برای مثال، تستر وارد یک صفحه Checkout میشود و متوجه رفتار غیرعادی هنگام تغییر روش پرداخت میشود.
بهجای اینکه فقط طبق Test Case اولیه ادامه دهد، موضوع را بررسی میکند:
- اگر روش پرداخت را تغییر دهیم چه اتفاقی میافتد؟
- اگر دوباره به روش قبلی برگردیم چه؟
- اگر در همین لحظه صفحه Refresh شود چه؟
- اگر Session منقضی شود چه؟
- اگر کاربر روی دکمه پرداخت چند بار کلیک کند چه؟
هر مشاهده میتواند مسیر تست بعدی را شکل دهد.
آیا Exploratory Testing یعنی تست بدون برنامه؟
خیر.
این یک تصور رایج اما نادرست است.
Exploratory Testing به معنی تست کاملاً تصادفی یا بدون هدف نیست. تستر میتواند برای تست خود مواردی مانند موارد زیر را مشخص کند:
- هدف
- محدوده
- ریسکهای مهم
- زمان
- اطلاعات اولیه
- مسیرهای احتمالی
حتی میتوان از Test Charter برای تعیین هدف یک Session استفاده کرد.
مثلاً:
Test Charter: رفتار Checkout را در شرایط قطع و وصل شدن شبکه بررسی کن.
در این حالت تستر آزادی دارد که در طول Session بر اساس یافتههای خود مسیر تست را تغییر دهد، اما همچنان یک هدف مشخص دارد.
۳. Checklist-based Testing چیست؟
در Checklist-based Testing، تستر از یک Checklist از مواردی که باید بررسی شوند استفاده میکند.
این Checklist میتواند بر اساس موارد زیر تهیه شده باشد:
- تجربه تیم
- Defectهای قبلی
- استانداردهای سازمان
- Requirements
- ویژگیهای محصول
- Riskهای شناختهشده
- Best Practiceها
برای مثال، یک Checklist ساده برای تست فرم Login میتواند شامل موارد زیر باشد:
☐ Login با اطلاعات معتبر
☐ Password اشتباه
☐ Username نامعتبر
☐ فیلد خالی
☐ Password بسیار طولانی
☐ کاراکترهای خاص
☐ چند Login ناموفق
☐ Account Lock
☐ Forgot Password
☐ Session Timeout
تستر این موارد را بررسی میکند و در صورت نیاز، هنگام تست موارد جدیدی نیز به Checklist اضافه میکند.
مزیت مهم Checklist چیست؟
یکی از مشکلات تست این است که بعضی موارد مهم به دلیل فراموشی از قلم میافتند. Checklist میتواند این ریسک را کاهش دهد.
همچنین اگر یک تیم QA بارها یک نوع Feature مشابه را تست کند، میتواند تجربههای قبلی خود را به Checklist تبدیل کند.
مثلاً تیمی که بارها سیستمهای پرداخت را تست کرده، ممکن است Checklist مخصوص Payment داشته باشد:
- Successful Payment
- Failed Payment
- Timeout
- Duplicate Request
- Callback Failure
- Refund
- Cancelled Transaction
- Network Interruption
این Checklist به مرور میتواند به یک دانش جمعی قابل استفاده مجدد برای تیم QA تبدیل شود.
تفاوت سه Experience-based Technique
| تکنیک | ایده اصلی |
|---|---|
| Error Guessing | حدس زدن نقاطی که احتمال Defect در آنها بیشتر است |
| Exploratory Testing | یادگیری، طراحی تست و اجرای تست بهصورت همزمان و پویا |
| Checklist-based Testing | استفاده از فهرستی از موارد مهم برای جلوگیری از فراموشی |
این سه تکنیک میتوانند در کنار یکدیگر نیز استفاده شوند.
مثلاً تستر ابتدا Checklist مربوط به Payment را بررسی میکند، سپس با استفاده از Error Guessing سراغ نقاط پرریسک میرود و در طول Exploratory Testing، بر اساس یافتههای جدید مسیر تست را تغییر میدهد.
تجربه تستر جایگزین تکنیکهای سیستماتیک نیست
یک نکته مهم این است که Experience-based Testing نباید به معنی کنار گذاشتن تکنیکهای ساختاریافته باشد.
مثلاً تستر میتواند ابتدا با Equivalence Partitioning ورودیهای مهم را شناسایی کند و سپس با Error Guessing سناریوهایی را بررسی کند که بر اساس تجربه، احتمال Defect در آنها بالاتر است.
در واقع، تستر حرفهای معمولاً بین این دو رویکرد تعادل ایجاد میکند:
روشهای سیستماتیک + تجربه و قضاوت حرفهای
چگونه Test Technique مناسب را انتخاب کنیم؟
شناخت Test Techniques بهتنهایی کافی نیست؛ در یک پروژه واقعی باید بتوانیم تشخیص دهیم برای یک Feature مشخص، کدام تکنیک یا ترکیب تکنیکها بیشترین ارزش را ایجاد میکند.
معمولاً یک تکنیک واحد برای همه شرایط بهترین گزینه نیست. انتخاب Test Technique به عواملی مانند نوع Requirement، پیچیدگی Business Rule، ساختار سیستم، Risk، اطلاعات در دسترس و زمان موجود برای تست بستگی دارد.
۱. نوع Requirement را بررسی کنید
اولین سؤال این است که Requirement چه ماهیتی دارد.
اگر Requirement شامل یک محدوده عددی باشد، تکنیکهایی مانند:
Equivalence Partitioning + Boundary Value Analysis
میتوانند مناسب باشند.
مثلاً:
سن کاربر باید بین ۱۸ تا ۶۰ سال باشد.
اگر Requirement شامل چند Business Rule و Condition باشد، میتوان از:
Decision Table Testing
استفاده کرد.
اگر رفتار سیستم به Stateهای مختلف وابسته باشد:
State Transition Testing
گزینه مناسبی است.
و اگر Requirement یک جریان مشخص از تعامل User با سیستم را توصیف کند:
Use Case Testing
میتواند برای طراحی سناریوها مفید باشد.
۲. پیچیدگی Business Logic را در نظر بگیرید
هرچه Business Logic پیچیدهتر باشد، احتمال اینکه تستهای ساده بعضی Combinationها را از دست بدهند بیشتر میشود.
مثلاً فرض کنید یک سیستم قیمت محصول را بر اساس این موارد محاسبه میکند:
- نوع Customer
- مبلغ سفارش
- نوع محصول
- کد تخفیف
- زمان خرید
در چنین شرایطی استفاده از چند Test Case ساده احتمالاً کافی نیست.
میتوان از Decision Table Testing برای مدلسازی Combinationهای مهم استفاده کرد و سپس با توجه به Risk، مهمترین Ruleها را برای تست انتخاب کرد.
۳. به Boundaryها توجه کنید
هر زمان Requirement دارای محدوده یا Threshold باشد، باید به Boundaryها حساس باشیم.
مثلاً:
کاربر حداکثر میتواند ۵ بار Password را اشتباه وارد کند.
در اینجا مقادیر زیر اهمیت دارند:
4 → قبل از مرز
5 → روی مرز
6 → بعد از مرز
در چنین شرایطی Boundary Value Analysis میتواند بسیار مفید باشد.
نکته مهم این است که Boundary فقط به اعداد محدود نیست و میتواند شامل مواردی مانند موارد زیر باشد:
- حداقل و حداکثر طول String
- تعداد مجاز تلاش
- حجم فایل
- تعداد آیتمهای قابل انتخاب
- تاریخ شروع و پایان
- محدودیت تعداد درخواستها
۴. بررسی کنید آیا رفتار سیستم State-based است
اگر رفتار یک Feature به وضعیت قبلی آن وابسته باشد، State Transition Testing ارزش بیشتری پیدا میکند.
مثلاً:
یک Account پس از ۵ Login ناموفق Lock میشود.
در اینجا فقط تست کردن «Login موفق» و «Login ناموفق» کافی نیست. باید مسیر تغییر وضعیت را نیز بررسی کنیم:
Active
↓
Failed Attempt 1
↓
Failed Attempt 2
↓
Failed Attempt 3
↓
Failed Attempt 4
↓
Failed Attempt 5
↓
Locked
همچنین باید بررسی کنیم چه اتفاقی در صورت تلاش مجدد برای Login یا Unlock شدن Account رخ میدهد.
۵. به Risk Feature توجه کنید
همه Featureها اهمیت یکسانی ندارند.
فرض کنید دو Feature داریم:
- Feature A: تغییر رنگ پسزمینه یک صفحه
- Feature B: انتقال وجه بین دو حساب بانکی
واضح است که Risk مربوط به Feature B بسیار بالاتر است.
بنابراین در Featureهای پرریسک، معمولاً باید ترکیب کاملتری از Test Techniques را در نظر گرفت.
مثلاً برای Payment:
Equivalence Partitioning
+
Boundary Value Analysis
+
Decision Table
+
State Transition
+
Error Guessing
این به معنی آن نیست که همه این تکنیکها همیشه باید استفاده شوند؛ بلکه Risk بالاتر میتواند استفاده از تکنیکهای متنوعتر و پوشش عمیقتر را توجیه کند.
۶. اطلاعات در دسترس را در نظر بگیرید
نوع اطلاعاتی که تستر در اختیار دارد نیز بر انتخاب تکنیک تأثیر میگذارد.
اگر Requirements و Business Rules در دسترس باشند، تکنیکهای Black-box میتوانند بسیار مفید باشند.
اگر ساختار داخلی Code نیز قابل بررسی باشد، White-box Techniques گزینههای بیشتری در اختیار تیم قرار میدهند.
اگر مستندات ناقص باشند اما تستر شناخت خوبی از سیستم داشته باشد، Experience-based Techniques میتوانند نقش مهمتری پیدا کنند.
یک مثال کامل از انتخاب تکنیک
فرض کنید یک سیستم برای Password Reset داریم.
Requirementها:
- لینک بازیابی Password تا ۳۰ دقیقه معتبر است.
- پس از استفاده از لینک، امکان استفاده مجدد از آن وجود ندارد.
- کاربر باید Password جدیدی با حداقل ۸ کاراکتر انتخاب کند.
- پس از چند درخواست ناموفق، سیستم باید رفتار مشخصی داشته باشد.
حالا میتوانیم Test Techniques را اینطور انتخاب کنیم:
Boundary Value Analysis
برای بررسی محدودیت ۳۰ دقیقه:
29 دقیقه و 59 ثانیه
30 دقیقه
30 دقیقه و 1 ثانیه
Equivalence Partitioning
کمتر از 8 → Invalid
8 یا بیشتر → Valid
State Transition Testing
Generated
↓
Active
↓
Used
↓
Invalid
Error Guessing
- استفاده مجدد از Token
- Refresh کردن صفحه
- باز کردن Token در چند Browser
- ارسال چندباره Request
- استفاده از Token منقضیشده
در نتیجه، یک Feature میتواند همزمان از چند Test Technique بهره ببرد.
یک قانون ساده برای انتخاب تکنیک
میتوانیم یک مدل ذهنی ساده داشته باشیم:
نوع Requirement
│
├── Range / Input
│ └── Equivalence Partitioning
│ Boundary Value Analysis
│
├── Business Rules
│ └── Decision Table
│
├── State-based Behavior
│ └── State Transition
│
├── User Flow
│ └── Use Case Testing
│
├── Code Structure
│ └── White-box Techniques
│
└── Unknown / Risky Areas
└── Experience-based Techniques
البته این یک راهنمای انتخاب است، نه یک قانون سخت و مطلق.
در عمل، یک تستر حرفهای ابتدا سیستم و Riskهای آن را درک میکند و سپس ترکیبی از تکنیکهای مناسب را انتخاب میکند.
ترکیب چند Test Technique در یک Feature
در پروژههای واقعی، معمولاً یک Test Technique بهتنهایی نمیتواند تمام جنبههای مهم یک Feature را پوشش دهد.
ممکن است یک Requirement هم محدوده عددی داشته باشد، هم Business Rule، هم State و هم سناریوهای خطای محتمل.
در چنین شرایطی، تستر میتواند چند Test Technique را در کنار یکدیگر به کار ببرد.
چرا ترکیب Test Techniques مهم است؟
فرض کنید یک فروشگاه اینترنتی برای سفارشها چنین قوانینی دارد:
- مبلغ سفارش باید بین ۱۰۰ هزار تا ۵ میلیون تومان باشد.
- مشتریان VIP برای سفارشهای بالاتر از ۱ میلیون تومان ۲۰٪ تخفیف دریافت میکنند.
- سفارش پس از پرداخت وارد وضعیت
Paidمیشود و پس از ارسال بهShippedتغییر میکند.
در این Feature چند نوع مسئله مختلف داریم:
- یک Range داریم.
- چند Business Rule داریم.
- چند State داریم.
- احتمال وجود Edge Case و خطاهای پیشبینینشده نیز وجود دارد.
بنابراین استفاده از یک تکنیک واحد کافی نیست.
ترکیب Equivalence Partitioning و Boundary Value Analysis
برای مبلغ سفارش میتوان ابتدا Partitionها را مشخص کرد:
| محدوده | وضعیت |
|---|---|
| کمتر از ۱۰۰,۰۰۰ | Invalid |
| ۱۰۰,۰۰۰ تا ۵,۰۰۰,۰۰۰ | Valid |
| بیشتر از ۵,۰۰۰,۰۰۰ | Invalid |
سپس با Boundary Value Analysis اطراف مرزها را بررسی میکنیم:
99,999
100,000
100,001
4,999,999
5,000,000
5,000,001
در اینجا هر تکنیک یک نقش متفاوت دارد:
- Equivalence Partitioning کمک میکند محدودههای رفتاری متفاوت را شناسایی کنیم.
- Boundary Value Analysis کمک میکند اطراف مرزهای حساس را دقیقتر بررسی کنیم.
ترکیب Decision Table با Test Techniques دیگر
حالا Business Rule تخفیف را در نظر بگیریم:
اگر Customer از نوع VIP باشد و مبلغ سفارش حداقل ۱ میلیون تومان باشد، ۲۰٪ تخفیف اعمال شود.
این Rule را میتوان با Decision Table Testing مدل کرد:
| VIP | مبلغ ≥ ۱ میلیون | تخفیف |
|---|---|---|
| Yes | Yes | 20% |
| Yes | No | بدون تخفیف |
| No | Yes | بدون تخفیف |
| No | No | بدون تخفیف |
اما یک نکته جالب وجود دارد. برای Condition مربوط به مبلغ، میتوانیم از Boundary Value Analysis نیز استفاده کنیم.
999,999
1,000,000
1,000,001
بنابراین دو تکنیک میتوانند روی یک Feature با یکدیگر ترکیب شوند:
Decision Table
+
Boundary Value Analysis
Decision Table مشخص میکند چه ترکیبهایی از شرایط باید بررسی شوند.
BVA مشخص میکند کدام مقادیر نزدیک به مرز اهمیت بیشتری دارند.
ترکیب State Transition با Error Guessing
حالا وضعیت سفارش را در نظر بگیریم:
Pending
↓
Paid
↓
Shipped
↓
Delivered
با State Transition Testing میتوانیم Transitionهای معتبر و نامعتبر را بررسی کنیم.
Pending → Paid ✓
Paid → Shipped ✓
Shipped → Delivered ✓
Delivered → Paid ?
در کنار آن میتوان از Error Guessing برای بررسی رفتارهای غیرعادی استفاده کرد.
- کاربر در لحظه پرداخت صفحه را Refresh کند.
- پرداخت انجام شود اما Response به Client نرسد.
- کاربر چند بار روی دکمه پرداخت کلیک کند.
- وضعیت سفارش در دو Request همزمان تغییر کند.
- ارتباط با Payment Gateway قطع شود.
اینجا State Transition ساختار رفتار سیستم را بررسی میکند، در حالی که Error Guessing به تستر کمک میکند نقاطی را که احتمال Defect در آنها بیشتر است هدف قرار دهد.
یک Feature میتواند چند لایه Test Design داشته باشد
بنابراین برای همین Feature میتوانیم چنین ترکیبی داشته باشیم:
Order Feature
│
┌───────────────┼────────────────┐
│ │ │
▼ ▼ ▼
Amount Discount Status
│ │ │
▼ ▼ ▼
EP + BVA Decision Table State Transition
│
└──────────────┐
▼
Error Guessing
این مدل نشان میدهد که Test Techniques رقیب یکدیگر نیستند، بلکه میتوانند مکمل یکدیگر باشند.
آیا همیشه باید همه تکنیکها را استفاده کنیم؟
خیر.
یکی از اشتباهات رایج این است که تصور کنیم تستر حرفهای باید برای هر Feature تمام Test Techniques را اجرا کند.
هدف Test Technique این نیست که تعداد Test Caseها را افزایش دهد؛ هدف این است که با توجه به Risk، Complexity، Business Impact و زمان موجود، تستهای مؤثرتر طراحی کنیم.
برای یک Feature ساده ممکن است یک یا دو تکنیک کافی باشد. اما برای یک Feature حساس مانند Payment، Authentication یا Financial Transaction، ترکیب چند تکنیک میتواند ارزش بسیار بیشتری داشته باشد.
Test Technique و Test Case یکی نیستند
یک نکته مهم دیگر این است که Test Technique خودش Test Case نیست.
برای مثال:
Boundary Value Analysis
یک Technique است.
اما:
وارد کردن مبلغ ۱۰۰,۰۰۰ تومان و بررسی پذیرش سفارش
یک Test Case است که میتواند با استفاده از آن Technique طراحی شده باشد.
به همین شکل، Decision Table یک تکنیک است، اما هر Rule موجود در جدول میتواند به یک یا چند Test Case تبدیل شود.
بنابراین مسیر کلی را میتوان اینگونه دید:
Requirement
↓
Business Rules / Conditions
↓
انتخاب Test Technique
↓
Test Conditions
↓
Test Cases
↓
Test Execution
↓
Test Results / Defects
در واقع Test Technique پلی بین Test Analysis و Test Case Design است و به تستر کمک میکند از اطلاعات موجود به Test Caseهای هدفمند برسد.
از Requirement تا Test Case با استفاده از Test Techniques
حالا میتوانیم فرآیند را از یک Requirement واقعی تا طراحی Test Case دنبال کنیم.
فرض کنید در یک فروشگاه اینترنتی چنین Requirementای داریم:
کاربر میتواند سفارشی با مبلغ بین ۱۰۰ هزار تا ۵ میلیون تومان ثبت کند. اگر کاربر VIP باشد و مبلغ سفارش حداقل ۱ میلیون تومان باشد، ۲۰٪ تخفیف دریافت میکند.
در نگاه اول ممکن است این Requirement ساده به نظر برسد؛ اما درون آن چند Test Condition مختلف وجود دارد.
مرحله اول: Requirement را به Test Condition تبدیل کنیم
ابتدا Requirement را به بخشهای قابل تست تقسیم میکنیم:
- مبلغ کمتر از ۱۰۰ هزار تومان نباید پذیرفته شود.
- مبلغ ۱۰۰ هزار تومان باید پذیرفته شود.
- مبلغ بین ۱۰۰ هزار تا ۵ میلیون تومان باید معتبر باشد.
- مبلغ بیشتر از ۵ میلیون تومان نباید پذیرفته شود.
- Customer نوع VIP میتواند تخفیف دریافت کند.
- تخفیف فقط برای سفارشهای حداقل ۱ میلیون تومان اعمال میشود.
- Customer غیر VIP نباید این تخفیف را دریافت کند.
اینجا هنوز Test Case ننوشتهایم. در واقع ابتدا Test Conditionهایی را شناسایی کردهایم که باید مورد بررسی قرار گیرند.
مرحله دوم: انتخاب Test Technique
حالا به ماهیت Requirement نگاه میکنیم.
برای مبلغ سفارش، Range داریم:
۱۰۰,۰۰۰ تا ۵,۰۰۰,۰۰۰
بنابراین Equivalence Partitioning برای شناسایی محدودههای مختلف مناسب است.
و چون Boundaryهای مهم داریم، Boundary Value Analysis نیز انتخاب مناسبی است.
از طرف دیگر، تخفیف به ترکیبی از دو Condition وابسته است:
- VIP بودن Customer
- مبلغ سفارش حداقل ۱ میلیون تومان
بنابراین Decision Table Testing میتواند برای این بخش استفاده شود.
مرحله سوم: طراحی Test Case با Equivalence Partitioning
Partitionهای مبلغ سفارش:
| Partition | محدوده | وضعیت |
|---|---|---|
| P1 | کمتر از ۱۰۰,۰۰۰ | Invalid |
| P2 | ۱۰۰,۰۰۰ تا ۵,۰۰۰,۰۰۰ | Valid |
| P3 | بیشتر از ۵,۰۰۰,۰۰۰ | Invalid |
از هر Partition میتوان یک مقدار نماینده انتخاب کرد:
| Test Case | مبلغ | نتیجه مورد انتظار |
|---|---|---|
| TC-01 | 50,000 | رد شود |
| TC-02 | 500,000 | پذیرفته شود |
| TC-03 | 6,000,000 | رد شود |
در اینجا بهجای تست کردن تعداد زیادی مقدار، از هر Partition یک مقدار نماینده انتخاب کردهایم.
مرحله چهارم: طراحی Test Case با Boundary Value Analysis
حالا سراغ مرزها میرویم.
برای مرز پایین:
99,999
100,000
100,001
برای مرز بالا:
4,999,999
5,000,000
5,000,001
بنابراین میتوان Test Caseهای زیر را طراحی کرد:
| Test Case | مبلغ | نتیجه مورد انتظار |
|---|---|---|
| TC-04 | 99,999 | رد شود |
| TC-05 | 100,000 | پذیرفته شود |
| TC-06 | 100,001 | پذیرفته شود |
| TC-07 | 4,999,999 | پذیرفته شود |
| TC-08 | 5,000,000 | پذیرفته شود |
| TC-09 | 5,000,001 | رد شود |
میبینیم که BVA تمرکز بیشتری روی اطراف Boundary دارد.
مرحله پنجم: طراحی Test Case با Decision Table
حالا بخش تخفیف را بررسی میکنیم.
دو Condition داریم:
- Customer VIP است؟
- مبلغ سفارش حداقل ۱ میلیون تومان است؟
جدول تصمیم:
| Rule | VIP | مبلغ ≥ ۱ میلیون | نتیجه |
|---|---|---|---|
| R1 | Yes | Yes | ۲۰٪ تخفیف |
| R2 | Yes | No | بدون تخفیف |
| R3 | No | Yes | بدون تخفیف |
| R4 | No | No | بدون تخفیف |
از این Ruleها میتوان Test Case طراحی کرد:
| Test Case | Customer | مبلغ | نتیجه مورد انتظار |
|---|---|---|---|
| TC-10 | VIP | 1,500,000 | ۲۰٪ تخفیف |
| TC-11 | VIP | 500,000 | بدون تخفیف |
| TC-12 | Non-VIP | 1,500,000 | بدون تخفیف |
| TC-13 | Non-VIP | 500,000 | بدون تخفیف |
حالا یک نکته مهم داریم. در TC-10 مبلغ ۱,۵۰۰,۰۰۰ انتخاب شده است، اما برای Condition مربوط به ۱ میلیون تومان بهتر است Boundaryها را نیز بررسی کنیم.
999,999
1,000,000
1,000,001
به این ترتیب Decision Table و BVA میتوانند در کنار یکدیگر استفاده شوند.
مرحله ششم: بررسی اینکه آیا Test Caseها Requirement را پوشش میدهند؟
حالا Test Caseهای طراحیشده را در کنار Requirement قرار میدهیم:
Requirement
│
├── Order Amount
│ ├── Equivalence Partitioning
│ └── Boundary Value Analysis
│
└── Discount Rule
└── Decision Table
این ساختار کمک میکند ببینیم Test Caseهای ما از کدام بخش Requirement استخراج شدهاند.
در پروژههای بزرگتر، چنین ارتباطی میتواند در Requirements Traceability Matrix (RTM) نیز ثبت و مدیریت شود.
آیا تعداد بیشتر Test Case همیشه بهتر است؟
خیر.
یکی از اهداف Test Techniques این است که بتوانیم با Test Caseهای منطقی و هدفمند، بخشهای مهم سیستم را پوشش دهیم.
اگر برای یک Requirement ساده صدها Test Case بدون تحلیل مناسب تولید کنیم، لزوماً کیفیت تست بالاتر نمیرود. ممکن است Test Caseهای زیادی داشته باشیم که عملاً یک رفتار یکسان را تکرار میکنند.
در مقابل، استفاده درست از تکنیکهایی مانند Equivalence Partitioning، Boundary Value Analysis و Decision Table Testing میتواند به طراحی Test Caseهای هدفمندتر کمک کند.
Test Technique جایگزین Tester’s Thinking نیست
Test Techniques ابزارهایی برای Systematic Test Design هستند، نه جایگزینی برای تحلیل و تفکر تستر.
ممکن است Requirement ظاهراً فقط یک Range داشته باشد، اما تستر بر اساس تجربه خود متوجه شود که موارد دیگری نیز ارزش بررسی دارند:
- مقدار Null
- مقدار خالی
- مقدار اعشاری
- مقدار منفی
- مقدار بسیار بزرگ
- کاراکترهای غیرمنتظره
- تغییر مقدار هنگام ارسال Request
- ارسال چندباره Request
در اینجا میتوان از Error Guessing یا Exploratory Testing در کنار تکنیکهای ساختاریافته استفاده کرد.
در نتیجه، یک Test Design خوب معمولاً حاصل ترکیب تحلیل Requirement + Test Technique + Risk Analysis + تجربه تستر است.
تکنیکهای تست در Agile، API و Automation Testing
Test Techniques فقط برای تست دستی و پروژههای سنتی کاربرد ندارند. در پروژههای مدرن، همین تکنیکها میتوانند در Agile، API Testing و Automation Testing نیز برای طراحی بهتر تستها مورد استفاده قرار بگیرند.
نکته مهم این است که Technique مستقل از ابزار است. یعنی Boundary Value Analysis چه بهصورت Manual اجرا شود و چه با یک Automation Framework، همچنان همان Test Technique است.
Test Techniques در Agile
در Agile معمولاً Requirements به شکلهایی مانند User Story، Acceptance Criteria و Business Rule در اختیار تیم قرار میگیرند.
مثلاً:
As a customer, I want to apply a discount code so that I can receive a discount on my order.
Acceptance Criteria:
- کد تخفیف معتبر باید پذیرفته شود.
- کد منقضیشده نباید پذیرفته شود.
- کد استفادهشده نباید دوباره قابل استفاده باشد.
- تخفیف فقط برای سفارشهای بالاتر از ۱ میلیون تومان اعمال شود.
تستر میتواند همین Acceptance Criteria را به Test Condition تبدیل کند و سپس تکنیک مناسب را انتخاب کند.
Acceptance Criteria
↓
شناخت Test Conditions
↓
انتخاب Test Techniques
↓
Test Cases
| ویژگی Requirement | Technique مناسب |
|---|---|
| محدودیت مبلغ سفارش | EP + BVA |
| معتبر/نامعتبر بودن Coupon | EP |
| ترکیب چند شرط تخفیف | Decision Table |
| وضعیت Coupon | State Transition |
| سناریوهای غیرعادی | Error Guessing / Exploratory |
بنابراین Agile به این معنی نیست که Test Design حذف میشود؛ بلکه Test Design معمولاً در کنار توسعه و Refinement، سریعتر و مستمرتر انجام میشود.
Test Techniques در API Testing
در API Testing نیز Test Techniques کاربرد زیادی دارند.
فرض کنید API زیر وجود دارد:
POST /orders
و API مقدار amount را بین ۱۰۰,۰۰۰ و ۵,۰۰۰,۰۰۰ قبول میکند.
میتوان از Boundary Value Analysis استفاده کرد:
99,999
100,000
100,001
4,999,999
5,000,000
5,000,001
اما در API Testing، علاوه بر مقدارهای معمول، میتوان نوع داده و ساختار Request را نیز بررسی کرد:
{
"amount": 100000
}
در کنار مقدار معتبر، حالتهای دیگری نیز ارزش بررسی دارند:
{
"amount": 99999
}
یا:
{
"amount": null
}
یا حتی:
{
"amount": "100000"
}
در اینجا تستر میتواند از ترکیبی از Equivalence Partitioning، Boundary Value Analysis و Error Guessing استفاده کند.
Decision Table در API Testing
فرض کنید API پرداخت بر اساس سه شرط رفتار متفاوتی دارد:
- Payment Method معتبر است؟
- مبلغ کافی است؟
- Account فعال است؟
در اینجا Decision Table میتواند Combinationهای مهم را مشخص کند.
Payment Method
+
Sufficient Balance
+
Active Account
↓
Payment Result
سپس میتوان Ruleهای مهم را به Test Case تبدیل کرد و آنها را مستقیماً روی API اجرا کرد.
این روش بهخصوص برای APIهایی که Business Logic پیچیدهای دارند بسیار مفید است.
State Transition در API
APIها نیز میتوانند State داشته باشند.
مثلاً یک Payment ممکن است این وضعیتها را داشته باشد:
Created
↓
Pending
↓
Paid
↓
Completed
یا در صورت شکست:
Pending
↓
Failed
حالا میتوان بررسی کرد:
- آیا Payment از
PendingبهPaidمنتقل میشود؟ - آیا Paymentِ
Failedمیتواند دوباره Retry شود؟ - آیا Paymentِ
Completedمیتواند دوباره پرداخت شود؟ - آیا Request تکراری باعث ایجاد تراکنش دوم میشود؟
در چنین شرایطی State Transition Testing میتواند ساختار مناسبی برای طراحی تستها ایجاد کند.
Test Techniques در Automation Testing
یک تصور اشتباه این است که وقتی تستها Automation میشوند، دیگر نیازی به Test Techniques نیست.
در واقع Automation بیشتر روش اجرای Test Case را تغییر میدهد، نه منطق طراحی آن را.
مثلاً اگر تستر با BVA این مقادیر را انتخاب کرده باشد:
99,999
100,000
100,001
میتوان همین Test Caseها را با Automation Framework اجرا کرد.
Test Technique
↓
Test Case Design
↓
Automation Script
↓
Automated Test Execution
Automation مشخص نمیکند چه چیزی را تست کنیم؛ بلکه کمک میکند Test Caseهای انتخابشده را سریعتر، قابل تکرارتر و در مقیاس بزرگتر اجرا کنیم.
یک مثال با Automation
فرض کنید یک Password باید حداقل ۸ کاراکتر داشته باشد.
با Boundary Value Analysis میتوان مقادیر زیر را انتخاب کرد:
7 characters
8 characters
9 characters
سپس همین Test Caseها میتوانند به Automated Test تبدیل شوند:
TC-01 → 7 characters → Invalid
TC-02 → 8 characters → Valid
TC-03 → 9 characters → Valid
در اینجا BVA منطق انتخاب دادههای تست را مشخص کرده است و Automation فقط اجرای این Test Caseها را بر عهده گرفته است.
ترکیب Test Techniques با CI/CD
در یک Pipeline مدرن، Test Techniques حتی میتوانند بهصورت غیرمستقیم بر کیفیت Automated Regression Suite تأثیر بگذارند.
فرض کنید تیم برای یک Feature جدید ابتدا Test Conditions را تحلیل میکند و با استفاده از:
- Equivalence Partitioning
- Boundary Value Analysis
- Decision Table
- Error Guessing
Test Caseهای مهم را طراحی میکند.
سپس Test Caseهای مناسب Automation میشوند و در CI/CD اجرا میشوند.
Requirement
↓
Test Analysis
↓
Test Technique
↓
Test Case
↓
Automation
↓
CI/CD Pipeline
↓
Test Result
بنابراین کیفیت Automation تا حد زیادی به کیفیت Test Design وابسته است.
اگر Test Caseها از ابتدا ضعیف طراحی شده باشند، Automation فقط همان تستهای ضعیف را با سرعت بیشتری اجرا میکند! ⚠️
نکته مهم: Automation خودش Test Technique نیست
برای جلوگیری از یک اشتباه مفهومی:
Automation Testing با Test Technique یکی نیست.
- Boundary Value Analysis → Test Technique
- Decision Table Testing → Test Technique
- Exploratory Testing → Test Technique
- Playwright → ابزار/Framework برای Automation
- Selenium → ابزار/Framework برای Automation
بنابراین میتوان گفت:
Test Technique مشخص میکند تست را چگونه طراحی کنیم؛ Automation Tool کمک میکند تست طراحیشده را چگونه اجرا و تکرار کنیم.
این تفکیک در پروژههای مدرن اهمیت زیادی دارد، چون ممکن است یک تیم از بهترین Automation Framework استفاده کند، اما اگر Test Design مناسبی نداشته باشد، همچنان بخش مهمی از Riskهای سیستم را پوشش ندهد.
نقش AI در Test Design و Test Techniques 🤖
با گسترش ابزارهای Artificial Intelligence (AI)، نحوه طراحی و اجرای تستها نیز در حال تغییر است. اما یک نکته مهم را باید از ابتدا روشن کنیم:
AI جایگزین Test Technique نیست؛ بلکه میتواند به تستر در انتخاب، ترکیب و اجرای بهتر Test Techniques کمک کند.
یعنی همچنان باید بدانیم Equivalence Partitioning چیست، Boundary Value Analysis چه زمانی مناسب است و Decision Table چه مسئلهای را حل میکند. AI میتواند در این فرآیند نقش یک دستیار هوشمند را داشته باشد.
AI چگونه میتواند به انتخاب Test Technique کمک کند؟
فرض کنید Requirement زیر را داریم:
کاربر میتواند بین ۱۰۰ هزار تا ۵ میلیون تومان سفارش ثبت کند و مشتریان VIP برای سفارشهای بالاتر از ۱ میلیون تومان ۲۰٪ تخفیف دریافت میکنند.
تستر میتواند Requirement را در اختیار یک ابزار AI قرار دهد و از آن بخواهد:
- Test Conditions را شناسایی کند.
- Boundaryها را پیدا کند.
- Business Ruleها را استخراج کند.
- Test Techniques مناسب را پیشنهاد دهد.
- Test Caseهای اولیه تولید کند.
مثلاً AI ممکن است تشخیص دهد که برای این Requirement استفاده از:
- Equivalence Partitioning
- Boundary Value Analysis
- Decision Table Testing
مناسب است.
اما پیشنهاد AI نباید بدون بررسی تستر مستقیماً به Test Case نهایی تبدیل شود.
AI برای استخراج Boundaryها
یکی از کاربردهای مناسب AI، پیدا کردن Boundaryهای پنهان یا قابل توجه در Requirements است.
مثلاً Requirement میگوید:
کاربر حداکثر میتواند ۵ بار رمز عبور خود را اشتباه وارد کند.
یک ابزار AI میتواند موارد زیر را پیشنهاد دهد:
4 attempts
5 attempts
6 attempts
و حتی سؤالهای تکمیلی مطرح کند:
- بعد از Attempt پنجم Account دقیقاً چه زمانی Lock میشود؟
- آیا Attemptهای ناموفق پس از Login موفق Reset میشوند؟
- آیا درخواست همزمان میتواند Counter را دچار مشکل کند؟
- آیا رفتار در Client و Server یکسان است؟
اینجا AI علاوه بر پیدا کردن Boundary، میتواند به کشف Test Conditionهای جدید نیز کمک کند.
AI و Decision Table
در Requirements پیچیده، یکی از کاربردهای جذاب AI تبدیل Business Rules به ساختار قابل تحلیل است.
مثلاً:
اگر Customer VIP باشد و مبلغ سفارش حداقل یک میلیون تومان باشد، تخفیف ۲۰٪ اعمال شود. اگر Coupon نیز معتبر باشد، تخفیف دیگری اعمال خواهد شد.
با افزایش تعداد Conditionها، احتمال فراموش شدن Combinationهای مهم بیشتر میشود.
AI میتواند در ایجاد یک Decision Table اولیه کمک کند:
Condition 1 → VIP?
Condition 2 → Amount ≥ 1M?
Condition 3 → Valid Coupon?
↓
Decision Table
↓
Test Conditions
↓
Test Cases
اما باز هم باید بررسی شود که:
- آیا Ruleها درست تفسیر شدهاند؟
- آیا بعضی Combinationها از نظر Business غیرممکن هستند؟
- آیا Rule مهمی جا افتاده است؟
- آیا Expected Resultها با Requirement مطابقت دارند؟
AI و Error Guessing
Error Guessing به تجربه و شناخت الگوهای رایج Defect وابستگی زیادی دارد. AI میتواند در این قسمت نیز مفید باشد.
مثلاً اگر Feature مربوط به File Upload باشد، میتوان از AI خواست نقاط مستعد خطا را پیشنهاد کند:
- فایل خالی
- فایل بسیار بزرگ
- Extension نامعتبر
- نام فایل بسیار طولانی
- کاراکترهای خاص در نام فایل
- Upload چندباره
- قطع Network هنگام Upload
- Refresh در زمان Upload
- ارسال Request تکراری
اما اینجا یک تفاوت مهم وجود دارد:
AI پیشنهاد میدهد؛ تستر باید تشخیص دهد کدام پیشنهاد واقعاً در Context سیستم اهمیت دارد.
AI و Exploratory Testing
حتی در Exploratory Testing نیز AI میتواند نقش دستیار داشته باشد.
مثلاً تستر در حال بررسی Checkout است و از AI میخواهد بر اساس Feature و Defectهای شناختهشده، مسیرهای احتمالی برای Exploration پیشنهاد دهد.
Checkout
│
├── Network interruption
├── Multiple clicks
├── Session expiration
├── Back / Forward
├── Refresh
├── Concurrent requests
└── Payment failure
تستر سپس بر اساس مشاهده سیستم، یافتههای جدید و Risk، مسیر Exploration را تغییر میدهد.
بنابراین AI میتواند ایده و Hypothesis تولید کند، اما بخش مهم Exploratory Testing یعنی مشاهده، یادگیری و تصمیمگیری همچنان به فرآیند تست وابسته است.
AI میتواند Test Case تولید کند؛ اما تولید Test Case به معنی Test Design کامل نیست
این نکته بسیار مهم است.
ممکن است AI برای یک Requirement دهها Test Case تولید کند.
اما سؤال اصلی این نیست که:
«چند Test Case تولید شده؟»
بلکه باید پرسید:
آیا Test Caseهای تولیدشده، Test Conditions و Riskهای مهم را پوشش میدهند؟
ممکن است یک AI تعداد زیادی Test Case تولید کند اما:
- Test Caseهای تکراری داشته باشد.
- Boundary مهمی را از دست بدهد.
- Business Rule را اشتباه تفسیر کند.
- Expected Result نادرست تولید کند.
- سناریوهای غیرممکن ایجاد کند.
- یک Risk مهم را اصلاً شناسایی نکند.
بنابراین AI-generated Test Cases نیازمند Review انسانی هستند.
یک مدل مناسب برای استفاده از AI
Requirement
↓
AI-assisted Analysis
↓
Test Conditions
↓
پیشنهاد Test Techniques
↓
Human Review
↓
Test Cases
↓
Review / Refinement
↓
Test Execution
در این مدل، AI نقش Assistant دارد، نه تصمیمگیرنده نهایی.
AI و ترکیب Test Techniques
یکی از کاربردهای ارزشمند AI این است که میتواند به تستر کمک کند متوجه شود یک Feature فقط با یک Technique پوشش مناسبی ندارد.
مثلاً برای یک Password Reset Feature ممکن است پیشنهاد شود:
Password Length
↓
Boundary Value Analysis
Token Validity
↓
Equivalence Partitioning
Token State
↓
State Transition Testing
Multiple Conditions
↓
Decision Table Testing
Unexpected Behavior
↓
Error Guessing
تستر میتواند این پیشنهادها را بررسی کرده و بر اساس Risk و Business Context تصمیم نهایی بگیرد.
محدودیتهای AI در Test Techniques
استفاده از AI بدون توجه به محدودیتهای آن میتواند حتی باعث ایجاد اعتماد کاذب شود.
AI ممکن است:
- Requirement را اشتباه تفسیر کند.
- Context کسبوکار را بهدرستی متوجه نشود.
- برخی Business Ruleهای ضمنی را نبیند.
- Test Caseهای مشابه تولید کند.
- Defectهای احتمالی را بیشازحد یا کمتر از واقعیت تخمین بزند.
- Expected Result اشتباه پیشنهاد کند.
به همین دلیل، هرچه Feature حساستر و پرریسکتر باشد، Review انسانی اهمیت بیشتری پیدا میکند.
آینده Test Design؛ همکاری تستر و AI
بهتر است AI را نه بهعنوان جایگزین Tester، بلکه بهعنوان یک Test Design Assistant در نظر بگیریم.
تستر دانش و درک مواردی مانند موارد زیر را وارد فرآیند میکند:
- Business Context
- Risk
- User Behavior
- Product Goals
- Technical Context
- Defect History
و AI میتواند در کارهایی مانند موارد زیر کمک کند:
- تحلیل Requirement
- استخراج Conditionها
- پیشنهاد Boundaryها
- تولید Decision Table
- پیشنهاد Test Case
- پیدا کردن Edge Case
- تحلیل Defect Patternها
در نتیجه، مهارت آینده تستر فقط این نیست که Test Case بنویسد؛ بلکه باید بتواند Test Problem را تحلیل کند، Test Technique مناسب را انتخاب کند و از AI برای افزایش کیفیت Test Design استفاده کند.
اشتباهات رایج در استفاده از Test Techniques ⚠️
شناخت Test Techniques بهتنهایی تضمین نمیکند که Test Design خوبی داشته باشیم. حتی اگر تستر با Equivalence Partitioning، Boundary Value Analysis، Decision Table، State Transition و Error Guessing آشنا باشد، ممکن است آنها را به شکل نادرستی به کار ببرد.
۱. استفاده از یک Technique برای همه چیز
یکی از اشتباهات رایج این است که تستر یک تکنیک را یاد میگیرد و تلاش میکند همه Requirementها را با همان تکنیک تست کند.
مثلاً چون Boundary Value Analysis برای یک Feature نتیجه خوبی داده، برای Featureهای دیگر نیز از آن استفاده شود.
در حالی که هر Technique برای نوع خاصی از مسئله مناسبتر است.
Range
↓
EP / BVA
Business Rules
↓
Decision Table
State-based Behavior
↓
State Transition
User Flow
↓
Use Case Testing
۲. تصور اینکه هر Test Case باید فقط با یک Technique طراحی شود
یک Test Case میتواند نتیجه ترکیب چند Technique باشد.
مثلاً برای یک Discount Feature، Decision Table میتواند Combination شرایط را مشخص کند و Boundary Value Analysis مقادیر حساس اطراف Threshold را تعیین کند.
بنابراین لازم نیست برای هر Test Case فقط یک Technique در نظر بگیریم.
۳. اشتباه گرفتن Test Technique با Test Type
این اشتباه بهخصوص در ابتدای یادگیری Software Testing زیاد دیده میشود.
مثلاً:
Functional Testing یک Test Technique است.
❌ اشتباه.
Functional Testing یک Test Type است.
یا:
Boundary Value Analysis یک Test Type است.
❌ اشتباه.
Boundary Value Analysis یک Test Technique است.
Test Level
↓
در چه سطحی؟
Test Type
↓
چه جنبهای؟
Test Technique
↓
چگونه Test Case طراحی کنیم؟
۴. تصور اینکه ۱۰۰٪ Coverage یعنی ۱۰۰٪ تست شده است
در White-box Testing ممکن است به ۱۰۰٪ Statement Coverage یا ۱۰۰٪ Branch Coverage برسیم.
اما این موضوع به معنی بدون نقص بودن نرمافزار نیست.
Coverage میتواند نشان دهد کدام بخشهایی از Code یا ساختار مورد اجرا قرار گرفتهاند، اما لزوماً تضمین نمیکند که:
- Requirementها بهدرستی پوشش داده شدهاند.
- Business Ruleها درست تست شدهاند.
- Expected Resultها صحیح هستند.
- تمام Edge Caseها بررسی شدهاند.
- مشکلات Usability یا Performance کشف شدهاند.
بنابراین Coverage یک ابزار مهم برای ارزیابی پوشش است، اما معادل کیفیت کامل تست نیست.
۵. تبدیل Test Techniques به یک Checklist خشک
Test Techniques قرار نیست باعث شوند تستر فقط یک فهرست ثابت را بدون فکر اجرا کند.
☑ EP
☑ BVA
☑ Decision Table
☑ State Transition
این فهرست بهتنهایی به معنی کامل شدن Test Design نیست.
باید ابتدا مسئله را درک کند و سپس ببیند کدام Technique واقعاً برای آن Feature ارزش ایجاد میکند.
۶. نادیده گرفتن Risk
ممکن است دو Feature از نظر تکنیکی مشابه باشند اما Risk کاملاً متفاوتی داشته باشند.
مثلاً یک محدودیت عددی در Font Size با یک محدودیت عددی در Transaction Amount هر دو ممکن است BVA داشته باشند، اما اهمیت و Risk آنها یکسان نیست.
در Featureهای حساس، ممکن است لازم باشد علاوه بر تکنیکهای ساختاریافته، از Error Guessing، Exploratory Testing و تستهای تکمیلی نیز استفاده شود.
۷. تولید Test Caseهای زیاد به جای Test Caseهای مؤثر
هدف Test Techniques افزایش تعداد Test Caseها نیست. هدف این است که بتوانیم Test Caseهای معنادار و هدفمند طراحی کنیم.
مثلاً اگر یک Input دارای سه Equivalence Partition باشد، لزوماً نیازی نیست دهها مقدار از هر Partition را بدون دلیل تست کنیم.
از طرف دیگر، اگر Boundary بسیار حساس باشد، ممکن است چند مقدار نزدیک به آن ارزش زیادی داشته باشند.
بنابراین سؤال اصلی این نیست:
«چند Test Case داریم؟»
بلکه این است:
«آیا Test Caseهای ما Riskها و رفتارهای مهم سیستم را بهخوبی هدف قرار دادهاند؟»
۸. نادیده گرفتن تجربه و Defect History
گاهی Requirements فقط بخشی از داستان را نشان میدهند.
فرض کنید در نسخههای قبلی یک سیستم، مشکل تکراری در این موارد وجود داشته است:
- Double Submit
- Session Expiration
- Duplicate Transaction
- Incorrect Date Handling
حتی اگر Requirement جدید مستقیماً به این موارد اشاره نکند، Defect History میتواند سرنخ ارزشمندی برای Test Design باشد.
اینجاست که Experience-based Techniques مانند Error Guessing اهمیت پیدا میکنند.
۹. تصور اینکه Exploratory Testing یعنی تست بدون برنامه
Exploratory Testing به معنی «هر چیزی به ذهنم رسید امتحان کنم» نیست.
در Exploratory Testing، تستر همزمان:
Test Design + Test Execution + Learning
را پیش میبرد.
داشتن یک هدف یا Test Charter میتواند Exploration را متمرکزتر کند.
مثلاً:
رفتار Checkout را هنگام قطع و وصل شدن Network بررسی کن.
این بسیار متفاوت از تست کاملاً تصادفی است.
۱۰. اعتماد کامل به Test Caseهای تولیدشده توسط AI
AI میتواند در Test Design بسیار مفید باشد، اما خروجی آن باید Review شود.
اگر AI صد Test Case تولید کند، تعداد زیاد آنها بهتنهایی نشانه کیفیت نیست.
باید بررسی کنیم:
- آیا Requirement درست تفسیر شده است؟
- آیا Boundaryها درست شناسایی شدهاند؟
- آیا Business Ruleها کامل هستند؟
- آیا Test Caseها تکراری نیستند؟
- آیا Expected Result درست است؟
- آیا Riskهای مهم پوشش داده شدهاند؟
بنابراین:
AI میتواند Test Design را سریعتر کند، اما مسئولیت تصمیمگیری درباره کیفیت تست همچنان با تیم تست است.
یک مدل ساده برای جلوگیری از این اشتباهات
قبل از نهایی کردن Test Caseها، میتوان این مسیر را دنبال کرد:
Requirement
↓
شناخت Business Ruleها
↓
شناسایی Test Conditions
↓
تحلیل Risk
↓
انتخاب Technique مناسب
↓
ترکیب Techniqueهای مکمل در صورت نیاز
↓
طراحی Test Cases
↓
Review
↓
Test Execution
این فرآیند باعث میشود Test Technique به یک اسم حفظشده در ذهن تستر تبدیل نشود، بلکه به یک ابزار واقعی برای Test Design تبدیل شود.
نکته کلیدی
یک تستر خوب کسی نیست که فقط تعداد زیادی Test Technique را حفظ کرده باشد.
تستر حرفهای باید بتواند تشخیص دهد:
این Requirement چه نوع مسئلهای ایجاد میکند، چه Riskهایی دارد و کدام Test Technique میتواند با کمترین تکرار، بیشترین ارزش را برای کشف Defectهای مهم ایجاد کند؟
و در بسیاری از پروژههای واقعی، بهترین پاسخ نه یک Technique، بلکه ترکیبی هوشمندانه از چند Technique است.
