وقتی وارد دنیای تست نرم‌افزار می‌شوید، خیلی زود با چند واژه روبه‌رو می‌شوید که در ظاهر شبیه هم هستند:

  • Error — خطا یا اشتباه
  • Defect — نقص یا اشکال
  • Bug — باگ
  • Failure — شکست یا خرابی
  • Incident — رخداد یا رویداد

در گفت‌وگوی روزمره تیم‌های نرم‌افزاری، ممکن است همه این مفاهیم را با یک جمله ساده بیان کنیم:

«یه مشکلی توی نرم‌افزار هست.»

اما در تست نرم افزار، این مشکل می‌تواند در مراحل مختلف ایجاد یا مشاهده شود و هر اصطلاح، زاویه متفاوتی از آن را توصیف می‌کند.

Table of Contents

خطا(Error) نقص(Defect) خرابی (Failure) دقیقا چیست؟

فرض کنید یک فروشگاه اینترنتی داریم.

یکی از قوانین کسب‌وکار این است:

اگر مبلغ سفارش بیشتر از یک میلیون تومان باشد، مشتری باید ۱۰٪ تخفیف دریافت کند.

Developer مسئول پیاده‌سازی این قابلیت است.

او Requirement را بررسی می‌کند، اما هنگام پیاده‌سازی شرط را اشتباه متوجه می‌شود و منطق نادرستی را وارد Code می‌کند.

در این لحظه هنوز مشتری با مشکلی مواجه نشده است.

اما یک انسان مرتکب اشتباه شده است.

🧠 این همان Error (خطا یا اشتباه) است.

Error چیست؟ خطا یا اشتباه چیست؟

Error را در فارسی معمولاً «خطا» ترجمه می‌کنیم. در برخی منابع و توضیحات نیز ممکن است واژه Mistake (اشتباه) را ببینید.

به زبان ساده:

Error یک اشتباه انسانی است که می‌تواند به ایجاد یک Defect منجر شود.

مثلاً:

  • Developer یک Requirement را اشتباه تفسیر می‌کند.
  • Business Analyst یک نیازمندی را اشتباه متوجه می‌شود.

در این موارد، منشأ اولیه مشکل می‌تواند یک اشتباه انسانی باشد.

نکته مهم این است که در این مرحله درباره عمل یا تصمیم نادرست انسان صحبت می‌کنیم، نه هنوز درباره رفتار سیستم.

از Error به Defect

اشتباه Developer وارد Code شده است.

حالا در نرم‌افزار یک شرط اشتباه وجود دارد.

اینجا دیگر فقط درباره اشتباه انسان صحبت نمی‌کنیم؛ یک مشکل در Work Product ایجاد شده است.

🐞 این مشکل را Defect (نقص یا اشکال) می‌نامیم.

Defect چیست؟

به زبان ساده:

Defect یک نقص یا مشکل در یک Work Product است که باعث می‌شود آن محصول کاری با نیازمندی، مشخصات یا انتظار موردنظر مطابقت نداشته باشد.

نکته مهم این است که Defect فقط در Code وجود ندارد.

ممکن است Defect در موارد زیر وجود داشته باشد:

  • Requirement
  • Design
  • Architecture
  • Source Code
  • Database
  • Test Case
  • Test Data
  • Documentation
  • Configuration

مثلاً اگر Business Analyst یک Requirement را اشتباه نوشته باشد، همان Requirement می‌تواند یک Defect داشته باشد.

Error و Defect چه تفاوتی دارند؟

تفاوت اصلی را می‌توان این‌طور خلاصه کرد:

Error در سطح اشتباه انسان است.

و:

Defect در سطح نقص ایجادشده در یک Work Product است.

مثلاً:

Business Analyst نیاز مشتری را اشتباه متوجه شده است.

این Error است.

اگر این برداشت اشتباه وارد Requirement شود و Requirement با نیاز واقعی مطابقت نداشته باشد:

🐞 Defect داریم.

به شکل ساده:

  • 👤 انسان اشتباه می‌کند → Error
  • 📄 اشتباه وارد Work Product می‌شود → Defect

چرا به Defect می‌گوییم Bug؟ 🐞

اگر در یک تیم نرم‌افزاری کار کنید، احتمالاً واژه Bug (باگ) را زیاد می‌شنوید.

مثلاً Tester می‌گوید:

«یک Bug پیدا کردم.»

یا در ابزار مدیریت Issue، یک مورد با عنوان Bug ثبت می‌شود.

Bug و Defect یکی هستند؟

در استفاده روزمره صنعت نرم‌افزار، Bug و Defect اغلب تقریباً به یک معنا استفاده می‌شوند.

وقتی Tester می‌گوید:

«یک Bug پیدا کردم.»

معمولاً منظورش این است:

«یک Defect در نرم‌افزار پیدا کردم.»

با این حال، بهتر است این دو را کاملاً مترادف و رسمی در نظر نگیریم.

Defect اصطلاح گسترده‌تری است و می‌تواند به نقص موجود در انواع Work Product اشاره کند، در حالی که Bug در گفت‌وگوی رایج صنعت نرم‌افزار معمولاً برای اشاره به یک مشکل یا نقص نرم‌افزاری استفاده می‌شود.

Bug ≈ Defect

اما این دو همیشه اصطلاحاتی کاملاً مترادف و یکسان نیستند.

چرا اصلاً به مشکل نرم‌افزار می‌گوییم Bug؟

داستان معروفی در تاریخ کامپیوتر وجود دارد.

در سال ۱۹۴۷، هنگام کار روی کامپیوتر Harvard Mark II، یک پروانه واقعی (Moth) در یکی از تجهیزات دستگاه گیر کرد و باعث ایجاد مشکل شد. تیم آن را خارج کرد و این اتفاق در گزارش‌های تاریخی ثبت شد.

این داستان بعدها به یکی از مشهورترین روایت‌ها درباره اصطلاح Computer Bug تبدیل شد.

💡 واژه Bug برای اشاره به مشکلات فنی، پیش از این اتفاق نیز استفاده می‌شده است.

حالا Tester وارد داستان می‌شود 🔍

تا اینجا داریم:

Developer یک اشتباه کرده است.

Error

⬇️

این اشتباه باعث ایجاد مشکل در Code شده است.

Defect / Bug

حالا Tester باید این مشکل را پیدا کند.

Tester یک Test Case طراحی می‌کند:

مبلغ سفارش = ۱,۵۰۰,۰۰۰ تومان

Expected Result:

۱۰٪ تخفیف اعمال شود.

اما سیستم تخفیف را اعمال نمی‌کند.

Tester بررسی می‌کند، شرایط را تکرار می‌کند و شواهد لازم را جمع‌آوری می‌کند.

حالا Defect شناسایی شده است.

اگر Defect در همین مرحله پیدا شود، می‌توان آن را قبل از Production اصلاح کرد.

وقتی Defect از تست عبور می‌کند

فرض کنید Tester این سناریو را تست نکرده باشد یا Test Case وجود داشته باشد اما Defect به هر دلیل شناسایی نشود.

در نتیجه:

Defect

⬇️

Production

نرم‌افزار در اختیار کاربران قرار می‌گیرد.

چند روز بعد، یک مشتری سفارش ۱.۵ میلیون تومانی ثبت می‌کند.

سیستم باید ۱۰٪ تخفیف بدهد، اما نمی‌دهد.

اینجا:

⚠️ Failure

Failure چیست؟ شکست یا خرابی چیست؟

Failure را می‌توان به فارسی «شکست» یا در بسیاری از متن‌های فنی «خرابی» ترجمه کرد.

Failure زمانی رخ می‌دهد که سیستم هنگام اجرا نتواند رفتار مورد انتظار را ارائه کند یا رفتاری خلاف انتظار نشان دهد.

در مثال ما:

  • سیستم باید تخفیف بدهد.
  • اما تخفیف نمی‌دهد.

پس سیستم رفتار مورد انتظار را ارائه نکرده است.

این یک Failure است.

آیا هر Defect باعث Failure می‌شود؟

❌ خیر.

ممکن است یک Defect در نرم‌افزار وجود داشته باشد، اما شرایط لازم برای فعال شدن آن هرگز اتفاق نیفتد.

مثلاً یک Defect در مسیر بسیار خاصی از Code وجود دارد، اما هیچ کاربری وارد آن مسیر نمی‌شود.

در این حالت:

Defect وجود دارد، اما Failure رخ نداده است.

اگر شرایط لازم ایجاد شود و سیستم رفتار نادرست نشان دهد:

Defect → Failure

بنابراین می‌توانیم رابطه را این‌طور در نظر بگیریم:

Defect + شرایط لازم برای فعال شدن → Failure

Failure و Incident چه تفاوتی دارند؟ 🚨

Incident (رخداد یا رویداد) اصطلاح دیگری است که ممکن است با Failure اشتباه گرفته شود.

فرض کنید کاربر وارد فروشگاه می‌شود و هنگام پرداخت، سیستم رفتار غیرمنتظره‌ای نشان می‌دهد.

کاربر یا Tester ممکن است این اتفاق را به‌عنوان یک Incident گزارش کند.

Incident چیست؟

Incident یک رویداد یا وضعیت غیرمنتظره است که در جریان Testing یا استفاده از سیستم مشاهده می‌شود و نیاز به بررسی دارد.

در لحظه مشاهده Incident، هنوز لزوماً نمی‌دانیم علت چیست.

مثلاً Tester می‌گوید:

«هنگام پرداخت، سیستم پیام خطای عجیبی نمایش داد.»

این یک Incident است که باید بررسی شود.

بعد از Investigation ممکن است مشخص شود:

  • واقعاً یک Defect وجود داشته است.
  • یک Failure رخ داده است.
  • مشکل از Test Environment بوده است.
  • Test Data اشتباه بوده است.
  • Configuration اشتباه بوده است.
  • رفتار سیستم طبق Requirement بوده و اصلاً Defect وجود نداشته است.

بنابراین:

Incident یک رخداد مشاهده‌شده است که نیاز به بررسی دارد؛ Failure رفتار نادرست سیستم در زمان اجرا نسبت به رفتار مورد انتظار است.

مثال

Tester هنگام تست پرداخت متوجه می‌شود:

«بعد از کلیک روی Pay، صفحه برای چند ثانیه سفید شد.»

🔍 این اتفاق می‌تواند یک Incident باشد.

اگر مشخص شود Backend هنگام پردازش درخواست Crash کرده و سیستم رفتار مورد انتظار را نداشته است:

Failure رخ داده است.

اگر بررسی بیشتر نشان دهد یک شرط اشتباه در Code وجود دارد:

Defect را پیدا کرده‌ایم.

پس ممکن است چنین رابطه‌ای شکل بگیرد:

Incident → Investigation → Failure → Defect

البته این ترتیب همیشه یکسان نیست و Incident و Failure را نباید مراحل اجباری یک زنجیره دانست.

حالا کل داستان را یکجا ببینیم 🧩

برگردیم به فروشگاه اینترنتی.

1. Error — خطا / اشتباه

Developer یک اشتباه انسانی انجام داده است.

⬇️

2. Defect — نقص / اشکال

اشتباه وارد Code شده و یک نقص در نرم‌افزار ایجاد کرده است.

⬇️

3. Bug — باگ

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

⬇️

4. Testing

Tester ممکن است Defect را پیدا کند.

اگر پیدا کند، مشکل قبل از Production اصلاح می‌شود.

اگر پیدا نکند:

⬇️

5. Production

کاربر واقعی از نرم‌افزار استفاده می‌کند.

⬇️

6. Failure — شکست / خرابی

سیستم در شرایط خاص رفتار نادرست نشان می‌دهد.

و اگر کاربر یا Tester این اتفاق را گزارش کند:

7. Incident — رخداد

یک Incident برای بررسی ثبت می‌شود.

یک نکته بسیار مهم درباره این زنجیره

نباید این تصویر را به‌صورت یک قانون قطعی حفظ کنیم:

Error → Defect → Bug → Failure → Incident

چون Bug و Defect در بسیاری از موقعیت‌ها به یک مفهوم اشاره می‌کنند و Incident نیز الزاماً بعد از Failure ایجاد نمی‌شود.

مدل مفهومی بهتر این است:

Error (اشتباه انسانی)

Defect (نقص موجود در Work Product)

در صورت فعال شدن شرایط لازم

Failure (رفتار نادرست هنگام اجرا)

ممکن است به‌عنوان Incident گزارش شود

و Bug را می‌توان در بسیاری از تیم‌ها به‌عنوان واژه رایج برای Defect در نظر گرفت.

خلاصه

اصطلاحمعادل فارسیبه چه چیزی اشاره می‌کند؟
Errorخطا / اشتباهاشتباه انسانی
Mistakeاشتباهواژه‌ای نزدیک به Error در برخی متون
Defectنقص / اشکالمشکل موجود در Work Product
Bugباگاصطلاح رایج برای نقص نرم‌افزاری
Failureشکست / خرابیرفتار نادرست سیستم هنگام اجرا
Incidentرخداد / رویداداتفاقی که مشاهده یا گزارش شده و نیاز به بررسی دارد

💡 اگر فقط یک چیز از این بخش به خاطر بسپارید:

Error یک اشتباه است، Defect یک نقص در Work Product است، Bug واژه رایج برای بسیاری از Defectهای نرم‌افزاری است، Failure بروز رفتار نادرست سیستم هنگام اجراست و Incident یک رخداد مشاهده‌شده است که ممکن است برای کشف علت آن نیاز به بررسی داشته باشد.

آیا هر Error حتماً به Defect تبدیل می‌شود؟

حالا که تفاوت Error (خطا یا اشتباه)، Defect (نقص یا اشکال) و Failure (شکست یا خرابی) را می‌دانیم، یک سؤال مهم مطرح می‌شود:

اگر یک انسان اشتباه کند، آیا حتماً یک Defect در نرم‌افزار ایجاد می‌شود؟

خیر.

یک Error همیشه به محصول آسیب نمی‌زند.

یک Error همیشه به محصول آسیب نمی‌زند

فرض کنید Developer هنگام نوشتن یک تابع، ابتدا یک راه‌حل اشتباه در ذهنش در نظر می‌گیرد.

او چند خط Code می‌نویسد، اما قبل از اینکه Code را Commit کند متوجه اشتباه خود می‌شود و آن را اصلاح می‌کند.

اینجا:

🧑‍💻 Error اتفاق افتاده است.

اما چون اشتباه قبل از ورود به Work Product نهایی اصلاح شده:

❌ Defect ایجاد نشده است.

ممکن است Error رخ دهد، اما به Defect منجر نشود.

این یکی از دلایلی است که Review، Pair Programming، Static Analysis و سایر فعالیت‌های کنترل کیفیت اهمیت دارند. آن‌ها می‌توانند بعضی از اشتباه‌ها را قبل از اینکه به نقص واقعی در محصول تبدیل شوند، شناسایی کنند.

یک مثال از Requirement

فرض کنید Business Analyst در ابتدا Requirement را اشتباه برداشت می‌کند.

او در یادداشت شخصی خودش می‌نویسد:

«کاربر می‌تواند سفارش را تا ۲۴ ساعت بعد لغو کند.»

اما هنگام جلسه Review، متوجه می‌شود که Requirement واقعی این بوده:

«کاربر می‌تواند سفارش را تا قبل از ارسال لغو کند.»

او مستندات را اصلاح می‌کند.

یک Error (اشتباه) رخ داده بود، اما این Error قبل از اینکه وارد Requirement نهایی شود، شناسایی و اصلاح شد.

Error ≠ الزاماً Defect

چه زمانی Error به Defect تبدیل می‌شود؟

وقتی نتیجه‌ی آن اشتباه وارد یک Work Product شود و باعث شود آن Work Product با نیازمندی یا انتظار موردنظر مطابقت نداشته باشد، با Defect مواجه می‌شویم.

مثلاً:

Error

Business Analyst Requirement را اشتباه متوجه می‌شود.

⬇️

Defect

Requirement اشتباه وارد مستندات رسمی می‌شود.

⬇️

Developer بر اساس Requirement اشتباه Code می‌نویسد.

⬇️

ممکن است Defectهای بیشتری ایجاد شوند.

این موضوع اهمیت Early Testing و فعالیت‌های Static Testing را نشان می‌دهد. هرچه زودتر Error یا Defect را پیدا کنیم، احتمال اینکه مشکل به مراحل بعدی منتقل شود کمتر می‌شود.

آیا هر Defect حتماً Failure ایجاد می‌کند؟

اینجا سؤال مهم‌تری داریم:

اگر Defect در نرم‌افزار وجود داشته باشد، آیا حتماً یک Failure رخ می‌دهد؟

خیر. ❌

وجود یک Defect به‌تنهایی به این معنی نیست که سیستم حتماً Failure نشان خواهد داد.

برای اینکه Failure اتفاق بیفتد، معمولاً باید شرایط خاصی فراهم شود تا Defect فعال شود و در رفتار سیستم خودش را نشان دهد.

یک مثال ساده

فرض کنید در یک نرم‌افزار، یک Defect در بخشی از Code وجود دارد که فقط زمانی اجرا می‌شود که:

تعداد محصولات سبد خرید بیشتر از ۱۰۰۰ عدد باشد.

اما در عمل تقریباً هیچ کاربری بیشتر از ۲۰ محصول در سبد خرید ندارد.

پس Defect در سیستم وجود دارد، ولی ممکن است ماه‌ها یا حتی سال‌ها هیچ Failureای ایجاد نکند.

Defect وجود دارد، اما Failure رخ نداده است.

چه زمانی Defect به Failure تبدیل می‌شود؟

می‌توانیم خیلی ساده بگوییم:

Defect زمانی می‌تواند باعث Failure شود که شرایط لازم برای فعال شدن آن فراهم شود و سیستم در نتیجه‌ی آن رفتار مورد انتظار را ارائه نکند.

مثلاً:

Defect

یک شرط اشتباه در Code وجود دارد.

⬇️

شرایط مناسب

کاربر وارد همان مسیر خاص می‌شود.

⬇️

Execution

Code اجرا می‌شود.

⬇️

Failure

سیستم نتیجه‌ی اشتباه تولید می‌کند.

Defect + شرایط مناسب + Execution → Failure

این مدل برای درک تفاوت Defect و Failure بسیار مفید است. 🧠

یک Defect ممکن است هیچ‌وقت Failure ایجاد نکند

فرض کنید در یک برنامه یک Defect وجود دارد، اما:

  • آن بخش از Code هیچ‌وقت اجرا نمی‌شود.
  • Feature مربوطه هیچ‌وقت استفاده نمی‌شود.
  • شرایط خاص موردنیاز برای فعال شدن Defect اتفاق نمی‌افتد.
  • Feature قبل از استفاده از سیستم حذف می‌شود.
  • Defect قبل از رسیدن به آن شرایط اصلاح می‌شود.

در همه‌ی این موارد ممکن است:

Defect وجود داشته باشد، اما Failure مشاهده نشود.

بنابراین یکی از اشتباهات رایج این است که فکر کنیم:

«اگر Failure ندیده‌ایم، پس Defectی وجود ندارد.»

این نتیجه‌گیری درست نیست.

آیا Tester با پیدا کردن Defect باعث Failure می‌شود؟

نه لزوماً.

فرض کنید Tester یک Test Case اجرا می‌کند و متوجه می‌شود سیستم در یک شرایط خاص نتیجه‌ی اشتباهی تولید می‌کند.

Tester در واقع یک Failure را مشاهده کرده است و با بررسی بیشتر می‌تواند Defect مربوط به آن را پیدا کند.

مثلاً Tester می‌بیند:

«مبلغ نهایی سفارش اشتباه محاسبه شده است.»

این چیزی است که Tester مشاهده کرده:

Failure

حالا Tester بررسی می‌کند چرا این اتفاق افتاده است.

در نهایت متوجه می‌شود:

یک شرط اشتباه در Code وجود دارد.

این:

Defect

است.

💡 بنابراین Tester همیشه مستقیماً Defect را مشاهده نمی‌کند؛ گاهی ابتدا Failure را مشاهده می‌کند و سپس با Investigation به Defect می‌رسد.

یک نکته ظریف: Defect همیشه در Code نیست

فرض کنید Tester متوجه می‌شود قیمت یک محصول اشتباه محاسبه شده است.

ممکن است در ابتدا تصور کنیم:

«حتماً Code مشکل دارد.»

اما بررسی بیشتر نشان می‌دهد Requirement اشتباه بوده است.

در این حالت:

Failure

رفتار اشتباه سیستم است.

اما Root Cause ممکن است یک:

Defect در Requirement

باشد.

این مثال اهمیت زیادی دارد، چون نشان می‌دهد Tester نباید فقط به دنبال «خط اشتباه در Code» بگردد.

گاهی باید زنجیره را به عقب دنبال کند:

Failure → Defect → Error

یک سناریوی کامل‌تر 🛒

فرض کنید فروشگاه اینترنتی ما قانون زیر را دارد:

برای سفارش‌های بالاتر از ۱ میلیون تومان، ۱۰٪ تخفیف اعمال شود.

مرحله اول — Error

Business Analyst نیازمندی را اشتباه متوجه می‌شود.

او فکر می‌کند:

تخفیف برای سفارش‌های کمتر از ۱ میلیون تومان است.

Error = اشتباه انسانی

مرحله دوم — Defect

Requirement اشتباه در سیستم ثبت می‌شود.

Defect = نقص در Requirement

مرحله سوم — Implementation

Developer بر اساس Requirement اشتباه، Code را پیاده‌سازی می‌کند.

حالا ممکن است یک Defect در Code هم ایجاد شود.

مرحله چهارم — Testing

Tester یک Test Case برای سفارش ۱.۵ میلیون تومانی اجرا می‌کند.

سیستم تخفیف نمی‌دهد.

Tester متوجه یک:

Failure

می‌شود.

مرحله پنجم — Investigation

Tester بررسی می‌کند.

مشخص می‌شود Code دقیقاً مطابق Requirement نوشته شده است.

پس مشکل Code نیست.

Tester نیازمندی را بررسی می‌کند و متوجه می‌شود نیازمندی از ابتدا اشتباه بوده است.

🐞 بنابراین Root Cause را باید در Defect موجود در Requirement جست‌وجو کرد.

اینجا یک درس مهم برای Tester داریم

Tester نباید فقط بپرسد:

«کدام خط Code اشتباه است؟»

بلکه باید بپرسد:

«چرا سیستم این رفتار را نشان داد؟»

ممکن است پاسخ در:

  • Code
  • Requirement
  • Design
  • Database
  • Configuration
  • Test Data
  • Environment

باشد.

این همان چیزی است که Testing را از صرفاً اجرای چند Test Case جدا می‌کند.

Error، Defect و Failure در یک نگاه

تا اینجا می‌توانیم رابطه را این‌طور ببینیم:

انسان اشتباه می‌کند
        ↓
Error
خطا / اشتباه
        ↓
ممکن است وارد Work Product شود
        ↓
Defect
نقص / اشکال
        ↓
ممکن است شرایط فعال شدن فراهم شود
        ↓
Execution
اجرای سیستم
        ↓
Failure
شکست / خرابی

اما مسیر دیگری هم ممکن است:

Error
  ↓
اصلاح قبل از ورود به محصول
  ↓
No Defect

یا:

Defect
  ↓
شرایط لازم هیچ‌وقت ایجاد نمی‌شود
  ↓
No Failure

و در Testing نیز ممکن است:

Test
 ↓
Failure مشاهده می‌شود
 ↓
Investigation
 ↓
Defect پیدا می‌شود

این مدل‌ها نشان می‌دهند که رابطه‌ی بین این مفاهیم خطی و اجباری نیست.

یک نکته مهم درباره Bug

در تمام این مثال‌ها وقتی می‌گوییم:

«Defect در Code وجود دارد.»

در یک تیم واقعی احتمالاً کسی می‌گوید:

«این Code یک Bug دارد.»

از نظر عملی، در بسیاری از تیم‌ها این دو عبارت به یک مشکل اشاره می‌کنند.

Bug معمولاً نام رایج‌تری برای یک Defect نرم‌افزاری است، اما Defect مفهوم گسترده‌تری دارد و می‌تواند در Work Productهای مختلف وجود داشته باشد.

این تفاوت زمانی اهمیت بیشتری پیدا می‌کند که بخواهیم درباره‌ی Requirement Defect، Design Defect، Code Defect، Test Defect و سایر انواع نقص صحبت کنیم.

جمع‌بندی این بخش 💡

۱. هر Error الزاماً Defect ایجاد نمی‌کند.

اگر اشتباه قبل از ورود به Work Product شناسایی و اصلاح شود، ممکن است Defectی ایجاد نشود.

۲. هر Defect الزاماً Failure ایجاد نمی‌کند.

برای بروز Failure باید شرایط لازم برای فعال شدن Defect و اجرای بخش مربوطه فراهم شود.

۳. Tester ممکن است ابتدا Failure را ببیند و سپس Defect را پیدا کند.

Failure چیزی است که در رفتار سیستم مشاهده می‌کنیم؛ Defect چیزی است که باید علت آن را پیدا کنیم.

این تفاوت، یکی از مهم‌ترین مفاهیمی است که یک Tester باید از همان ابتدای مسیر حرفه‌ای خود به‌خوبی درک کند.

Static Testing و Dynamic Testing چه ارتباطی با Defect دارند؟ 🔍

حالا که تفاوت Error (خطا)، Defect (نقص) و Failure (شکست) را می‌دانیم، یک سؤال مهم مطرح می‌شود:

اگر یک Defect در نرم‌افزار یا یکی از Work Productها وجود داشته باشد، آیا حتماً باید نرم‌افزار را اجرا کنیم تا آن را پیدا کنیم؟

خیر.

گاهی می‌توانیم یک Defect را بدون اجرای نرم‌افزار پیدا کنیم و گاهی برای کشف یک مشکل، باید نرم‌افزار را اجرا کنیم و رفتار آن را مشاهده کنیم.

اینجاست که دو مفهوم مهم وارد داستان می‌شوند:

  • Static Testing — تست ایستا
  • Dynamic Testing — تست پویا

Static Testing چیست؟ تست ایستا چیست؟

فرض کنید Developer هنوز Code را اجرا نکرده است.

Tester یا Developer کد را بررسی می‌کند و متوجه می‌شود شرطی که نوشته شده با Requirement مطابقت ندارد.

هیچ برنامه‌ای اجرا نشده و هیچ کاربری هم با سیستم کار نکرده است، اما یک Defect پیدا شده است.

🔍 این نمونه‌ای از Static Testing (تست ایستا) است.

تعریف ساده

Static Testing یعنی بررسی Work Product بدون اجرای نرم‌افزار یا سیستم مورد بررسی.

در Static Testing می‌توانیم مواردی مانند این‌ها را بررسی کنیم:

  • Requirements
  • User Stories
  • Design
  • Architecture
  • Source Code
  • Test Cases
  • Documentation

روش‌های رایج Static Testing شامل مواردی مانند:

  • Review
  • Walkthrough
  • Inspection
  • Static Analysis

یک مثال ساده از Static Testing

فرض کنید Requirement می‌گوید:

کاربر باید بتواند رمز عبوری بین ۸ تا ۲۰ کاراکتر انتخاب کند.

Developer هنوز Code را اجرا نکرده است.

Tester یا Developer Code را بررسی می‌کند و می‌بیند Validation به این شکل نوشته شده:

حداقل ۶ کاراکتر

همین‌جا می‌توانیم مشکل را تشخیص دهیم.

نیازی نیست:

  • برنامه را اجرا کنیم،
  • صفحه Login را باز کنیم،
  • رمز عبور وارد کنیم،
  • یا منتظر Failure بمانیم.

🐞 یک Defect از طریق Static Testing شناسایی شده است.

Dynamic Testing چیست؟ تست پویا چیست؟

حالا شرایط را تغییر دهیم.

Tester نرم‌افزار را اجرا می‌کند، وارد صفحه Login می‌شود و رمزی با ۷ کاراکتر وارد می‌کند.

سیستم آن را قبول می‌کند، در حالی که Requirement می‌گوید حداقل باید ۸ کاراکتر باشد.

اینجا Tester رفتار واقعی سیستم هنگام اجرا را مشاهده کرده است.

این نمونه‌ای از:

Dynamic Testing (تست پویا)

تعریف ساده

Dynamic Testing یعنی ارزیابی نرم‌افزار با اجرای آن و بررسی رفتار واقعی سیستم.

در Dynamic Testing می‌توانیم چیزهایی مانند این‌ها را بررسی کنیم:

  • Input
  • Output
  • Response
  • Business Logic
  • UI Behavior
  • API Response
  • Database Behavior
  • Performance
  • Security Behavior

Static و Dynamic چه تفاوتی دارند؟

ویژگیStatic TestingDynamic Testing
اجرای نرم‌افزار❌ بدون اجرا✅ با اجرا
هدفپیدا کردن مشکلات در Work Productبررسی رفتار سیستم
مثالReview، Inspection، Static AnalysisFunctional Testing، API Testing، UI Testing
Failure قابل مشاهدهمعمولاً نه✅ می‌تواند مشاهده شود
زمان کشف Defectمی‌تواند بسیار زود باشدمعمولاً بعد از قابل اجرا شدن محصول

اما یک نکته مهم:

Static Testing فقط برای پیدا کردن Defect در Code نیست.

ما می‌توانیم حتی قبل از شروع Coding، Defect را در Requirement پیدا کنیم.

مثلاً:

Requirement:
کاربر باید بتواند رمز عبور 6 تا 20 کاراکتری انتخاب کند.
Business Rule:
رمز عبور باید حداقل 8 کاراکتر باشد.

این تناقض را می‌توانیم در Review Requirement پیدا کنیم.

Static Testing می‌تواند قبل از وجود نرم‌افزار قابل اجرا انجام شود.

آیا به Defectهای کشف‌شده Static Defect می‌گوییم؟

اینجا باید کمی دقت کنیم. ⚠️

ممکن است در برخی منابع یا توضیحات آموزشی با عباراتی مانند:

  • Static Defect
  • Dynamic Defect

مواجه شوید.

اما بهتر است این اصطلاحات را به‌عنوان یک طبقه‌بندی رسمی و بنیادی برای خود Defectها در نظر نگیریم.

اصطلاحات استانداردتر این‌ها هستند:

Static Testing

و:

Dynamic Testing

یعنی بهتر است بگوییم:

«این Defect با استفاده از Static Testing شناسایی شد.»

نه اینکه لزوماً بگوییم:

«این یک Static Defect است.»

چون یک Defect می‌تواند در Work Product وجود داشته باشد و ما فقط درباره‌ی روش کشف آن صحبت کنیم.

یک Defect می‌تواند با Static Testing پیدا شود و Failure نداشته باشد

این نکته ارتباط بحث امروز با بخش قبلی را روشن می‌کند.

فرض کنید در Code یک شرط اشتباه وجود دارد، اما Tester هنوز نرم‌افزار را اجرا نکرده است.

با Code Review این شرط اشتباه پیدا می‌شود.

در اینجا:

Defect وجود دارد.

اما:

Failure مشاهده نشده است.

چرا؟ چون سیستم اصلاً اجرا نشده است.

پیدا کردن Defect الزاماً به معنی مشاهده Failure نیست.

آیا Dynamic Testing همیشه به Failure منجر می‌شود؟

باز هم نه.

فرض کنید Tester نرم‌افزار را اجرا می‌کند، اما Test Caseهای او همه موفق می‌شوند.

در این حالت:

Dynamic Testing انجام شده است.

اما ممکن است هیچ Failureای مشاهده نشده باشد.

حتی ممکن است Defectهایی در نرم‌افزار باقی مانده باشند که Test Caseهای فعلی قادر به فعال کردن آن‌ها نیستند.

Dynamic Testing ≠ الزاماً Failure

بلکه Dynamic Testing فرصتی برای مشاهده رفتار سیستم در زمان اجرا فراهم می‌کند.

یک مثال واقعی‌تر 🛒

برگردیم به فروشگاه اینترنتی.

Requirement می‌گوید:

اگر مبلغ سفارش بیشتر از ۱ میلیون تومان باشد، ۱۰٪ تخفیف اعمال شود.

مرحله اول: Review Requirement

Tester در جلسه Review متوجه می‌شود که در یک بخش از Requirement نوشته شده:

«بیشتر از ۱ میلیون»

ولی در بخش دیگری نوشته شده:

«۱ میلیون و بیشتر»

این تناقض بدون اجرای نرم‌افزار قابل مشاهده است.

🔍 Static Testing

مرحله دوم: Code Review

Developer Code را بررسی می‌کند و متوجه می‌شود شرط به شکل اشتباه نوشته شده است.

باز هم:

🔍 Static Testing

مرحله سوم: اجرای Test

Tester نرم‌افزار را اجرا می‌کند، سفارش ۱.۵ میلیون تومانی ثبت می‌کند و سیستم تخفیف نمی‌دهد.

حالا رفتار اشتباه سیستم مشاهده شده است.

⚠️ Dynamic Testing → Failure

پس یک Defect ممکن است از چند مسیر پیدا شود

ممکن است یک Defect را ابتدا در Requirement پیدا کنیم:

Static Testing

یا در Code Review:

Static Testing

یا هنگام اجرای نرم‌افزار:

Dynamic Testing

بنابراین Static و Dynamic در واقع دو رویکرد برای ارزیابی کیفیت Work Product و سیستم هستند.

چرا Static Testing اهمیت زیادی دارد؟ 💡

یکی از مهم‌ترین مزیت‌های Static Testing این است که می‌تواند مشکلات را قبل از اینکه به مراحل بعدی منتقل شوند شناسایی کند.

تصور کنید یک Requirement اشتباه داریم.

اگر آن را در مرحله‌ی Requirement Review پیدا کنیم:

اصلاح Requirement

اما اگر پیدا نشود:

Requirement اشتباه
        ↓
Design اشتباه
        ↓
Code اشتباه
        ↓
Test Caseهای اشتباه
        ↓
Production
        ↓
Failure

هرچه مشکل دیرتر کشف شود، معمولاً اصلاح آن می‌تواند هزینه و زمان بیشتری داشته باشد.

به همین دلیل Static Testing بخشی مهم از رویکرد Shift Left Testing محسوب می‌شود.

آیا Static Testing جای Dynamic Testing را می‌گیرد؟

خیر. ❌

این دو جایگزین یکدیگر نیستند.

Static Testing می‌تواند بسیاری از مشکلات را بدون اجرای نرم‌افزار پیدا کند، اما نمی‌تواند همه‌ی رفتارهای سیستم را بررسی کند.

از طرف دیگر Dynamic Testing به ما اجازه می‌دهد سیستم واقعی را در شرایط اجرا بررسی کنیم.

بنابراین یک رویکرد مناسب معمولاً ترکیبی از هر دو است:

Static Testing + Dynamic Testing

یک مثال ساده

Static Testing ممکن است بتواند متوجه شود:

«شرط تخفیف در Code اشتباه نوشته شده است.»

اما Dynamic Testing می‌تواند نشان دهد:

«وقتی کاربر سفارش ۱.۵ میلیون تومانی ثبت می‌کند، سیستم واقعاً تخفیف را اعمال نمی‌کند.»

هر دو ارزشمند هستند، اما از دو زاویه متفاوت به کیفیت نگاه می‌کنند.

یک نکته مهم برای Tester

اگر فقط Dynamic Testing انجام دهیم، ممکن است منتظر بمانیم تا نرم‌افزار اجرا شود و بعد مشکلات را پیدا کنیم.

اما یک Tester حرفه‌ای می‌تواند قبل از اجرای نرم‌افزار هم شروع به پیدا کردن مشکل کند.

  • 📝 Requirement را بررسی کند.
  • 🎨 Design را بررسی کند.
  • 💻 Code را Review کند.
  • 🧪 Test Caseها را بررسی کند.
  • 🔍 سپس در مرحله Dynamic Testing، رفتار واقعی سیستم را آزمایش کند.

این یعنی Testing فقط «اجرای Test Case» نیست.

جمع‌بندی این بخش

تا اینجا دو مسیر مهم برای کشف Defect داریم:

Static Testing

بدون اجرای نرم‌افزار → بررسی Work Product → امکان کشف Defect

Dynamic Testing

با اجرای نرم‌افزار → بررسی رفتار سیستم → امکان مشاهده Failure و کشف Defect

و مهم‌تر از همه:

Static Defect و Dynamic Defect را بهتر است اصطلاحات اصلی و رسمی برای دسته‌بندی Defectها ندانیم؛ اصطلاحات دقیق‌تر، Static Testing و Dynamic Testing هستند.

یک سناریوی کامل؛ از Error تا Defect و Failure 🛒

حالا وقت آن است که تمام مفاهیمی را که تا اینجا یاد گرفتیم، در یک سناریوی واقعی کنار هم قرار دهیم.

وقتی مفاهیم Error، Defect، Bug، Failure و Incident را در یک داستان واقعی ببینیم، تفاوت آن‌ها خیلی راحت‌تر در ذهن می‌ماند.

برای همین دوباره سراغ همان فروشگاه اینترنتی می‌رویم.

داستان از کجا شروع می‌شود؟

فرض کنید یک فروشگاه اینترنتی بزرگ داریم که روزانه هزاران سفارش دریافت می‌کند.

یکی از قوانین کسب‌وکار این فروشگاه این است:

🎁 اگر مبلغ نهایی سفارش بیشتر از ۱ میلیون تومان باشد، مشتری ۱۰٪ تخفیف دریافت می‌کند.

این قانون در Requirement ثبت شده و تیم توسعه باید آن را پیاده‌سازی کند.

در ظاهر، قانون بسیار ساده است. اما حالا ببینیم چگونه یک اشتباه کوچک می‌تواند مسیر طولانی‌ای را طی کند.

مرحله اول: یک Error اتفاق می‌افتد 👤

Business Analyst هنگام تحلیل Requirement، قانون کسب‌وکار را اشتباه متوجه می‌شود.

او تصور می‌کند قانون این است:

«اگر مبلغ سفارش کمتر از یک میلیون تومان باشد، تخفیف اعمال شود.»

در حالی که Requirement واقعی می‌گوید:

«اگر مبلغ سفارش بیشتر از یک میلیون تومان باشد، تخفیف اعمال شود.»

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

این چیست؟

Error (خطا / اشتباه)

مرحله دوم: Error وارد Requirement می‌شود 📝

Business Analyst بر اساس برداشت اشتباه خود، Requirement را ثبت می‌کند.

حالا این اشتباه دیگر فقط در ذهن یک فرد نیست؛ وارد یک Work Product شده است.

Requirement اکنون اطلاعات نادرستی دارد.

این چیست؟

🐞 Defect (نقص / اشکال)

پس:

Error باعث ایجاد Defect در Requirement شده است.

اگر Tester یا تیم در همین مرحله Requirement را Review کند، می‌تواند Defect را پیدا کند. در این صورت هنوز هیچ Codeای اجرا نشده است.

🔍 این یک نمونه از Static Testing است.

مرحله سوم: Defect وارد مرحله توسعه می‌شود 💻

فرض کنیم کسی Defect موجود در Requirement را پیدا نمی‌کند.

Developer نیازمندی را دریافت می‌کند و بر اساس همان منطق اشتباه شروع به کدنویسی می‌کند.

در نتیجه ممکن است یک Defect دیگر نیز در کد ایجاد شود.

Error
اشتباه در درک Requirement
        ↓
Defect
Requirement اشتباه
        ↓
Defect
Code اشتباه

یک Error اولیه می‌تواند در طول فرآیند توسعه، به مشکلات بیشتری در Work Productهای مختلف منجر شود.

مرحله چهارم: Tester شروع به Testing می‌کند 🔍

حالا Tester وارد فرآیند می‌شود.

فرض کنیم Test Case زیر نوشته شده است:

Test Case

ورودی: خریدی به مبلغ ۱,۵۰۰,۰۰۰ تومان انجام بده.

Expected Result: سیستم باید ۱۰٪ تخفیف اعمال کند.

Tester تست را اجرا می‌کند، اما سیستم تخفیف نمی‌دهد.

Tester نتیجه را با Expected Result مقایسه می‌کند و متوجه می‌شود:

Expected Result ≠ Actual Result

⚠️ چیزی که در زمان اجرای سیستم مشاهده شده است، یک Failure (شکست / خرابی) است.

مرحله پنجم: تستر Investigation را شروع می‌کند 🔎

Tester نمی‌خواهد فقط بگوید:

«تخفیف کار نمی‌کند.»

او باید بفهمد:

«چرا تخفیف کار نمی‌کند؟»

برای بررسی علت، اطلاعات مختلفی بررسی می‌شود:

  • Requirement
  • Test Case
  • Actual Result
  • Application Logs
  • API Response
  • Database
  • Code

در نهایت مشخص می‌شود Code دقیقاً مطابق Requirement پیاده‌سازی شده است.

پس مشکل در Code نیست. Tester به سراغ Requirement می‌رود و متوجه می‌شود Requirement از ابتدا اشتباه بوده است.

مرحله ششم: Root Cause پیدا می‌شود 🧠

با بررسی بیشتر مشخص می‌شود Business Analyst در ابتدای فرآیند، Requirement را اشتباه متوجه شده است.

Error
اشتباه انسانی در درک Requirement
        ↓
Defect
Requirement اشتباه
        ↓
Defect
Code بر اساس Requirement اشتباه
        ↓
Dynamic Testing
اجرای Test Case
        ↓
Failure
سیستم رفتار مورد انتظار را نشان نمی‌دهد

این مثال نشان می‌دهد که:

Failure همیشه همان چیزی نیست که Root Cause آن است.

Failure چیزی است که مشاهده کرده‌ایم؛ Defect یکی از دلایل ایجاد آن است و Error ممکن است در ریشه‌ی زنجیره قرار داشته باشد.

حالا سناریوی دوم را تصور کنیم

فرض کنید Tester از همان ابتدا Requirement را Review می‌کرد و متوجه می‌شد Requirement با Business Rule واقعی مطابقت ندارد.

Error
        ↓
Defect در Requirement
        ↓
🔍 Static Testing
        ↓
Defect اصلاح می‌شود
        ↓
Developer Requirement صحیح را دریافت می‌کند

در این حالت:

Failure اصلاً اتفاق نمی‌افتد.

این یکی از مهم‌ترین مزایای پیدا کردن مشکلات در مراحل اولیه است.

سناریوی سوم: Defect وجود دارد اما Failure رخ نمی‌دهد

فرض کنید در بخشی از سیستم یک Defect بسیار خاص وجود دارد که فقط زمانی فعال می‌شود که کاربر سفارشی با بیش از ۵۰۰۰ محصول ثبت کند.

در حالت عادی هیچ کاربری چنین سفارشی ثبت نمی‌کند.

بنابراین:

Defect وجود دارد.

اما:

Failure مشاهده نمی‌شود.

چون شرایط لازم برای فعال شدن Defect فراهم نشده است.

هر Defect الزاماً Failure ایجاد نمی‌کند.

سناریوی چهارم: Incident وارد داستان می‌شود 📋

حالا فرض کنیم مشتری با یک مشکل مواجه شده و به پشتیبانی گزارش می‌دهد:

«هنگام پرداخت سفارش، صفحه برای چند ثانیه سفید شد و بعد به صفحه اصلی برگشت.»

پشتیبانی این اتفاق را ثبت می‌کند.

در این مرحله با یک Incident (رخداد / رویداد) مواجه هستیم؛ زیرا یک اتفاق غیرمنتظره مشاهده یا گزارش شده و هنوز علت آن مشخص نیست.

ممکن است علت:

  • یک Defect در Code باشد.
  • یک مشکل Server باشد.
  • مشکل Network باشد.
  • Test Environment یا Production Configuration باشد.
  • داده‌ی ورودی نامعتبر باشد.
  • یا حتی رفتار سیستم مطابق Requirement باشد و انتظار کاربر اشتباه باشد.

پس Incident در این مرحله بیشتر یک موضوع برای Investigation است.

Incident چگونه ممکن است به Failure مرتبط شود؟

Tester یا تیم فنی Incident را بررسی می‌کند.

مشخص می‌شود هنگام پرداخت، یک Exception رخ داده و سیستم نتوانسته درخواست را پردازش کند.

حالا مشخص شده که سیستم در زمان اجرا رفتار مورد انتظار را نداشته است:

Failure

Investigation ادامه پیدا می‌کند و تیم متوجه می‌شود یک شرط اشتباه در Code وجود دارد.

این:

Defect

است.

اگر Root Cause را بیشتر بررسی کنیم، ممکن است مشخص شود Developer در پیاده‌سازی منطق یک Requirement اشتباه دچار Error شده است.

Incident
   ↓
Investigation
   ↓
Failure
   ↓
Defect
   ↓
Error

این مسیر نشان می‌دهد چرا Tester باید بتواند بین این مفاهیم تفاوت بگذارد.

یک نکته بسیار مهم: Error، Defect و Failure همیشه یک زنجیره خطی نیستند

بعد از دیدن این مثال‌ها شاید وسوسه شویم که این مدل را حفظ کنیم:

Error → Defect → Failure → Incident

اما واقعیت پیچیده‌تر است.

این‌ها مفاهیم مرتبط هستند، نه الزاماً مراحل اجباری یک فرآیند.

حالت اول

Error
  ↓
اصلاح قبل از ورود به Work Product
  ↓
❌ Defect ایجاد نمی‌شود

حالت دوم

Defect
  ↓
Static Testing
  ↓
❌ Failure رخ نمی‌دهد

حالت سوم

Defect
  ↓
شرایط فعال شدن ایجاد نمی‌شود
  ↓
❌ Failure رخ نمی‌دهد

حالت چهارم

Failure
  ↓
Investigation
  ↓
Defect پیدا می‌شود

حالت پنجم

Incident
  ↓
Investigation
  ↓
مشخص می‌شود اصلاً Defect وجود نداشته است

این حالت هم کاملاً ممکن است.

یک تصویر ذهنی ساده 🧩

اگر بخواهیم همه چیز را در یک تصویر ذهنی خلاصه کنیم:

👤 Human
   │
   │ اشتباه
   ▼
Error
خطا / اشتباه
   │
   │ اگر وارد Work Product شود
   ▼
Defect
نقص / اشکال
   │
   │ اگر شرایط لازم فراهم شود
   ▼
Execution
اجرای سیستم
   │
   ▼
Failure
شکست / خرابی
   │
   │ ممکن است گزارش شود
   ▼
Incident
رخداد / رویداد

اما این تصویر فقط برای درک ارتباط مفاهیم است و نباید آن را به‌عنوان یک فرآیند قطعی در نظر گرفت.

نقش Tester در این زنجیره چیست؟ 🔍

یکی از نکات جالب این داستان این است که Tester لزوماً فقط در انتهای زنجیره وارد نمی‌شود.

یک Tester حرفه‌ای می‌تواند خیلی زودتر وارد شود.

قبل از Coding

Requirement را بررسی می‌کند.

Static Testing

هنگام Development

Code Review و Static Analysis می‌تواند به پیدا کردن Defectها کمک کند.

Static Testing

هنگام اجرای نرم‌افزار

Behavior سیستم را بررسی می‌کند.

Dynamic Testing

بعد از مشاهده مشکل

Failure را بررسی می‌کند و به دنبال Defect می‌گردد.

Investigation

بعد از Release

Incidentهای Production را تحلیل می‌کند.

بنابراین نقش Tester فقط این نیست که:

«نرم‌افزار را اجرا کن و Bug پیدا کن.»

بلکه Tester می‌تواند در مراحل مختلف به پیشگیری، کشف، تحلیل و کاهش ریسک Defectها کمک کند.

چیزی که باید از این سناریو به خاطر بسپاریم 💡

اگر بخواهیم تمام این داستان را در چند جمله خلاصه کنیم:

  • Error (خطا / اشتباه) در سطح انسان اتفاق می‌افتد.
  • Defect (نقص / اشکال) مشکلی است که در یک Work Product وجود دارد.
  • Bug (باگ) واژه‌ای رایج برای اشاره به بسیاری از Defectهای نرم‌افزاری است.
  • Failure (شکست / خرابی) زمانی مشاهده می‌شود که سیستم در هنگام اجرا رفتار مورد انتظار را نشان ندهد.
  • Incident (رخداد) اتفاقی است که مشاهده یا گزارش می‌شود و ممکن است برای مشخص شدن علت آن نیاز به Investigation داشته باشد.

و مهم‌تر از همه:

Tester می‌تواند Defect را قبل از وقوع Failure پیدا کند.

این دقیقاً یکی از ارزش‌های اصلی Testing است. ✅

تفاوت Error، Defect، Bug، Fault، Failure و Incident در یک نگاه

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

Fault

اینجا ممکن است سؤال جدیدی ایجاد شود:

«Fault دیگر چیست؟ مگر ما Error، Defect و Bug را نداشتیم؟» 🤔

این سؤال منطقی است؛ چون این اصطلاحات در منابع مختلف گاهی با تفاوت‌های ظریفی استفاده می‌شوند و نباید آن‌ها را بدون توجه به Context کاملاً یکسان در نظر گرفت.

Fault چیست؟ خطا یا نقص؟

واژه‌ی Fault بسته به Context می‌تواند با مفاهیمی مثل «خطا»، «نقص»، «عیب» یا «ایراد» ترجمه شود.

اما ترجمه‌ی فارسی به‌تنهایی برای درک این اصطلاح کافی نیست؛ چون در بسیاری از منابع، Fault و Defect بسیار نزدیک به هم استفاده می‌شوند و گاهی عملاً به یک مفهوم اشاره می‌کنند.

تعریف ساده Fault

در بسیاری از متون تست نرم‌افزار، Fault به یک نقص یا ایراد در یک Work Product اشاره دارد که می‌تواند در شرایط خاص باعث رفتار نادرست سیستم شود.

مثلاً فرض کنید Requirement می‌گوید:

if (amount > 1000000)

اما در Code به اشتباه نوشته شده است:

if (amount < 1000000)

این منطق اشتباه می‌تواند در یک Context خاص، Fault محسوب شود. در بسیاری از Contextهای دیگر، همین مورد را Defect یا Bug نیز می‌نامیم.

پس Fault و Defect چه تفاوتی دارند؟

اینجا باید کمی محتاط باشیم. در منابع مختلف، این دو واژه همیشه با یک مرز ثابت و یکسان استفاده نمی‌شوند.

بنابراین نمی‌توان یک قانون همیشگی مانند این تعریف کرد که:

Fault همیشه X است و Defect همیشه Y.

با این حال، در برخی مدل‌های آموزشی می‌توان یک تفاوت مفهومی در نظر گرفت:

  • Defect بیشتر بر وجود یک نقص در یک Work Product تأکید می‌کند.
  • Fault می‌تواند به یک وضعیت نادرست یا ایراد در یک Artifact اشاره کند که ممکن است در شرایط خاص به Failure منجر شود.

اما در محیط‌های کاری و بسیاری از منابع، ممکن است این سه واژه را بسیار نزدیک به هم ببینید:

Fault ≈ Defect ≈ Bug

البته باید همیشه Context منبع یا تیم را در نظر گرفت.

چرا این همه واژه داریم؟ 😵

دلیل اصلی این است که اصطلاحات مهندسی نرم‌افزار در تمام منابع دقیقاً با یک الگوی واحد استفاده نمی‌شوند.

ممکن است یک منبع از Defect استفاده کند، منبع دیگری از Fault و در یک تیم نرم‌افزاری از Bug استفاده شود؛ در حالی که هر سه در حال اشاره به یک مشکل یا مفهومی بسیار نزدیک باشند.

بنابراین یک Tester حرفه‌ای باید بتواند مفهوم پشت واژه را تشخیص دهد، نه اینکه فقط به ترجمه‌ی لغوی آن وابسته باشد.

حالا همه اصطلاحات را کنار هم بگذاریم 🧩

اصطلاحمعادل پیشنهادی فارسیمفهوم ساده
Errorخطا / اشتباهاشتباه انسان
Mistakeاشتباهواژه‌ای نزدیک به Error در برخی Contextها
Defectنقص / اشکالمشکل در یک Work Product
Bugباگواژه‌ای رایج برای بسیاری از نقص‌های نرم‌افزاری
Faultنقص / عیب / ایراداصطلاحی نزدیک به Defect در بسیاری از منابع
Failureشکست / خرابیرفتار نادرست سیستم هنگام اجرا
Incidentرخداد / رویداداتفاقی که مشاهده یا گزارش شده و نیاز به بررسی دارد

اما یک نکته مهم وجود دارد:

این اصطلاحات را نباید صرفاً با معادل فارسی‌شان یکی فرض کنیم.

مثلاً «خطا»، «نقص» و «شکست» در فارسی روزمره ممکن است شبیه هم به نظر برسند، اما در Testing نقش‌های متفاوتی دارند.

یک مثال ساده برای تفاوت همه مفاهیم

فرض کنیم یک ماشین‌حساب آنلاین داریم.

Requirement می‌گوید:

۱۰ + ۵ باید برابر ۱۵ باشد.

۱. Error 👤

Developer به دلیل یک اشتباه انسانی، منطق محاسبه را به‌صورت نادرست پیاده‌سازی می‌کند.

Error یعنی همان اشتباه انسانی.

۲. Defect 🐞

این اشتباه وارد Code می‌شود و Code دارای یک نقص می‌شود.

Defect

۳. Bug

Tester در تیم ممکن است بگوید:

«محاسبه جمع یک Bug دارد.»

در اینجا Bug همان واژه رایج برای اشاره به آن Defect است.

۴. Fault

در یک منبع فنی دیگر ممکن است همین منطق اشتباه را Fault بنامند.

۵. Dynamic Testing 🔍

Tester ماشین‌حساب را اجرا می‌کند و ورودی زیر را وارد می‌کند:

10 + 5

۶. Failure ⚠️

سیستم نمایش می‌دهد:

14

در حالی که Expected Result برابر 15 است.

این رفتار نادرست هنگام اجرای سیستم، Failure است.

۷. Incident 📋

این مشکل مشاهده و برای بررسی ثبت می‌شود:

«ماشین‌حساب در محاسبه ۱۰ + ۵ نتیجه‌ی ۱۴ نمایش می‌دهد.»

این رخداد می‌تواند به‌عنوان یک Incident نیازمند Investigation باشد تا علت آن مشخص شود.

یک تفاوت بسیار مهم: Failure با Defect یکی نیست

گاهی افراد تازه‌کار می‌گویند:

«این Bug است چون سیستم نتیجه‌ی اشتباه نشان داد.»

اما بهتر است دقیق‌تر صحبت کنیم.

  • نتیجه‌ی اشتباه سیستم هنگام اجرا: Failure
  • نقصی که باعث آن شده: Defect / Bug

مثلاً:

سیستم به جای ۱۵ عدد ۱۴ نشان می‌دهد.

این چیزی است که مشاهده کرده‌ایم.

اما اگر مشخص شود Code دارای منطق یا Operator اشتباه است، این نقص، Defect محسوب می‌شود.

Failure را مشاهده می‌کنیم؛ Defect را با بررسی و Investigation پیدا می‌کنیم.

البته این جمله یک ساده‌سازی آموزشی است، اما برای ساختن یک تصویر ذهنی درست بسیار مفید است.

چرا این تفاوت برای Tester مهم است؟

فرض کنید Tester فقط گزارش کند:

❌ «جمع اشتباه است.»

این گزارش اطلاعات زیادی به Developer نمی‌دهد.

اما اگر Tester اطلاعات دقیق‌تری ارائه کند:

  • Expected: 15
  • Actual: 14
  • Input: 10 + 5
  • Environment: Production
  • Reproducibility: Always

حالا تیم می‌تواند Failure را بررسی کند و به Defect برسد.

بنابراین یک Tester حرفه‌ای فقط به دنبال گفتن «Bug پیدا کردم» نیست؛ بلکه باید بتواند:

  1. رفتار نادرست را مشاهده کند.
  2. Failure را دقیق توصیف کند.
  3. شرایط بازتولید را مشخص کند.
  4. شواهد جمع‌آوری کند.
  5. در صورت امکان Root Cause را بررسی کند.

آیا Tester باید Root Cause را پیدا کند؟

این موضوع به نقش Tester، تیم و فرآیند سازمان بستگی دارد.

Tester همیشه مسئول پیدا کردن Root Cause در سطح Code نیست. گاهی Tester فقط Failure را شناسایی و گزارش می‌کند و Developer یا تیم فنی Root Cause و Defect را بررسی می‌کند.

با این حال، یک Tester باتجربه می‌تواند اطلاعات ارزشمندی برای Investigation ارائه کند، مانند:

  • Logs
  • API Request / Response
  • Screenshots
  • Video
  • Network Trace
  • Test Data
  • Steps to Reproduce
  • Environment Information

این اطلاعات می‌توانند فرآیند پیدا کردن علت را بسیار سریع‌تر کنند.

یک مدل ذهنی بهتر برای حفظ این مفاهیم

به‌جای حفظ کردن هفت تعریف جداگانه، می‌توان این تصویر ذهنی را در نظر گرفت:

👤 انسان
   │
   │ اشتباه می‌کند
   ▼
ERROR
خطا / اشتباه
   │
   │ ممکن است وارد محصول شود
   ▼
DEFECT
نقص / اشکال
   │
   ├── در بسیاری از تیم‌ها: BUG
   │
   └── در برخی منابع: FAULT
   │
   │ اگر شرایط مناسب فراهم شود
   ▼
EXECUTION
اجرای سیستم
   │
   ▼
FAILURE
رفتار نادرست سیستم
   │
   │ ممکن است گزارش شود
   ▼
INCIDENT
رخداد / رویداد

این مدل کامل نیست و نباید آن را یک زنجیره‌ی اجباری دانست؛ اما برای ساختن یک تصویر ذهنی اولیه بسیار کاربردی است.

نکته طلایی مقاله ⭐

اگر بخواهیم کل مقاله را در یک جمله خلاصه کنیم:

Error اشتباه انسان است؛ Defect نقص موجود در Work Product است؛ Bug واژه‌ای رایج برای بسیاری از Defectهای نرم‌افزاری است؛ Fault اصطلاحی نزدیک به Defect است که در برخی منابع با معنایی مشابه یا با تفاوتی ظریف استفاده می‌شود؛ Failure بروز رفتار نادرست سیستم هنگام اجراست؛ و Incident رخدادی است که مشاهده یا گزارش می‌شود و ممکن است نیازمند بررسی باشد.

و یک نکته مهم‌تر:

نباید تصور کنیم همه‌ی منابع دقیقاً از این واژه‌ها با یک تعریف یکسان استفاده می‌کنند.

به همین دلیل، هنگام مطالعه منابع تخصصی بهتر است همیشه Context و منبع تعریف را در نظر بگیریم.

تعریف‌های رسمی؛ ISTQB درباره Error، Defect و Failure چه می‌گوید؟ 📚

تا اینجا مفاهیم را با روایت و مثال توضیح دادیم. حالا بهتر است یک قدم تخصصی‌تر شویم و ببینیم ISTQB، یکی از مهم‌ترین مراجع واژگان تست نرم‌افزار، این اصطلاحات را چگونه تعریف می‌کند.

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

Error از دید ISTQB چیست؟

در واژگان ISTQB، Error با Mistake به‌عنوان Synonym معرفی شده و به‌طور خلاصه به معنای یک اقدام انسانی است که نتیجه‌ی نادرست ایجاد می‌کند.

Error = Mistake = اشتباه انسانی

مثلاً Developer قرار است شرط زیر را پیاده‌سازی کند:

اگر سن کاربر ۱۸ سال یا بیشتر بود، اجازه ثبت‌نام بده.

اما هنگام نوشتن منطق، شرط را اشتباه متوجه می‌شود.

این اشتباه انسانی:

Error

است.

Defect از دید ISTQB چیست؟

در واژگان ISTQB، Defect به یک نقص یا اشکال در یک Component یا System اشاره دارد که می‌تواند باعث شود آن Component یا System نتواند عملکرد موردنیاز خود را انجام دهد. اگر یک Defect هنگام اجرا مورد مواجهه قرار بگیرد، ممکن است باعث Failure شود.

این قسمت یک نکته بسیار مهم را روشن می‌کند:

وجود Defect لزوماً به معنی وقوع Failure نیست.

بلکه:

Defect ممکن است در زمان Execution باعث Failure شود.

این همان تفاوتی است که در بخش‌های قبلی مقاله با مثال فروشگاه اینترنتی توضیح دادیم.

Bug از دید ISTQB

اینجا یک نکته جالب داریم.

در واژگان ISTQB، Bug نیز به‌عنوان اصطلاحی مرتبط با Defect مطرح می‌شود و در برخی نسخه‌های واژه‌نامه، برای Defect واژه‌هایی مانند Bug، Fault و Problem نیز به‌عنوان مترادف آمده‌اند.

بنابراین بهتر است در مقاله روی تفاوت مطلق میان:

Bug ≠ Defect ≠ Fault

تأکید نکنیم.

از نظر واژگان استاندارد ISTQB، این اصطلاحات در مواردی می‌توانند به‌عنوان مترادف برای اشاره به یک نقص استفاده شوند.

تفاوت‌هایی که در بخش‌های قبلی درباره آن‌ها صحبت کردیم بیشتر برای درک مفهومی و Contextهای مختلف مفید هستند، اما در منابع استاندارد باید تعریف همان منبع را ملاک قرار دهیم.

Failure از دید ISTQB چیست؟

در تعریف ISTQB، Failure رویدادی است که در آن یک Component یا System هنگام اجرا، در محدوده‌های مشخص‌شده، نیازمندی‌های خود را برآورده نمی‌کند.

این تعریف یک نکته بسیار مهم را روشن می‌کند:

Failure مربوط به زمان Execution است

یعنی:

Failure زمانی مطرح می‌شود که سیستم اجرا شده و رفتار واقعی آن با چیزی که باید انجام دهد مطابقت ندارد.

مثلاً:

Expected Result:

موجودی حساب = ۱۰ میلیون تومان

Actual Result:

موجودی حساب = ۸ میلیون تومان

اگر این رفتار ناشی از نقص سیستم باشد، با یک Failure مواجه هستیم.

حالا رابطه رسمی این سه مفهوم را ببینیم

با کنار هم گذاشتن تعاریف ISTQB می‌توانیم یک مدل ساده بسازیم:

👤 Human Action
       ↓
    ERROR
خطا / اشتباه
       ↓
    DEFECT
نقص / اشکال
       ↓
   Execution
اجرای سیستم
       ↓
   FAILURE
شکست / خرابی

اما یک نکته مهم:

این یک زنجیره احتمالی است، نه یک زنجیره اجباری.

یک Defect ممکن است هنگام اجرا باعث Failure شود؛ اما این اتفاق الزامی نیست.

بنابراین:

Defect → ممکن است → Failure

نه:

Defect → حتماً → Failure

Static Testing اینجا چه نقشی دارد؟

اینجا یکی از جالب‌ترین قسمت‌های بحث مشخص می‌شود.

Static Testing تستی است که بدون اجرای Test Item انجام می‌شود.

مثلاً:

  • Requirement Review
  • Design Review
  • Code Review
  • Static Analysis

در Static Testing می‌توانیم Defectها را بدون اجرای نرم‌افزار شناسایی کنیم.

اما در Dynamic Testing، نرم‌افزار را اجرا می‌کنیم و ممکن است یک Failure مشاهده شود؛ سپس با تحلیل آن Failure می‌توانیم Defect مربوطه را پیدا کنیم.

Static Testing

Work Product را بررسی می‌کنیم → Defect را شناسایی می‌کنیم

Dynamic Testing

سیستم را اجرا می‌کنیم → Failure مشاهده می‌شود → علت بررسی می‌شود → Defect پیدا می‌شود

پس آیا جمله‌ای که قبلاً گفتیم درست بود؟

در ابتدای مقاله گفتیم:

«اگر بتوانیم Error را با تست اثبات کنیم، آن را Defect می‌نامیم.»

اینجا بهتر است جمله را دقیق‌تر کنیم.

Error یک اقدام انسانی است که نتیجه‌ی نادرست ایجاد می‌کند. اگر این Error باعث ایجاد یک نقص در Work Product شود، با Defect مواجه می‌شویم. اگر Defect هنگام اجرای سیستم باعث شود سیستم نیازمندی خود را برآورده نکند، Failure رخ می‌دهد.

بنابراین Tester با پیدا کردن Error، آن را به Defect تبدیل نمی‌کند؛ بلکه ممکن است Error قبلاً باعث ایجاد Defect شده باشد و Tester آن Defect را کشف کند.

یک مثال دقیق با سه مفهوم

فرض کنیم Developer باید این شرط را بنویسد:

اگر موجودی >= 100 باشد
    اجازه خرید بده

اما اشتباهاً می‌نویسد:

اگر موجودی > 100 باشد
    اجازه خرید بده

Error

Developer هنگام پیاده‌سازی اشتباه کرده است.

Error

Defect

منطق نادرست وارد Code شده است.

Defect / Bug / Fault

Dynamic Testing

Tester موجودی را دقیقاً برابر ۱۰۰ قرار می‌دهد و خرید را امتحان می‌کند.

Failure

سیستم اجازه خرید نمی‌دهد، در حالی که باید اجازه بدهد.

Failure

یک نکته بسیار مهم درباره Static Testing

اینجا می‌توانیم صحبت قبلی درباره Static Defect را دقیق‌تر کنیم.

بهتر است نگوییم:

«این یک Static Defect است.»

بلکه بهتر است بگوییم:

«این Defect با Static Testing شناسایی شده است.»

چون Static در اینجا ویژگی روش Testing است، نه الزاماً نوع Defect.

سه قاعده طلایی 🧠

با توجه به تعریف‌های استاندارد، می‌توانیم سه جمله را به‌عنوان قواعد طلایی این بخش در نظر بگیریم:

🧠 Error = یک اقدام یا اشتباه انسانی که نتیجه نادرست ایجاد می‌کند.

🐞 Defect / Bug / Fault = اصطلاحاتی برای اشاره به یک نقص در Component، System یا Work Product که می‌تواند باعث عملکرد نادرست شود.

⚠️ Failure = زمانی که سیستم هنگام اجرا نیازمندی خود را برآورده نمی‌کند.

و رابطه کلی را می‌توان این‌گونه به خاطر سپرد:

Error
  ↓
Defect
  ↓
[Execution]
  ↓
Failure

اما دو فلش آخر اجباری نیستند.

در بخش بعدی، این مفاهیم را روی چرخه‌ی Requirement → Design → Coding → Testing → Production قرار می‌دهیم تا ببینیم در یک پروژه واقعی، Error، Defect و Failure دقیقاً در چه مرحله‌ای می‌توانند شکل بگیرند و چگونه می‌توان آن‌ها را زودتر شناسایی کرد.

Error، Defect و Failure در چرخه توسعه نرم‌افزار کجا اتفاق می‌افتند؟ 🔄

تا اینجا مفاهیم Error، Defect و Failure را جداگانه بررسی کردیم. حالا یک سؤال کاربردی مطرح می‌شود:

در یک پروژه واقعی، Error، Defect و Failure دقیقاً در چه مرحله‌ای اتفاق می‌افتند؟

برای پاسخ، مسیر یک Feature را از لحظه شکل‌گیری Requirement تا رسیدن آن به Production دنبال می‌کنیم.

از Requirement تا Production

فرض کنید قرار است قابلیت زیر به یک فروشگاه اینترنتی اضافه شود:

🎯 کاربر بتواند سفارش خود را قبل از ارسال لغو کند.

مسیر معمول این Feature را می‌توان به شکل زیر دید:

Requirement
     ↓
Analysis / Design
     ↓
Development
     ↓
Testing
     ↓
Release
     ↓
Production

در هر یک از این مراحل امکان ایجاد Error و در نتیجه Defect وجود دارد. Failure نیز معمولاً زمانی مطرح می‌شود که سیستم اجرا شده و رفتار واقعی آن با رفتار مورد انتظار مطابقت نداشته باشد.

۱. Requirement؛ جایی که اولین Error ممکن است اتفاق بیفتد 📝

فرض کنید قانون کسب‌وکار این است:

سفارش تا زمانی که ارسال نشده، قابل لغو است.

اما Business Analyst درک اشتباهی از این قانون پیدا می‌کند و Requirement را این‌گونه می‌نویسد:

سفارش فقط تا ۳۰ دقیقه بعد از ثبت قابل لغو است.

در اینجا یک Error (خطا / اشتباه) انسانی رخ داده است. اگر این اشتباه وارد Requirement رسمی شود، یک Defect (نقص / اشکال) در Requirement ایجاد شده است.

این Defect می‌تواند در همان مرحله با Requirement Review شناسایی شود؛ بدون اینکه Code نوشته یا نرم‌افزار اجرا شده باشد. این نمونه‌ای از Static Testing است.

۲. Design؛ Error می‌تواند دوباره اتفاق بیفتد 🎨

فرض کنیم Requirement کاملاً درست است، اما Software Architect هنگام طراحی سیستم تصمیم اشتباهی می‌گیرد.

مثلاً وضعیت سفارش فقط با دو حالت Pending و Completed طراحی می‌شود، در حالی که منطق لغو سفارش به وضعیت‌هایی مانند Pending، Confirmed، Shipped، Delivered و Cancelled نیاز دارد.

اگر این تصمیم اشتباه وارد Design شود، یک Defect در Design ایجاد شده است. این نقص نیز می‌تواند با Architecture Review یا Design Review قبل از Coding شناسایی شود.

۳. Coding؛ Error به Code راه پیدا می‌کند 💻

حالا فرض کنیم Requirement و Design درست هستند. Developer شروع به پیاده‌سازی می‌کند.

Requirement می‌گوید سفارش قبل از ارسال قابل لغو است، اما Developer به اشتباه فقط سفارش‌های Pending را قابل لغو در نظر می‌گیرد؛ در حالی که سفارش‌های Confirmed نیز باید قابل لغو باشند.

اینجا یک Error در هنگام Coding رخ داده و نتیجه آن یک Defect در Code است.

۴. Code Review؛ فرصت کشف Defect قبل از اجرا 🔍

قبل از ورود Code به محیط تست، Developer دیگری آن را Review می‌کند و متوجه می‌شود شرط لغو سفارش ناقص است.

Defect در همین مرحله پیدا می‌شود؛ بدون اینکه نرم‌افزار اجرا شده باشد یا Failure رخ داده باشد.

این یک نمونه از Static Testing است.

۵. Dynamic Testing؛ حالا نرم‌افزار را اجرا می‌کنیم ▶️

فرض کنیم Code Review نتوانسته این Defect را پیدا کند و نسخه وارد Test Environment می‌شود.

Tester سفارشی در وضعیت Confirmed قرار می‌دهد و تلاش می‌کند آن را لغو کند.

Expected Result: سفارش باید لغو شود.

Actual Result: سیستم اجازه لغو سفارش را نمی‌دهد.

در اینجا رفتار واقعی سیستم با رفتار مورد انتظار مطابقت ندارد و یک Failure (شکست / خرابی) مشاهده شده است.

۶. Incident؛ گزارش یک اتفاق غیرمنتظره 📋

فرض کنید Tester هنوز علت این رفتار را نمی‌داند و گزارش می‌کند:

هنگام تلاش برای لغو سفارش در وضعیت Confirmed، سیستم اجازه لغو نمی‌دهد.

این اتفاق می‌تواند به‌عنوان یک Incident (رخداد / رویداد) ثبت و بررسی شود. در این مرحله هنوز علت مشخص نیست و Investigation باید انجام شود.

ممکن است علت، یک Defect در Code باشد یا مشکل از Configuration، Environment، Server، Network یا حتی برداشت نادرست از Requirement باشد.

۷. Production؛ جایی که Failure به کاربر واقعی می‌رسد 🚨

حالا فرض کنید Tester سناریوی لغو سفارش در وضعیت Confirmed را بررسی نکرده باشد و نسخه وارد Production شود.

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

کاربر با یک Failure مواجه شده است. اگر این مشکل را به پشتیبانی گزارش کند، یک Incident در Production نیز شکل می‌گیرد.

پس یک Error می‌تواند چه مسیری طی کند؟

👤 Error
   ↓
🐞 Defect
   ↓
🔍 ممکن است با Static Testing پیدا شود
   ↓
❌ اگر پیدا نشود
   ↓
▶️ Dynamic Testing
   ↓
⚠️ Failure
   ↓
📋 Incident

اما این مسیر اجباری نیست. ممکن است Error قبل از ایجاد Defect اصلاح شود، Defect با Static Testing پیدا شود یا Defect وجود داشته باشد اما هیچ‌گاه شرایط لازم برای ایجاد Failure فراهم نشود.

Error فقط مربوط به Developer نیست 👥

Error یک مفهوم انسانی است و می‌تواند در هر مرحله و توسط هر نقش ایجاد شود.

  • Business Analyst: برداشت اشتباه از Requirement
  • Architect / Designer: انتخاب Design نامناسب
  • Developer: پیاده‌سازی اشتباه
  • Tester: طراحی اشتباه Test Case
  • DevOps Engineer: Configuration اشتباه

بنابراین Error محدود به یک نقش خاص در تیم نرم‌افزار نیست.

حتی Tester هم می‌تواند Error ایجاد کند 🧪

فرض کنید Requirement می‌گوید کاربر باید حداقل ۱۸ سال داشته باشد. Tester هنگام طراحی Test Case حالت ۱۷ سال → Reject را بررسی می‌کند، اما حالت مرزی ۱۸ سال → Accept را فراموش می‌کند.

این می‌تواند یک Error در طراحی تست باشد. اگر این اشتباه باعث شود یک Defect واقعی کشف نشود، آن Defect ممکن است به مراحل بعدی منتقل شود.

Testware هم می‌تواند Defect داشته باشد

Tester فقط با Code سروکار ندارد. مواردی مانند Test Case، Test Scenario، Test Data، Test Script، Test Plan و Test Report نیز Work Product محسوب می‌شوند.

بنابراین ممکن است خود Testware نیز دارای Defect باشد؛ مثلاً Test Case یک Expected Result اشتباه داشته باشد یا Test Data شرایط مهمی را پوشش ندهد.

به همین دلیل Review کردن Testware نیز اهمیت دارد.

چرا پیدا کردن Defect در مراحل اولیه مهم است؟ 💰

هرچه یک مشکل دیرتر کشف شود، معمولاً اصلاح و مدیریت آن پیچیده‌تر می‌شود.

  • 🟢 Requirement Review: اصلاح معمولاً ساده‌تر است.
  • 🟡 Design / Development: ممکن است تغییرات بیشتری لازم باشد.
  • 🟠 Test Environment: علاوه بر اصلاح، ممکن است Regression Testing لازم شود.
  • 🔴 Production: احتمال درگیری کاربران، Support، داده‌های نادرست، Hotfix و آسیب به اعتبار محصول بیشتر است.

این همان فلسفه‌ای است که پشت رویکردهایی مانند Shift Left قرار دارد:

هرچه زودتر مشکلات را پیدا کنیم، معمولاً مدیریت و اصلاح آن‌ها ساده‌تر و کم‌هزینه‌تر است.

آیا Production Failure همیشه نتیجه یک Coding Error است؟

خیر. ❌

یک Production Failure می‌تواند ناشی از موارد مختلفی باشد، از جمله:

  • Requirement Defect
  • Design Defect
  • Code Defect
  • Database Problem
  • Configuration Problem
  • Infrastructure Problem
  • Integration Problem
  • Environment Problem

بنابراین هنگام مشاهده یک Failure نباید بلافاصله نتیجه بگیریم که مشکل از Code یا Developer است. ابتدا باید Investigation انجام شود.

یک مثال از Failure بدون Code Defect ⚙️

فرض کنید Code کاملاً درست است، اما Production Configuration اشتباه تنظیم شده است:

Test Environment:
Payment URL = correct
Production:
Payment URL = wrong

کاربر روی پرداخت کلیک می‌کند و سیستم نمی‌تواند به Payment Service متصل شود. کاربر یک Failure مشاهده می‌کند، اما ممکن است هیچ Defectی در Source Code وجود نداشته باشد و مشکل از Configuration باشد.

یک مدل کامل‌تر برای درک مفاهیم 🧠

Requirements
     ↓
   Design
     ↓
 Development
     ↓
   Testing
     ↓
   Release
     ↓
 Production

در هر مرحله ممکن است فعالیت انسانی با یک Error همراه شود:

Human Activity
      ↓
    Error
      ↓
   Work Product
      ↓
   Defect

و هنگام اجرای سیستم:

Defect
   +
Activation Conditions
   +
Execution
   ↓
Failure

اگر یک رفتار غیرمنتظره مشاهده یا گزارش شود، ممکن است یک Incident ایجاد شود و Investigation برای مشخص کردن علت آغاز شود.

نکته طلایی این بخش ⭐

اگر در یک پروژه واقعی با یک مشکل مواجه شدی، فقط نپرس:

«Bug کجاست؟»

سؤال‌های دقیق‌تر این‌ها هستند:

  • چه رفتاری را مشاهده کردیم؟ → Failure؟
  • چه نقصی باعث این رفتار شده است؟ → Defect؟
  • این نقص در کدام Work Product ایجاد شده است؟ → Requirement، Design، Code یا Configuration؟
  • چه اشتباه انسانی باعث ایجاد آن شده است؟ → Error؟
  • آیا این مشکل قبلاً قابل پیشگیری یا کشف بوده است؟

این نوع نگاه کمک می‌کند Tester فقط یک Bug Finder نباشد و نقش فعال‌تری در Quality Engineering و پیشگیری از مشکلات داشته باشد. 🎯

Root Cause چیست و چه ارتباطی با Error و Defect دارد؟ 🧠

تا اینجا فهمیدیم که یک Error (خطا / اشتباه) می‌تواند باعث ایجاد Defect (نقص / اشکال) شود و Defect نیز در شرایط خاص ممکن است هنگام اجرای سیستم به Failure (شکست / خرابی) منجر شود.

اما حالا یک سؤال مهم‌تر داریم:

اصلاً چرا آن Defect به وجود آمد؟

اینجاست که مفهوم Root Cause یا علت ریشه‌ای وارد داستان می‌شود.

Root Cause یعنی چه؟

Root Cause را می‌توان به فارسی علت ریشه‌ای ترجمه کرد.

به زبان ساده، Root Cause به عاملی اشاره می‌کند که در پشت ایجاد یک مشکل قرار دارد و اگر آن عامل را شناسایی و برطرف کنیم، می‌توانیم احتمال تکرار مشکل را کاهش دهیم.

مثلاً فرض کنید:

سیستم در Production هنگام پرداخت Crash می‌کند.

این چیزی است که می‌بینیم.

اما سؤال مهم‌تر این است:

چرا Crash کرد؟

بررسی می‌کنیم و می‌بینیم:

یک مقدار null وارد بخشی از سیستم شده است.

باز هم می‌پرسیم:

چرا مقدار null وارد سیستم شد؟

مشخص می‌شود Requirement مشخص نکرده بود که این مقدار می‌تواند null باشد.

حالا ممکن است به یک Root Cause احتمالی برسیم:

Requirement ناقص یا مبهم بوده است.

Root Cause با Defect یکی نیست ❌

این تفاوت بسیار مهم است.

فرض کنید:

Code دارای یک شرط اشتباه است.

این:

🐞 Defect

است.

اما سؤال بعدی این است:

چرا Developer این شرط را اشتباه نوشته است؟

ممکن است پاسخ این باشد:

Requirement مبهم بوده است.

این می‌تواند یکی از علت‌های ریشه‌ای احتمالی باشد.

پس:

Defect خودِ نقص است؛ Root Cause علت یا مجموعه‌ای از علل پشت ایجاد آن نقص است.

یک مثال کامل 🛒

برگردیم به فروشگاه اینترنتی.

Requirement می‌گوید:

سفارش تا قبل از ارسال قابل لغو است.

Developer Code را بررسی می‌کند و اشتباهاً فقط سفارش‌های Pending را قابل لغو می‌کند.

آنچه کاربر می‌بیند

کاربر سفارش Confirmed را نمی‌تواند لغو کند.

⚠️ Failure

چیزی که در Code پیدا می‌کنیم

if order.status == "Pending":
    allow_cancel()

این:

🐞 Defect

است.

حالا سؤال بعدی

چرا Developer چنین شرطی نوشته است؟

بررسی می‌کنیم.

مشخص می‌شود Developer در جلسه Refinement تصور کرده:

فقط سفارش‌های Pending قابل لغو هستند.

چرا چنین برداشتی داشته؟

Requirement در این قسمت ابهام داشته است.

مثلاً:

«کاربر می‌تواند سفارش را در مراحل اولیه لغو کند.»

عبارت «مراحل اولیه» دقیق نیست.

بنابراین می‌توان گفت این ابهام یکی از علل احتمالی ایجاد Defect بوده است و برای تعیین Root Cause واقعی باید Investigation بیشتری انجام شود.

دو مسیر مهم را از هم جدا کنیم 🧩

برای اینکه Error، Defect، Failure و Root Cause را با یکدیگر اشتباه نگیریم، بهتر است دو مسیر متفاوت را در ذهن داشته باشیم.

مسیر ایجاد مشکل

👤 Error
   ↓
🐞 Defect
   ↓
▶️ Execution
   ↓
⚠️ Failure

در این مسیر، یک Error انسانی ممکن است باعث ایجاد Defect شود و Defect نیز در صورت فعال شدن شرایط لازم، هنگام Execution به Failure منجر شود.

مسیر تحلیل مشکل

⚠️ Failure
   ↓
🐞 Defect
   ↓
🧠 Root Cause
   ↓
🛡️ Prevention / Process Improvement

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

این تفکیک از حفظ کردن یک زنجیره ساده مثل Error → Defect → Failure → Root Cause دقیق‌تر است؛ چون Root Cause بخشی از مسیر تحلیل مشکل است، نه الزاماً مرحله بعدی Failure.

چرا پیدا کردن Root Cause مهم است؟

فرض کنید تیم فقط Failure را برطرف کند.

Developer Code را تغییر می‌دهد:

if order.status in ["Pending", "Confirmed"]:
    allow_cancel()

تست‌ها Pass می‌شوند.

همه خوشحال‌اند. 🎉

اما آیا مشکل واقعاً حل شده است؟

شاید نه.

اگر Requirement همچنان مبهم باشد، ممکن است چند ماه بعد همین مشکل یا مشکلی مشابه در بخش دیگری از سیستم دوباره ایجاد شود.

بنابراین:

Fix کردن Defect با برطرف کردن Root Cause همیشه یک چیز نیست.

Fix چیست؟

Fix یعنی اقدامی که برای برطرف کردن یک مشکل یا Defect انجام می‌دهیم.

مثلاً:

Code را اصلاح می‌کنیم.

این می‌تواند یک Fix باشد.

اما Root Cause ممکن است همچنان وجود داشته باشد.

Defect
   ↓
Code را اصلاح کردیم
   ↓
Fix

در مقابل:

Root Cause
   ↓
Requirement همچنان مبهم است
   ↓
مشکل مشابه ممکن است دوباره ایجاد شود

پس یک تیم حرفه‌ای فقط نمی‌پرسد:

«چطور این Bug را Fix کنیم؟»

بلکه می‌پرسد:

«چرا این Bug اصلاً ایجاد شد و چطور می‌توانیم احتمال تکرار آن را کاهش دهیم؟»

Root Cause Analysis چیست؟ 🔎

Root Cause Analysis (RCA) یعنی تحلیل علت ریشه‌ای.

RCA فرآیندی برای بررسی یک مشکل با هدف پیدا کردن علت یا علل بنیادی آن است.

هدف RCA فقط این نیست که بگوید:

«چه چیزی خراب شد؟»

بلکه می‌خواهد بفهمد:

«چرا این اتفاق افتاد؟»

و مهم‌تر:

«چطور می‌توانیم احتمال تکرار آن را کاهش دهیم؟»

یکی از روش‌های معروف: Five Whys

یکی از روش‌های ساده برای Root Cause Analysis، تکنیک 5 Whys است.

در این روش چند بار پشت سر هم سؤال می‌کنیم:

Why? چرا؟

هدف این است که از Symptom به سمت علت یا علل عمیق‌تر حرکت کنیم.

مثال

مشکل: کاربر نتوانست سفارش را پرداخت کند.

  • چرا؟ Payment API خطا داد.
  • چرا؟ درخواست شامل مقدار نامعتبر بود.
  • چرا؟ سیستم مقدار ورودی را Validate نکرد.
  • چرا؟ Validation در Design در نظر گرفته نشده بود.
  • چرا؟ Requirement مربوط به Validation مشخص نشده بود.

حالا به یک علت ریشه‌ای احتمالی نزدیک شده‌ایم:

Requirement ناقص بوده است.

آیا همیشه باید دقیقاً پنج بار Why بپرسیم؟

خیر. ❌

اسم تکنیک Five Whys است، اما عدد پنج قانون جادویی نیست.

ممکن است بعد از سه سؤال به علت مناسب برسیم یا برای یک مشکل پیچیده به بررسی بسیار بیشتری نیاز داشته باشیم.

بنابراین:

هدف رسیدن به علت مناسب و قابل اقدام است، نه اینکه حتماً پنج سؤال بپرسیم.

Root Cause همیشه یک Error انسانی نیست

این نکته بسیار مهم است.

Root Cause می‌تواند شامل موارد مختلفی باشد، از جمله:

  • Requirement ناقص
  • Requirement مبهم
  • فرآیند نامناسب
  • Design اشتباه
  • Configuration اشتباه
  • تست ناکافی
  • نبود Automation مناسب
  • مشکل معماری
  • محدودیت زیرساخت
  • ارتباط ضعیف بین تیم‌ها
  • داده نامناسب

بنابراین نباید در RCA سریعاً به این نتیجه برسیم:

«Developer اشتباه کرده.»

ممکن است Developer فقط آخرین حلقه زنجیره باشد و علت اصلی در Requirement، Design، فرآیند یا حتی محیط اجرا قرار داشته باشد.

یک مثال جالب: Bug در Production

فرض کنید یک Bug جدی در Production پیدا شده است.

تیم می‌گوید:

«Developer شرط را اشتباه نوشته.»

اما بررسی دقیق‌تر نشان می‌دهد:

Requirement
    ↓
ابهام
    ↓
Design
    ↓
تفسیر نادرست
    ↓
Development
    ↓
Defect
    ↓
Testing
    ↓
Test Case این سناریو را پوشش نداده
    ↓
Production
    ↓
Failure

پس شاید:

Developer فقط جایی بوده که Defect در آن ایجاد شده است.

اما علت یا علل ریشه‌ای می‌توانند در فرآیند Requirement، Design یا حتی فرآیند Testing قرار داشته باشند.

نقش Tester در Root Cause Analysis چیست؟

Tester می‌تواند نقش بسیار مهمی داشته باشد، اما یک نکته مهم وجود دارد:

Tester همیشه مسئول پیدا کردن Root Cause نیست.

در برخی تیم‌ها افراد مختلفی در RCA مشارکت می‌کنند، از جمله:

  • Developer
  • QA
  • Product
  • DevOps
  • SRE
  • Business Analyst

نقش Tester می‌تواند شامل این موارد باشد:

  • 🔍 جمع‌آوری شواهد
  • 🧪 بررسی شرایط بازتولید
  • 📋 بررسی Test Caseها
  • 📊 بررسی داده‌های تست
  • 📝 بررسی Requirement
  • 🔎 بررسی اینکه چرا Defect در مراحل قبلی کشف نشده است

یک سؤال حرفه‌ای‌تر برای Tester

فرض کنید یک Defect در Production پیدا شده است.

یک Tester تازه‌کار ممکن است بپرسد:

«چطور این Bug را تست کنیم؟»

اما یک Tester باتجربه‌تر ممکن است بپرسد:

«چرا این Bug قبل از Production پیدا نشد؟»

این سؤال می‌تواند به Process Improvement منجر شود.

  • Test Case وجود نداشته است.
  • Test Data مناسب نبوده است.
  • Requirement تست‌پذیر نبوده است.
  • Regression Test این بخش اجرا نشده است.
  • تست فقط در Happy Path انجام شده است.

Root Cause و Prevention 🛡️

هدف نهایی RCA فقط پیدا کردن مقصر نیست.

اتفاقاً یکی از بدترین رویکردها این است که RCA تبدیل شود به:

«چه کسی اشتباه کرد؟»

هدف بهتر این است:

«چه چیزی در سیستم، فرآیند یا محصول باعث شد این اشتباه بتواند به Defect و سپس Failure تبدیل شود؟»

مثلاً به جای:

❌ «Developer اشتباه کرد.»

بپرسیم:

«چه چیزی باعث شد این اشتباه وارد Production شود؟»

این تغییر نگاه بسیار مهم است.

از Bug Fix تا Quality Improvement 🚀

اینجا می‌توانیم چهار سطح مختلف را از هم جدا کنیم:

سطح اول — Symptom

سیستم Crash کرد.

⚠️ Failure

سطح دوم — Defect

یک Null Handling اشتباه وجود داشت.

🐞 Defect

سطح سوم — Root Cause

Requirement مشخص نکرده بود این مقدار می‌تواند Null باشد.

🧠 Root Cause احتمالی

سطح چهارم — Prevention

Requirement Template را تغییر می‌دهیم و برای فیلدهای Nullable صراحتاً Rule تعریف می‌کنیم.

🛡️ Prevention / Process Improvement

این سطح چهارم بسیار مهم است؛ چون هدف نهایی کیفیت فقط پیدا کردن Bug نیست.

بلکه:

کم کردن احتمال ایجاد Bugهای مشابه در آینده است.

چهار سؤال طلایی برای تحلیل یک Failure ⭐

وقتی در یک پروژه با Failure مواجه شدی، این چهار سؤال را از خودت بپرس:

  1. چه چیزی را مشاهده کردیم؟
    → Failure
  2. چه نقصی باعث آن شد؟
    → Defect
  3. چرا این Defect ایجاد شد؟
    → Root Cause
  4. چرا زودتر پیدا نشد و چگونه از تکرار آن جلوگیری کنیم؟
    → Process Improvement / Prevention

این چهار سؤال کمک می‌کنند نگاه ما از:

Bug Finding

به:

Quality Engineering

نزدیک‌تر شود. 🚀

جمع‌بندی

Error یک اشتباه یا اقدام انسانی است که می‌تواند به ایجاد Defect منجر شود.

Defect خودِ نقص موجود در یک Work Product، Component یا System است.

Failure رفتار نادرست سیستم هنگام اجراست که می‌تواند در نتیجه فعال شدن یک Defect رخ دهد.

Root Cause به علت یا علل بنیادی پشت ایجاد یک مشکل اشاره دارد و با خود Defect یکی نیست.

در نهایت، یک تیم حرفه‌ای فقط به Fix کردن Defect فکر نمی‌کند؛ بلکه تلاش می‌کند علت‌های ایجاد آن را بشناسد و با Prevention و Process Improvement احتمال تکرار مشکلات مشابه را کاهش دهد.

Failure، Error Message و Exception چه تفاوتی دارند؟ ⚠️

یکی از اشتباهات رایج در بین افراد تازه‌وارد به تست نرم‌افزار این است که این سه مفهوم را یکی در نظر می‌گیرند:

Failure = Error Message = Exception

در حالی که این‌ها سه مفهوم متفاوت هستند.

ممکن است یک Failure داشته باشیم بدون اینکه هیچ Error Messageای نمایش داده شود.

ممکن است یک Exception رخ دهد اما کاربر هیچ Failureای مشاهده نکند.

و حتی ممکن است یک Error Message نمایش داده شود در حالی که سیستم دقیقاً همان رفتاری را انجام داده که Requirement مشخص کرده است.

پس بیایید این سه مفهوم را با یک داستان ساده از هم جدا کنیم.

اول از همه: Failure چیست؟

همان‌طور که در بخش‌های قبلی گفتیم:

Failure زمانی رخ می‌دهد که سیستم هنگام اجرا نتواند رفتار مورد انتظار را ارائه دهد.

مثلاً Requirement می‌گوید:

وقتی کاربر رمز عبور اشتباه وارد کرد، پیام مناسب نمایش داده شود.

Tester رمز اشتباه وارد می‌کند.

Expected:

«رمز عبور اشتباه است.»

Actual:

صفحه کاملاً سفید می‌شود.

اینجا:

⚠️ Failure

داریم.

اما دقت کنید:

هیچ Error Messageای نمایش داده نشده است.

پس:

Failure ≠ Error Message

Error Message چیست؟ 💬

Error Message همان پیامی است که سیستم برای اطلاع‌رسانی درباره یک وضعیت خطا یا مشکل به کاربر یا سیستم دیگر نمایش یا ارسال می‌کند.

مثلاً:

  • ❌ Invalid username or password
  • ❌ Payment failed
  • ❌ File not found

یا در API:

{
  "error": "Invalid token"
}

این‌ها Error Message هستند.

اما وجود Error Message به‌تنهایی به این معنی نیست که سیستم Defect دارد.

یک مثال مهم

فرض کنید کاربر رمز اشتباه وارد می‌کند.

Requirement می‌گوید:

در صورت اشتباه بودن رمز، پیام Invalid password نمایش داده شود.

سیستم دقیقاً همین پیام را نشان می‌دهد.

آیا Failure داریم؟

❌ خیر.

چون سیستم دقیقاً طبق Requirement رفتار کرده است.

اما روی صفحه یک:

Error Message

می‌بینیم.

پس:

هر Error Message الزاماً Failure نیست.

Exception چیست؟ 💻

Exception بیشتر یک مفهوم در سطح اجرای برنامه و Runtime است.

در بسیاری از زبان‌های برنامه‌نویسی، Exception مکانیزمی است که برای نشان دادن یک وضعیت غیرعادی در زمان اجرای برنامه استفاده می‌شود.

مثلاً:

NullPointerException
IndexOutOfBoundsException
FileNotFoundException

این‌ها Exception هستند.

اما نکته مهم:

Exception خودش لزوماً معادل Failure نیست.

چطور ممکن است Exception داشته باشیم ولی Failure نداشته باشیم؟

فرض کنید برنامه هنگام پردازش یک ورودی، Exception ایجاد می‌کند.

try:
    process_payment()
except PaymentException:
    show_payment_failed_message()

در اینجا ممکن است Exception در داخل سیستم رخ داده باشد، اما برنامه آن را به‌درستی مدیریت کرده باشد.

اگر Requirement می‌گوید:

در صورت عدم موفقیت پرداخت، پیام مناسب نمایش داده شود.

و سیستم دقیقاً همین کار را انجام می‌دهد، ممکن است از دید کاربر Failure نداشته باشیم.

البته این موضوع به Context و رفتار مورد انتظار سیستم بستگی دارد.

یک مثال برعکس

فرض کنیم سیستم هنگام پرداخت Exception ایجاد می‌کند:

PaymentException

اما Exception به‌درستی مدیریت نمی‌شود.

در نتیجه:

برنامه Crash می‌کند.

کاربر صفحه خطا می‌بیند.

اینجا:

Exception

⬇️

رفتار غیرمنتظره

⬇️

Failure

بنابراین یک Exception می‌تواند علت یا بخشی از مسیر ایجاد Failure باشد، اما خود Exception را نباید همیشه با Failure یکی بدانیم.

یک مثال از فروشگاه اینترنتی 🛒

حالت اول

موجودی محصول صفر است.

سیستم پیام می‌دهد:

❌ این محصول موجود نیست.

Requirement نیز دقیقاً همین رفتار را مشخص کرده است.

پس:

  • Error Message:
  • Failure:

چون سیستم درست کار کرده است.

حالت دوم

موجودی صفر است.

سیستم به جای پیام مناسب، صفحه را Crash می‌کند.

اینجا:

  • Failure:
  • Exception: ممکن است وجود داشته باشد. ✅

حالت سوم

موجودی صفر است.

Backend یک Exception ایجاد می‌کند.

اما سیستم آن را مدیریت می‌کند و پیام مناسب نمایش می‌دهد.

ممکن است:

  • Exception:
  • Failure:

یک مدل ساده برای تفکیک این سه مفهوم

Exception
   │
   │ ممکن است مدیریت شود
   ▼
Application Behavior
   │
   ├── رفتار مطابق Requirement
   │       ↓
   │    No Failure
   │
   └── رفتار برخلاف Requirement
           ↓
        Failure
Error Message
      │
      ├── ممکن است کاملاً مورد انتظار باشد
      │
      └── ممکن است بخشی از Failure باشد

بنابراین هیچ‌کدام از این روابط را نباید به شکل:

Error Message = Failure = Exception

در نظر گرفت.

Error Message با Error هم یکی نیست

این هم یک اشتباه رایج دیگر است. ⚠️

Error در بحث قبلی ما یعنی:

اشتباه انسانی

اما:

Error Message

یعنی:

پیامی که سیستم برای اعلام یک وضعیت یا خطا نمایش می‌دهد.

پس این دو کلمه با وجود شباهت ظاهری، در این Context یکی نیستند.

مثلاً:

  • Developer یک اشتباه می‌کند → Error
  • سیستم بعداً پیام Invalid input را نشان می‌دهد → Error Message

این دو مفهوم کاملاً متفاوت هستند.

جدول مقایسه‌ای

مفهوم معنی ساده زمان / Context مثال
Error خطا / اشتباه انسانی هنگام فعالیت انسان Developer منطق را اشتباه می‌نویسد
Error Message پیام اعلام وضعیت خطا معمولاً هنگام تعامل با سیستم Invalid password
Exception وضعیت استثنایی در اجرای برنامه Runtime NullPointerException
Failure عدم برآورده شدن رفتار مورد انتظار هنگام اجرای سیستم سیستم به جای پرداخت، Crash می‌کند

یک نکته بسیار مهم برای تست API 🔌

در API Testing این تفاوت‌ها حتی مهم‌تر می‌شوند.

فرض کنید API زیر را داریم:

POST /login

کاربر Password اشتباه ارسال می‌کند.

API پاسخ می‌دهد:

HTTP 401 Unauthorized

آیا این Failure است؟

نه لزوماً.

اگر Requirement می‌گوید:

برای Credentials نامعتبر باید HTTP 401 برگردد.

آنگاه:

401 = رفتار صحیح سیستم

و Failure نداریم.

اما اگر Requirement می‌گوید:

باید HTTP 401 برگردد.

و API:

HTTP 500

برگرداند، آنگاه:

⚠️ Failure

داریم.

این نکته در Automation Testing هم بسیار مهم است 🤖

فرض کنید در یک Test Automation Script نوشته‌ایم:

assert response.status_code == 200

اما API برای یک درخواست نامعتبر:

400

برمی‌گرداند.

Test Fail می‌شود.

آیا حتماً Application Failure داشته‌ایم؟

❌ نه.

ممکن است:

Test خودش اشتباه طراحی شده باشد.

یعنی:

  • Test Error
  • یا Defect در Testware

داشته باشیم.

این مثال نشان می‌دهد حتی یک:

Failed Test

هم لزوماً به معنی:

Failure در Application

نیست.

این موضوع برای یک Tester بسیار مهم است.

پس وقتی یک Test Fail شد چه کنیم؟

به‌جای اینکه بلافاصله بگوییم:

«Bug پیدا کردم! 🐞»

بهتر است بگوییم:

«Test مورد انتظار را برآورده نکرد؛ حالا باید علت را بررسی کنیم.»

ممکن است:

حالت ۱

Application Defect باشد.

حالت ۲

Test Case اشتباه باشد.

حالت ۳

Test Data اشتباه باشد.

حالت ۴

Environment مشکل داشته باشد.

حالت ۵

Configuration اشتباه باشد.

حالت ۶

Requirement اشتباه یا مبهم باشد.

Failed Test یک سیگنال برای Investigation است، نه اثبات قطعی Bug.

جمع‌بندی این بخش ⭐

سه مفهوم را این‌طور در ذهن نگه دار:

Error Message 💬

سیستم چه پیامی نشان می‌دهد؟

Exception 💻

در Runtime چه وضعیت استثنایی در برنامه رخ داده است؟

Failure ⚠️

آیا رفتار واقعی سیستم با رفتار مورد انتظار تفاوت دارد؟

و مهم‌تر از همه:

  • هر Error Message یک Failure نیست.
  • هر Exception یک Failure نیست.
  • هر Failed Test هم الزاماً به معنی Defect در Application نیست.

این تفکیک‌ها در تست API، Automation، UI و حتی Performance Testing بسیار کاربردی هستند و کمک می‌کنند Tester به جای واکنش سریع به یک علامت، ابتدا علت واقعی مشکل را پیدا کند.

در بخش بعدی می‌توانیم این مفاهیم را در یک مدل یکپارچه کنار Error، Defect، Bug، Fault، Failure، Incident و Root Cause قرار دهیم تا تمام واژگان اصلی مقاله در یک تصویر ذهنی واحد جمع شوند.

تفاوت Defect، Issue، Problem و Incident چیست؟ 📋

حالا که تفاوت Error، Defect، Bug، Fault و Failure را می‌دانیم، یک ابهام دیگر در محیط واقعی پروژه‌ها زیاد دیده می‌شود:

اگر در Jira یا ابزار مدیریت پروژه چیزی به نام Issue ثبت کنیم، آیا آن Issue همان Bug یا Defect است؟

و اگر یک مشکل در Production گزارش شود، آیا حتماً باید آن را Incident بنامیم؟

پاسخ کوتاه:

خیر. این واژه‌ها در همه Contextها مترادف نیستند.

بیایید با یک مثال شروع کنیم.

Issue چیست؟ 📝

Issue در بسیاری از ابزارهای مدیریت پروژه، مخصوصاً ابزارهایی مانند Jira، یک اصطلاح عمومی برای ثبت و پیگیری یک مورد است.

یعنی Issue می‌تواند شامل موارد مختلفی باشد:

  • 🐞 Bug
  • 🛠️ Task
  • ✨ Feature
  • 🔧 Improvement
  • 📋 Story
  • ⚠️ Problem

بنابراین:

هر Bug می‌تواند به‌عنوان یک Issue ثبت شود، اما هر Issue الزاماً Bug نیست.

یک مثال ساده در Jira

فرض کنید در Jira یک مورد جدید ایجاد می‌کنیم:

Issue: Add dark mode

این یک Bug نیست.

یک Feature یا Task است.

حالا Issue دیگری ایجاد می‌کنیم:

Issue: Login button does not work

این احتمالاً یک:

Bug / Defect

است.

پس کلمه‌ی Issue بیشتر به «موردی که باید پیگیری شود» اشاره می‌کند، نه به نوع خاصی از مشکل.

آیا Issue یک اصطلاح تست نرم‌افزار است؟

باید بین اصطلاح عمومی مدیریت کار و اصطلاح تخصصی Testing تفاوت بگذاریم.

در محیط‌های کاری، Issue معمولاً یک اصطلاح بسیار عمومی است.

مثلاً تیم ممکن است بگوید:

«یک Issue برای این موضوع باز کن.»

این جمله لزوماً به این معنا نیست که:

«یک Defect ثبت کن.»

ممکن است منظورشان هر نوع Work Item قابل پیگیری باشد.

بنابراین در مقاله بهتر است بگوییم:

Issue یک اصطلاح عمومی برای یک مورد قابل پیگیری است و معنای دقیق آن به ابزار و فرآیند سازمان بستگی دارد.

Problem چیست؟ 🔎

Problem یا «مشکل» معمولاً مفهوم گسترده‌تری دارد.

در محیط IT، Problem می‌تواند به وضعیتی اشاره کند که:

یک یا چند Incident ایجاد کرده یا پتانسیل ایجاد Incident را دارد و نیازمند بررسی علت و جلوگیری از تکرار است.

اینجا یک تفاوت مهم با Incident داریم.

Incident

چه اتفاقی افتاد؟

Problem

چه چیزی پشت این اتفاق‌ها قرار دارد؟

یک مثال واقعی از Production 🚨

فرض کنید کاربران فروشگاه اینترنتی مرتباً گزارش می‌دهند:

«پرداخت بعضی سفارش‌ها ناموفق است.»

هر گزارش کاربر می‌تواند یک:

Incident

باشد.

Incident #1
پرداخت سفارش 125 ناموفق شد.
Incident #2
پرداخت سفارش 231 ناموفق شد.
Incident #3
پرداخت سفارش 412 ناموفق شد.

تیم متوجه می‌شود که این‌ها احتمالاً اتفاقات جداگانه‌ای نیستند.

Investigation انجام می‌شود و مشخص می‌شود:

سرویس Payment Gateway در شرایط خاص Timeout می‌کند.

حالا تیم باید علت اصلی را بررسی کند.

این موضوع می‌تواند به یک:

Problem

تبدیل شود.

پس Incident و Problem چه تفاوتی دارند؟

خیلی ساده:

Incident بیشتر روی یک رخداد یا اختلال مشخص تمرکز دارد.

Problem بیشتر روی علت یا وضعیت بنیادی پشت یک یا چند Incident تمرکز دارد.

Incident
پرداخت ناموفق شد
       ↓
Incident
پرداخت دیگری ناموفق شد
       ↓
Incident
پرداخت دیگری هم ناموفق شد
       ↓
       🔎
Problem
مشکل Timeout در Payment Service

Incident الزاماً Defect نیست

این نکته بسیار مهم است. ⚠️

فرض کنید کاربر گزارش می‌کند:

«دکمه پرداخت کار نمی‌کند.»

این یک Incident است.

اما هنوز نمی‌دانیم علت چیست.

  • Defect در Code باشد.
  • Server Down باشد.
  • Network مشکل داشته باشد.
  • Configuration اشتباه باشد.
  • سرویس خارجی در دسترس نباشد.
  • داده نامعتبر باشد.
  • یا حتی کاربر انتظار اشتباهی داشته باشد.

بنابراین:

Incident نقطه شروع Investigation است، نه لزوماً نتیجه Investigation.

Incident و Failure چه تفاوتی دارند؟

این دو اصطلاح خیلی به هم نزدیک می‌شوند، اما یکی نیستند.

Failure

تمرکز روی این است که:

سیستم هنگام اجرا رفتار مورد انتظار را انجام نداده است.

Incident

تمرکز روی این است که:

یک اتفاق یا وضعیت غیرمنتظره مشاهده یا گزارش شده و نیاز به بررسی دارد.

مثال

سیستم باید بعد از پرداخت موفق:

صفحه Confirmation

را نمایش دهد.

پرداخت موفق شده، اما صفحه Confirmation نمایش داده نمی‌شود.

اینجا:

⚠️ Failure

داریم.

کاربر این اتفاق را به Support گزارش می‌کند:

📋 Incident

داریم.

Failure
   ↓
گزارش توسط کاربر
   ↓
Incident

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

حالا Defect کجای این داستان قرار می‌گیرد؟ 🐞

فرض کنیم Investigation انجام می‌شود.

مشخص می‌شود علت Failure این است:

Developer در Code شرط اشتباهی نوشته است.

این:

Defect

است.

پس یک مسیر ممکن می‌تواند این باشد:

Defect
   ↓
Execution
   ↓
Failure
   ↓
Incident
   ↓
Investigation
   ↓
Root Cause Analysis

اما باز هم تأکید می‌کنیم:

این یک مسیر ممکن است، نه یک زنجیره اجباری.

یک مثال کامل از فروشگاه اینترنتی 🛒

فرض کنید مشتری سفارش خود را پرداخت کرده است.

اما مبلغ از حساب او کم شده و سفارش در سیستم ثبت نشده است.

چیزی که مشتری تجربه می‌کند

«پول از حسابم کم شد ولی سفارش ثبت نشد.»

📋 Incident

بررسی سیستم

مشخص می‌شود Payment Gateway پاسخ موفق داده، اما Order Service پاسخ را به‌درستی پردازش نکرده است.

ممکن است یک:

🐞 Defect

وجود داشته باشد.

اجرای سناریو

وقتی این شرایط تکرار می‌شود:

Payment = Success
Order = Not Created

رفتار واقعی سیستم با رفتار مورد انتظار تفاوت دارد.

⚠️ Failure

بررسی بیشتر

مشخص می‌شود:

یک Timeout باعث شده Transaction به شکل ناقص مدیریت شود.

این می‌تواند بخشی از:

Root Cause Analysis

باشد.

بررسی گسترده‌تر

تیم متوجه می‌شود همین مشکل قبلاً برای ۳۰ سفارش دیگر هم اتفاق افتاده است.

حالا موضوع فقط یک Incident نیست.

تیم باید یک Problem را مدیریت کند و علت ریشه‌ای و راهکار جلوگیری از تکرار را پیدا کند.

تفاوت این چهار مفهوم در یک جدول

مفهوم ترجمه پیشنهادی سؤال اصلی
Defect نقص / اشکال چه نقصی در Work Product وجود دارد؟
Issue مورد / مسئله قابل پیگیری چه چیزی را باید ثبت و پیگیری کنیم؟
Incident رخداد / رویداد چه اتفاق غیرمنتظره‌ای رخ داده یا گزارش شده است؟
Problem مشکل چه علت یا وضعیت بنیادی پشت Incidentها قرار دارد؟

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

در فارسی این چهار کلمه گاهی همه با کلماتی مثل:

مشکل، ایراد، مسئله، خطا

ترجمه می‌شوند.

و همین باعث سردرگمی می‌شود.

برای همین در یک مقاله تخصصی بهتر است اصطلاح انگلیسی را کنار معادل فارسی بیاوریم:

  • Defect — نقص / اشکال
  • Issue — مورد قابل پیگیری / مسئله
  • Incident — رخداد
  • Problem — مشکل

این کار مخصوصاً برای مخاطبی که بعداً وارد محیط واقعی QA می‌شود بسیار مفید است.

یک نکته مهم درباره Bug Report 🐞

حالا متوجه می‌شویم چرا در محیط کاری ممکن است بشنویم:

«برای این Issue یک Bug Report بساز.»

یا:

«این Issue را به تیم Development Assign کن.»

یا:

«این Incident را به Problem تبدیل کنیم.»

این جملات ممکن است در سازمان‌های مختلف معانی و Workflowهای متفاوتی داشته باشند.

بنابراین نباید فقط از روی اسم یک Ticket نتیجه بگیریم که:

Issue = Bug

یا:

Incident = Defect

بلکه باید ببینیم فرآیند سازمان و ابزار دقیقاً چه تعریفی برای آن اصطلاح دارد.

یک اشتباه رایج ❌

فرض کنید در Jira یک Ticket داریم:

Issue #4521 — Payment failed

یک Tester تازه‌کار ممکن است بگوید:

«این Issue یک Defect است.»

اما هنوز Investigation انجام نشده است.

ممکن است واقعاً Defect باشد.

ولی ممکن است:

  • Payment Gateway Down بوده باشد.
  • Configuration اشتباه باشد.
  • Network قطع شده باشد.
  • Test Data مشکل داشته باشد.

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

یک Issue/Incident برای بررسی داریم.

و بعد از Investigation مشخص کنیم:

Root Cause و Defect چیست.

نکته طلایی این بخش ⭐

این چهار سؤال را در ذهن داشته باشید:

🐞 Defect:
چه نقصی در محصول یا Work Product وجود دارد؟

📋 Issue:
چه موردی را باید ثبت و پیگیری کنیم؟

🚨 Incident:
چه اتفاق غیرمنتظره‌ای مشاهده یا گزارش شده است؟

🔎 Problem:
چه وضعیت یا علت بنیادی پشت یک یا چند Incident قرار دارد؟

و مهم‌تر:

هر Bug می‌تواند یک Issue باشد، اما هر Issue Bug نیست.

هر Incident الزاماً Defect نیست.

هر Failure الزاماً به معنای یک Defect در Source Code نیست.

این تفکیک‌ها وقتی وارد محیط واقعی QA، Jira، Bug Tracking و Production Support شوید، بسیار کاربردی خواهند بود.

آیا هر Error به Defect و هر Defect به Failure تبدیل می‌شود؟ 🔗

تا اینجا یک زنجیره نسبتاً ساده در ذهنمان ساخته‌ایم:

Error → Defect → Failure

اما اگر همین زنجیره را بدون توضیح بیشتر حفظ کنیم، ممکن است یک برداشت اشتباه ایجاد شود:

«پس هر Error حتماً یک Defect می‌سازد و هر Defect هم حتماً یک Failure ایجاد می‌کند.»

نه. ❌

واقعیت کمی جالب‌تر است.

اول یک نکته مهم: این‌ها رابطه یک‌به‌یک ندارند

در یک پروژه واقعی، رابطه بین این مفاهیم معمولاً این‌گونه نیست:

Error
  ↓
یک Defect
  ↓
یک Failure

بلکه ممکن است:

یک Error
   ↓
چند Defect

یا:

چند Error
   ↓
یک Defect

و حتی:

Defect
   ↓
هیچ Failure
Defect
   ↓
یک Failure
Defect
   ↓
چندین Failure

پس بهتر است این مفاهیم را رابطه علت و معلولی احتمالی ببینیم، نه یک زنجیره مکانیکی.

آیا هر Error باعث Defect می‌شود؟

خیر. ❌

فرض کنید Developer هنگام نوشتن Code یک اشتباه تایپی انجام می‌دهد:

total = price * quantitty

IDE بلافاصله خطا را نشان می‌دهد.

Developer آن را اصلاح می‌کند.

اینجا:

👤 Error اتفاق افتاده است.

اما:

🐞 Defect ماندگاری ایجاد نشده است.

چرا؟

چون اشتباه قبل از اینکه وارد Work Product نهایی شود، شناسایی و اصلاح شده است.

پس چه زمانی Error به Defect منجر می‌شود؟

وقتی Error باعث شود یک نقص وارد یک Work Product شود و آن نقص باقی بماند.

مثلاً:

Developer تصور می‌کند:

«مالیات همیشه ۱۰٪ است.»

و Code را این‌گونه می‌نویسد:

tax = price * 0.10

اما Business Rule می‌گوید:

مالیات بر اساس نوع محصول متفاوت است.

اشتباه Developer یا برداشت نادرست از Requirement باعث ایجاد:

🐞 Defect

در Code شده است.

حالا آیا هر Defect باعث Failure می‌شود؟

باز هم:

خیر. ❌

این یکی از مهم‌ترین نکات مقاله است.

فرض کنید در یک نرم‌افزار، یک Defect وجود دارد.

اما برای فعال شدن آن Defect شرایط خاصی لازم است.

Defect
   ↓
فقط زمانی فعال می‌شود که:
Country = X
AND
Payment = Y
AND
Amount > Z

اگر این شرایط هیچ‌وقت اتفاق نیفتد:

Defect وجود دارد.

اما:

Failure مشاهده نمی‌شود.

یک مثال ساده

فرض کنید در Code یک اشتباه وجود دارد:

if age > 18:
    allow()

در حالی که Requirement می‌گوید:

if age >= 18:
    allow()

این:

🐞 Defect

است.

اما اگر هیچ کاربری با سن دقیقاً ۱۸ سال وارد سیستم نشود، ممکن است این Defect هیچ‌وقت خودش را به شکل Failure نشان ندهد.

یعنی:

Defect = وجود دارد
Failure = هنوز رخ نداده

Activation Condition چیست؟ 🔓

برای اینکه یک Defect به Failure منجر شود، معمولاً باید شرایطی فراهم شود که آن Defect فعال شود.

به این شرایط می‌توان گفت:

Activation Conditions

یعنی شرایط فعال شدن نقص.

Defect
   +
Specific Input
   +
Specific State
   +
Execution
   ↓
Failure

این مفهوم در تست بسیار مهم است.

چون Tester دقیقاً با طراحی Test Caseهای مناسب تلاش می‌کند شرایطی را ایجاد کند که Defectهای پنهان فعال شوند.

اینجا نقش Test Design مشخص می‌شود 🎯

فرض کنیم Defect زیر وجود دارد:

سیستم در مبلغ دقیقاً ۱۰۰۰ دلار دچار محاسبه اشتباه می‌شود.

اگر Tester فقط این موارد را تست کند:

  • 100 دلار
  • 500 دلار
  • 1500 دلار

ممکن است Failure را نبیند.

اما اگر Test Case زیر را اجرا کند:

Amount = 1000

Defect فعال می‌شود.

و:

⚠️ Failure مشاهده می‌شود.

بنابراین یکی از ارزش‌های Testing این است که:

شرایطی را ایجاد کنیم که Defectهای موجود خودشان را نشان دهند.

یک Defect می‌تواند چند Failure ایجاد کند

فرض کنید در منطق محاسبه تخفیف یک Defect وجود دارد.

این Defect می‌تواند روی چند بخش اثر بگذارد:

       Defect
          ↓
 ┌────────┼────────┐
 ↓        ↓        ↓
Cart    Invoice   Payment
 ↓        ↓        ↓
Failure Failure  Failure

یعنی یک Defect می‌تواند در شرایط مختلف باعث چند Failure متفاوت شود.

مثلاً:

  • مبلغ سبد خرید اشتباه شود.
  • فاکتور اشتباه تولید شود.
  • مبلغ پرداخت اشتباه ارسال شود.

برعکس آن هم ممکن است

چند Defect مختلف می‌توانند باعث یک Failure مشابه شوند.

Defect A ──┐
           │
Defect B ──┼──→ Failure
           │
Defect C ──┘

مثلاً:

صفحه پرداخت باز نمی‌شود.

ممکن است علت آن:

  • Defect در Frontend باشد.
  • Defect در API باشد.
  • Defect در Authentication باشد.
  • Configuration اشتباه باشد.

پس از روی Failure به‌تنهایی نمی‌توانیم فوراً بگوییم:

«این دقیقاً همان Bug است.»

باید Investigation انجام دهیم.

آیا ممکن است Error داشته باشیم ولی Defect نداشته باشیم؟

بله. ✅

مثلاً:

Developer یک شرط را اشتباه می‌نویسد، اما قبل از Commit متوجه اشتباه خود می‌شود و آن را اصلاح می‌کند.

Error
 ↓
Detected
 ↓
Corrected
 ↓
No lasting Defect

این دقیقاً نشان می‌دهد چرا Review، Pair Programming، Static Analysis و Testing زودهنگام اهمیت دارند.

آیا ممکن است Defect داشته باشیم ولی هیچ‌وقت Failure نبینیم؟

بله. ✅

این همان چیزی است که درباره Defect پنهان گفتیم.

مثلاً:

یک Feature تقریباً هیچ‌وقت استفاده نمی‌شود.

داخل آن Feature یک Defect وجود دارد.

اما چون شرایط فعال شدن آن هرگز اتفاق نمی‌افتد:

Failure مشاهده نمی‌شود.

حتی ممکن است نرم‌افزار سال‌ها در Production کار کند و آن Defect هرگز خودش را نشان ندهد.

آیا ممکن است Failure داشته باشیم ولی Defect نداشته باشیم؟

این سؤال بسیار مهم است.

بله، بسته به تعریف و Context.

مثلاً:

Server به دلیل قطع برق خاموش شده است.

کاربر نمی‌تواند سرویس را استفاده کند.

این یک:

⚠️ Failure در سرویس

محسوب می‌شود.

اما الزاماً:

🐞 Defect در Software

وجود ندارد.

ممکن است علت:

  • Infrastructure Failure
  • Network Failure
  • External Service Failure

باشد.

بنابراین:

Failure همیشه مساوی با Software Defect نیست.

یک مثال مهم از سرویس خارجی 🌐

فرض کنید اپلیکیشن شما برای پرداخت به یک Payment Gateway خارجی متصل است.

Code شما کاملاً درست است.

اما سرویس خارجی Down می‌شود.

کاربر روی پرداخت کلیک می‌کند.

پرداخت انجام نمی‌شود.

از دید کاربر:

⚠️ Failure

رخ داده است.

اما ممکن است:

🐞 هیچ Defectی در Code شما وجود نداشته باشد.

این تفاوت در سیستم‌های مدرن که از:

  • Microservices
  • APIs
  • Cloud Services
  • Third-Party Services

استفاده می‌کنند بسیار مهم است.

حالا Error، Defect و Failure را مثل یک داستان ببینیم 📖

فرض کنیم یک Developer یک Requirement را اشتباه متوجه می‌شود.

مرحله اول

👤 Error

«فکر کردم فقط سفارش‌های Pending قابل لغو هستند.»

مرحله دوم

این برداشت وارد Code می‌شود.

🐞 Defect

فقط Pending قابل Cancel است.

مرحله سوم

Tester فقط سفارش Pending را تست می‌کند.

Defect فعال نمی‌شود.

پس:

Failure نداریم.

مرحله چهارم

کاربر Production یک سفارش Confirmed را لغو می‌کند.

Defect فعال می‌شود.

⚠️ Failure

مرحله پنجم

کاربر مشکل را گزارش می‌کند.

📋 Incident

مرحله ششم

تیم Investigation انجام می‌دهد.

🔎 Root Cause Analysis

و متوجه می‌شود:

Requirement مبهم بوده و Test Case هم شرایط Confirmed را پوشش نداده است.

حالا می‌توانیم علاوه بر Fix کردن Defect، فرآیند را هم بهبود دهیم.

این چرخه را به خاطر بسپار 🧠

        HUMAN
          │
          ▼
       ERROR
    خطا / اشتباه
          │
          ▼
       DEFECT
     نقص / اشکال
          │
          │ اگر فعال شود
          ▼
      EXECUTION
          │
          ▼
      FAILURE
     شکست / خرابی
          │
          ▼
      INCIDENT
       رخداد
          │
          ▼
   INVESTIGATION
          │
          ▼
    ROOT CAUSE
     علت ریشه‌ای

اما دقت کن:

این نمودار یک مدل آموزشی است، نه یک قانون قطعی که همه مشکلات نرم‌افزار دقیقاً طبق آن پیش بروند.

یک نکته بسیار مهم برای Tester ⭐

وقتی یک Failure مشاهده می‌کنی، به جای اینکه فوراً بگویی:

🐞 «Bug پیدا کردم!»

بهتر است چند سؤال پشت سر هم بپرسی:

  1. رفتار مورد انتظار چه بوده؟
  2. رفتار واقعی چه بوده؟
  3. آیا واقعاً Failure رخ داده؟
  4. علت این Failure چیست؟
  5. آیا Defectی وجود دارد؟
  6. این Defect در کدام Work Product قرار دارد؟
  7. چرا این Defect زودتر پیدا نشده؟
  8. چگونه از تکرار آن جلوگیری کنیم؟

این نوع تفکر باعث می‌شود Testing از یک فعالیت ساده برای:

«پیدا کردن Bug»

به یک فعالیت حرفه‌ای برای:

«کشف ریسک، تحلیل مشکل و بهبود کیفیت» 🚀

جمع‌بندی کوتاه

پس سه جمله زیر را به خاطر بسپار:

هر Error لزوماً Defect ایجاد نمی‌کند.

هر Defect لزوماً Failure ایجاد نمی‌کند.

هر Failure لزوماً ناشی از یک Software Defect نیست.

و مهم‌تر:

Defect زمانی می‌تواند به Failure منجر شود که شرایط لازم برای فعال شدن آن فراهم شود و سیستم اجرا شود.

این دقیقاً همان جایی است که Test Design، Test Data و انتخاب سناریوهای مناسب اهمیت پیدا می‌کنند.

Static Testing و Dynamic Testing چه نقشی در Error، Defect و Failure دارند؟ 🔍

حالا که رابطه‌ی Error، Defect و Failure را می‌دانیم، باید ببینیم Testing در کجای این چرخه وارد می‌شود.

در اینجا دو مفهوم مهم داریم:

  • Static Testing
  • Dynamic Testing

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

Static Testing؛ پیدا کردن Defect بدون اجرای نرم‌افزار

در Static Testing، Test Item اجرا نمی‌شود. در عوض، Work Productهایی مانند Requirement، Design، Code و Test Case را بررسی می‌کنیم.

برای مثال، فرض کنید Requirement نوشته است:

«سفارش در مراحل اولیه قابل لغو است.»

این عبارت ممکن است برای پیاده‌سازی و تست بیش از حد مبهم باشد.

در یک Requirement Review می‌توان این ابهام را قبل از اینکه وارد Design و Coding شود شناسایی کرد.

Requirement
     ↓
Review
     ↓
Defect detected

هنوز نرم‌افزار اجرا نشده است؛ بنابراین برای پیدا کردن این Defect نیازی به مشاهده‌ی Failure نداریم.

همین موضوع یکی از ارزش‌های مهم Static Testing است:

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

Dynamic Testing؛ مشاهده رفتار واقعی سیستم

در Dynamic Testing، نرم‌افزار یا Test Item اجرا می‌شود و رفتار واقعی آن را بررسی می‌کنیم.

فرض کنید یک Defect در منطق لغو سفارش وجود دارد:

if order.status == "Pending":
    allow_cancel()

در حالی که Requirement می‌گوید سفارش‌های Confirmed نیز باید قابل لغو باشند.

Tester سناریوی زیر را اجرا می‌کند:

Order Status = Confirmed
Action = Cancel Order

Expected Result

سفارش باید لغو شود.

Actual Result

سیستم اجازه لغو سفارش را نمی‌دهد.

در اینجا یک Failure مشاهده شده است.

سپس Tester با بررسی Failure می‌تواند به Defect موجود در Code برسد.

Defect
   ↓
Execution
   ↓
Failure
   ↓
Investigation
   ↓
Defect identified

تفاوت اصلی را این‌طور به خاطر بسپار 🧠

Static Testing

Work Product را بدون اجرای آن بررسی می‌کنیم تا Defect را زودتر پیدا کنیم.

Dynamic Testing

سیستم را اجرا می‌کنیم تا رفتار واقعی آن را بررسی کنیم و در صورت وجود اختلاف با رفتار مورد انتظار، Failure را مشاهده کنیم.

STATIC TESTING
      ↓
Review / Analysis
      ↓
Defect
DYNAMIC TESTING
      ↓
Execution
      ↓
Actual Behavior
      ↓
Failure
      ↓
Investigation
      ↓
Defect

آیا Static Testing همیشه Defect را پیدا می‌کند؟

خیر. ❌

Static Testing می‌تواند احتمال کشف زودهنگام Defect را افزایش دهد، اما تضمین نمی‌کند که همه‌ی Defectها پیدا شوند.

ممکن است یک Code Review انجام شود اما یک Defect از دید Reviewer پنهان بماند.

در این حالت، Dynamic Testing می‌تواند با اجرای سناریوهای مناسب باعث فعال شدن آن Defect و مشاهده‌ی Failure شود.

بنابراین این دو رویکرد جایگزین کامل یکدیگر نیستند و بهتر است آن‌ها را مکمل یکدیگر بدانیم.

آیا Dynamic Testing فقط برای پیدا کردن Failure است؟

نه دقیقاً.

هدف Dynamic Testing فقط «دیدن Failure» نیست. در Dynamic Testing، سیستم را اجرا می‌کنیم و رفتار آن را در برابر نیازمندی‌ها و انتظارات بررسی می‌کنیم.

اگر رفتار واقعی با رفتار مورد انتظار مطابقت نداشته باشد، ممکن است Failure مشاهده شود و سپس Investigation برای پیدا کردن علت انجام شود.

Failure یک نتیجه‌ی احتمالی از اجرای سیستم است، نه تعریف کامل Dynamic Testing.

Static و Dynamic Testing در کنار هم 🧩

در یک فرآیند حرفه‌ای، بهتر است این دو رویکرد را مکمل یکدیگر ببینیم:

        WORK PRODUCTS
              │
       ┌──────┴──────┐
       ↓             ↓
 STATIC TESTING   DYNAMIC TESTING
       │             │
       ↓             ↓
   Defect         Execution
   Detection         │
                     ↓
                  Behavior
                     │
              ┌──────┴──────┐
              ↓             ↓
          Expected       Unexpected
          Behavior        Behavior
                            ↓
                         Failure
                            ↓
                      Investigation

به همین دلیل، یک تیم QA حرفه‌ای فقط منتظر اجرای نرم‌افزار نمی‌ماند تا مشکلات را پیدا کند.

بخشی از کیفیت با بررسی زودهنگام Work Productها ایجاد می‌شود و بخش دیگری با اجرای سیستم و بررسی رفتار واقعی آن.

ارتباط این بخش با Shift Left 🚀

این موضوع ما را به مفهوم مهم دیگری به نام Shift Left می‌رساند.

اگر بتوانیم Defect را هنگام بررسی Requirement، Design یا Code پیدا کنیم، لازم نیست منتظر بمانیم تا نرم‌افزار ساخته و اجرا شود و همان مشکل در مراحل بعدی خودش را نشان دهد.

Requirement Review
        ↓
Design Review
        ↓
Code Review
        ↓
Dynamic Testing
        ↓
Production

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

البته Shift Left به این معنا نیست که Dynamic Testing یا تست در مراحل بعدی دیگر ضروری نیست.

یک نکته مهم ⭐

درک این تفاوت کمک می‌کند دو جمله را با هم اشتباه نگیریم:

Static Testing می‌تواند Defect را قبل از Execution شناسایی کند.

Dynamic Testing با اجرای سیستم می‌تواند Failureها را آشکار کند و به شناسایی Defect کمک کند.

پس در مدل کلی مقاله:

Error
  ↓
Defect
  │
  ├──── Static Testing ────→ Defect Detection
  │
  └──── Dynamic Testing
              ↓
          Execution
              ↓
           Failure
              ↓
       Investigation
              ↓
           Defect

این مدل نشان می‌دهد چرا Static Testing و Dynamic Testing دو بخش مکمل از رویکرد تست هستند، نه دو روش رقیب.

📌 مطالعه بیشتر: برای آشنایی کامل با تفاوت Static Testing و Dynamic Testing، روش‌ها، مزایا و کاربردهای هرکدام، به مقاله‌ی اختصاصی این موضوع مراجعه کنید.

چرخه عمر Defect؛ از کشف نقص تا بسته شدن آن 🐞🔄

حالا فرض کنیم یک Defect (نقص / اشکال) پیدا کرده‌ایم.

آیا کار تمام شده است؟

نه.

پیدا کردن Defect فقط شروع یک مسیر است. در یک تیم واقعی QA، Defect باید ثبت، بررسی، اولویت‌بندی، اصلاح، تست مجدد و در نهایت بسته شود.

به این مسیر معمولاً می‌گوییم:

Defect Life Cycle — چرخه عمر نقص

داستان را با یک مثال شروع کنیم 🛒

فرض کنید Tester در یک فروشگاه اینترنتی متوجه می‌شود:

وقتی کاربر یک محصول را به سبد خرید اضافه می‌کند، تعداد محصول همیشه به‌صورت 1 نمایش داده می‌شود؛ حتی اگر کاربر تعداد را روی 3 قرار داده باشد.

Tester ابتدا Expected و Actual Result را مقایسه می‌کند.

Expected

Quantity = 3

Actual

Quantity = 1

پس یک رفتار غیرمنتظره داریم.

Tester بررسی‌های اولیه را انجام می‌دهد و متوجه می‌شود:

یک Defect در منطق محاسبه Quantity وجود دارد.

حالا باید آن را در سیستم مدیریت Defect ثبت کند.

1. New — Defect جدید 🆕

اولین وضعیت می‌تواند:

New

باشد.

یعنی:

یک Defect شناسایی و ثبت شده، اما هنوز بررسی و تعیین تکلیف نشده است.

DEF-1024
Title:
Cart quantity is always displayed as 1
Status:
New

در این مرحله اطلاعاتی مثل موارد زیر اهمیت دارند:

  • عنوان واضح
  • Steps to Reproduce
  • Expected Result
  • Actual Result
  • Environment
  • Severity
  • Priority
  • Evidence

2. Open / Assigned 📋

بعد از ثبت، Defect ممکن است بررسی و به فرد یا تیم مربوطه Assign شود.

Assigned to: Backend Team

یا:

Assigned to: Developer

حالا تیم Development باید بررسی کند که آیا واقعاً مشکلی وجود دارد یا نه.

3. بررسی Defect 🔍

اینجا یک اتفاق مهم ممکن است رخ دهد.

Developer بررسی می‌کند و می‌گوید:

«این رفتار مطابق Requirement است.»

در این صورت ممکن است Defect:

Rejected

شود.

یا مشخص شود قبلاً همین مشکل ثبت شده است:

Duplicate

یا اصلاً نتوانند آن را دوباره ایجاد کنند:

Cannot Reproduce

پس:

هر چیزی که Tester گزارش می‌کند الزاماً یک Defect معتبر نیست.

این نکته با بحث قبلی ما درباره Incident، Failure و Investigation کاملاً مرتبط است.

4. Confirmed / Accepted ✅

اگر تیم تأیید کند که:

بله، این رفتار برخلاف Requirement است.

Defect پذیرفته می‌شود.

در بعضی Workflowها ممکن است وضعیت‌هایی مانند Confirmed یا Accepted وجود داشته باشد.

البته نام Statusها در ابزارها و سازمان‌های مختلف متفاوت است.

5. In Progress 🛠️

Developer کار اصلاح را شروع می‌کند.

Status:

In Progress

یعنی:

Defect در حال بررسی یا اصلاح است.

در این مرحله Developer ممکن است:

  • Code را بررسی کند.
  • Root Cause را پیدا کند.
  • Fix ایجاد کند.
  • Unit Test اضافه کند.
  • Code Review انجام دهد.

6. Fixed 🔧

Developer اعلام می‌کند:

«مشکل اصلاح شد.»

Status ممکن است به:

Fixed

تغییر کند.

اما اینجا یک اشتباه رایج وجود دارد:

Fixed به معنی Verified نیست.

یعنی Developer گفته:

«من اصلاحش کردم.»

اما هنوز Tester باید بررسی کند:

«آیا واقعاً اصلاح شده است؟»

7. Retest — تست مجدد 🧪

حالا Tester همان سناریویی را که باعث کشف Defect شده بود، دوباره اجرا می‌کند.

مثلاً:

Before Fix
Quantity = 3
Actual = 1
❌
After Fix
Quantity = 3
Actual = 3
✅

اگر رفتار صحیح باشد، Tester می‌تواند Defect را Verified در نظر بگیرد.

8. Regression Testing 🔄

اما داستان هنوز تمام نشده است.

فرض کنید Developer منطق Cart را تغییر داده است.

ممکن است این تغییر قسمت‌های دیگری را خراب کرده باشد.

  • Add to Cart
  • Remove from Cart
  • Update Quantity
  • Checkout
  • Discount Calculation

بنابراین Tester ممکن است Regression Testing انجام دهد.

یعنی بررسی کند:

آیا Fix جدید باعث ایجاد مشکل دیگری نشده است؟

9. Closed — بسته شد 🔒

اگر:

  • Defect اصلاح شده باشد،
  • Retest موفق باشد،
  • Regression موردنیاز انجام شده باشد،

Defect می‌تواند:

Closed

شود.

New
 ↓
Assigned
 ↓
In Progress
 ↓
Fixed
 ↓
Retest
 ↓
Verified
 ↓
Closed

اما همیشه مسیر این‌قدر ساده نیست

در پروژه واقعی ممکن است Defect از مسیرهای دیگری عبور کند.

New
 ↓
Rejected

یا:

New
 ↓
Duplicate

یا:

Fixed
 ↓
Retest
 ↓
Reopened
 ↓
In Progress
 ↓
Fixed

Reopened — دوباره باز شد 🔁

فرض کنید Developer می‌گوید:

«Defect اصلاح شد.»

Tester آن را Retest می‌کند.

اما هنوز:

Actual Result ≠ Expected Result

است.

Tester Defect را:

Reopened

می‌کند.

یعنی:

Fix نتوانسته مشکل را به‌طور کامل برطرف کند.

یک مثال واقعی

Developer مشکل Quantity را اصلاح می‌کند.

Tester دوباره تست می‌کند:

Quantity = 3

حالا UI مقدار 3 را نشان می‌دهد.

اما وقتی کاربر وارد Checkout می‌شود:

Quantity = 1

پس مشکل هنوز به‌طور کامل حل نشده است.

Tester می‌گوید:

❌ Reopened

و Defect دوباره وارد چرخه اصلاح می‌شود.

Duplicate چیست؟ 🧩

گاهی Tester یک Defect جدید ثبت می‌کند، اما متوجه می‌شویم همین مشکل قبلاً ثبت شده است.

DEF-1024
Cart quantity incorrect
DEF-1098
Cart quantity not updated

اگر مشخص شود هر دو یک مشکل هستند، DEF-1098 می‌تواند:

Duplicate

شود.

این کار باعث می‌شود تیم چند بار یک Defect را مدیریت نکند.

Rejected چیست؟ ❌

گاهی Defect گزارش می‌شود، اما پس از بررسی مشخص می‌شود:

رفتار سیستم مطابق Requirement است.

مثلاً Tester انتظار دارد:

HTTP 404

برگردد.

اما Requirement مشخص کرده:

HTTP 400

باید برگردد.

Tester تصور کرده رفتار اشتباه است، اما بعد از بررسی متوجه می‌شود Test Expectation اشتباه بوده است.

در این حالت ممکن است Defect:

Rejected

شود.

این مثال دوباره یک نکته مهم را نشان می‌دهد:

هر Failed Test الزاماً Bug نیست.

Cannot Reproduce چیست؟ 🤔

گاهی Tester می‌گوید:

این مشکل را مشاهده کردم.

اما Developer هر کاری می‌کند، نمی‌تواند آن را دوباره ایجاد کند.

ممکن است وضعیت:

Cannot Reproduce

ثبت شود.

اما این وضعیت به معنی:

«پس Tester اشتباه کرده.»

نیست.

ممکن است مشکل به موارد زیر وابسته باشد:

  • Environment
  • Timing
  • Test Data
  • Race Condition
  • Network
  • Configuration

بنابراین باید شواهد بیشتری بررسی شود.

Won’t Fix چیست؟ 🛑

گاهی Defect واقعی است.

یعنی:

بله، مشکل وجود دارد.

اما تیم تصمیم می‌گیرد فعلاً آن را اصلاح نکند.

  • Impact بسیار کم است.
  • اصلاح آن هزینه زیادی دارد.
  • Feature قرار است حذف شود.
  • Release نزدیک است.
  • Risk قابل قبول است.

در چنین شرایطی ممکن است وضعیت‌هایی مانند:

Won’t Fix

یا:

Deferred

استفاده شوند.

نکته مهم:

Won’t Fix به معنی «Defect وجود ندارد» نیست.

بلکه یعنی:

Defect پذیرفته شده، اما فعلاً تصمیم به اصلاح آن گرفته نشده است.

Severity و Priority کجای این چرخه قرار می‌گیرند؟ 🎯

یکی از مهم‌ترین بخش‌های مدیریت Defect، تعیین:

Severity

و:

Priority

است.

Severity — شدت

می‌پرسد:

این Defect چقدر روی سیستم اثر می‌گذارد؟

مثلاً:

سیستم در پرداخت Crash می‌کند.

ممکن است:

High/Critical Severity

باشد.

Priority — اولویت

می‌پرسد:

این Defect با چه فوریتی باید اصلاح شود؟

ممکن است یک Defect Severity بالا داشته باشد و Priority بالا هم بگیرد، اما همیشه این دو دقیقاً یکسان نیستند.

یک مثال جالب

فرض کنید در صفحه اصلی سایت، لوگو کمی جابه‌جا شده است.

از نظر فنی:

Severity = Low

اما اگر قرار باشد فردا یک کمپین تبلیغاتی بزرگ اجرا شود و صفحه اصلی میلیون‌ها بازدید داشته باشد:

Priority = High

پس:

Severity و Priority یک مفهوم نیستند.

Defect Life Cycle را کامل‌تر ببینیم 🧠

              ┌──────────────┐
              │     New      │
              └──────┬───────┘
                     ↓
                Assigned
                     ↓
                In Progress
                     ↓
                  Fixed
                     ↓
                  Retest
                  ↙     ↘
               Pass     Fail
                ↓         ↓
             Closed    Reopened
                          ↓
                     In Progress

و مسیرهای جانبی:

New → Rejected
New → Duplicate
New → Cannot Reproduce
Confirmed → Deferred
Confirmed → Won't Fix

یک نکته بسیار مهم برای مقاله ⭐

چرخه عمر Defect یک استاندارد واحد با Statusهای کاملاً ثابت نیست.

ممکن است یک شرکت از این Statusها استفاده کند:

New
Open
In Progress
Fixed
Retest
Closed

و شرکت دیگری:

New
Triaged
Assigned
Development
Ready for QA
QA Testing
Verified
Closed

بنابراین:

اسم Statusها می‌تواند متفاوت باشد، اما مفهوم Workflow تقریباً مشابه است.

ارتباط این بخش با Error → Defect → Failure

حالا اگر کل مقاله را کنار هم بگذاریم، تصویر بسیار کامل‌تری داریم:

👤 ERROR
خطا / اشتباه انسانی
        ↓
🐞 DEFECT
نقص / اشکال
        ↓
▶️ Execution
        ↓
⚠️ FAILURE
شکست / خرابی
        ↓
📋 INCIDENT
رخداد / گزارش
        ↓
🔍 Investigation
        ↓
🧠 Root Cause
        ↓
🛠️ Fix
        ↓
🧪 Retest
        ↓
🔄 Regression
        ↓
🔒 Closed

اما یک نکته مهم را فراموش نکنیم:

Defect ممکن است قبل از Failure، مثلاً در Static Testing، پیدا و اصلاح شود.

در آن حالت مسیر این‌طور می‌شود:

Error
  ↓
Defect
  ↓
Static Testing
  ↓
Found
  ↓
Fixed
  ↓
No Failure

و این دقیقاً همان چیزی است که یک فرآیند تست خوب باید تا حد امکان به آن نزدیک شود:

کشف زودهنگام Defect، قبل از اینکه به Failure و سپس به مشکل واقعی برای کاربر تبدیل شود. 🚀

نقش Severity و Priority در چرخه عمر Defect 🎯

در هنگام ثبت و بررسی یک Defect، تیم باید درباره میزان تأثیر و فوریت رسیدگی به آن تصمیم بگیرد. اینجا دو مفهوم Severity و Priority اهمیت پیدا می‌کنند.

اما چون این دو مفهوم در مقاله‌ای جداگانه به‌طور کامل بررسی شده‌اند، در اینجا فقط ارتباط آن‌ها با Defect Life Cycle را مرور می‌کنیم.

Severity بیشتر به میزان تأثیر و شدت Defect مربوط است، در حالی که Priority به فوریت رسیدگی و زمان‌بندی اصلاح آن مربوط می‌شود.

این اطلاعات معمولاً در مرحله Defect Triage بررسی می‌شوند و به تیم کمک می‌کنند تصمیم بگیرد هر Defect چگونه و چه زمانی مدیریت شود.

برای مثال، ممکن است یک Defect تأثیر محدودی داشته باشد اما به دلیل نزدیک بودن یک Release یا کمپین مهم، در اولویت بالایی قرار گیرد.

در مقابل، ممکن است یک Defect از نظر فنی جدی باشد اما به دلیل شرایط خاص محصول یا Release، اصلاح آن به زمان دیگری موکول شود.

بنابراین در چرخه عمر Defect، Severity و Priority می‌توانند در تصمیم‌هایی مانند موارد زیر نقش داشته باشند:

  • تعیین اولویت رسیدگی
  • تصمیم‌گیری در Defect Triage
  • انتخاب Defectهای مناسب برای Release
  • تصمیم‌گیری درباره Fix یا Defer
  • ارزیابی Risk و Impact

برای جزئیات بیشتر درباره تفاوت Severity و Priority، سطوح رایج آن‌ها و نحوه تعیینشان، می‌توانید به مقاله اختصاصی این موضوع مراجعه کنید.

ارتباط با چرخه عمر Defect

به‌صورت ساده می‌توان این ارتباط را این‌گونه دید:

New
  ↓
Investigation / Triage
  ↓
Severity + Priority
  ↓
Decision
  ├── Fix
  ├── Defer
  ├── Reject
  └── Duplicate

البته این ترتیب در همه تیم‌ها یکسان نیست و ممکن است Severity و Priority هنگام ثبت Defect یا در مراحل بعدی Workflow تعیین یا تغییر داده شوند.

💡 نکته مهم: Severity و Priority بخشی از اطلاعات مورد استفاده برای مدیریت Defect هستند، نه اینکه خودشان Statusهای چرخه عمر Defect باشند.

یک سناریوی کامل؛ از Error تا Failure و Incident 🧩

تا اینجا هر مفهوم را جداگانه بررسی کردیم. اما بهترین راه برای اینکه تفاوت آن‌ها واقعاً در ذهن بماند، این است که همه را در یک داستان واحد ببینیم.

فرض کنیم در حال تست یک فروشگاه اینترنتی هستیم. 🛒

داستان از Requirement شروع می‌شود

Product Owner یک Requirement تعریف می‌کند:

«کاربر می‌تواند سفارش خود را تا زمانی که سفارش ارسال نشده است، لغو کند.»

در نگاه اول ساده به نظر می‌رسد.

اما یک سؤال مهم وجود دارد:

منظور از «ارسال نشده» دقیقاً چیست؟

آیا سفارش با وضعیت‌های زیر قابل لغو است؟

  • Pending
  • Confirmed
  • Processing

اگر این موارد در Requirement مشخص نشده باشند، همین‌جا ممکن است یک مشکل ایجاد شود.

مرحله اول: Error — خطا / اشتباه 👤

Developer Requirement را می‌خواند و تصور می‌کند:

«فقط سفارش‌های Pending قابل لغو هستند.»

این برداشت اشتباه، یک Error / Mistake است.

هنوز سیستم اجرا نشده است و هنوز Failure نداریم.

مرحله دوم: Defect — نقص / اشکال 🐞

Developer بر اساس برداشت اشتباه خود Code را می‌نویسد:

if order.status == "Pending":
    allow_cancel()

در حالی که Business Rule واقعی این است:

Pending
Confirmed
Processing
        ↓
   قابل لغو

حالا اشتباه انسانی وارد محصول شده است.

پس یک Defect داریم.

اما یک اتفاق مهم می‌تواند رخ دهد 🔍

Tester در Code Review یا Requirement Review متوجه مشکل می‌شود و می‌گوید:

«طبق Business Rule، سفارش Confirmed هم باید قابل لغو باشد.»

Defect قبل از اجرای نرم‌افزار پیدا می‌شود.

Error
 ↓
Defect
 ↓
Static Testing
 ↓
Defect Found
 ↓
Fix

Failure؟ ❌ نداریم.

Incident؟ ❌ نداریم.

کاربر آسیب دیده؟ ❌ خیر.

این یکی از بهترین حالت‌های ممکن است.

اما اگر Defect در Static Testing پیدا نشود چه؟

فرض کنیم Tester این Defect را پیدا نمی‌کند.

Code وارد Build می‌شود و تیم آن را Deploy می‌کند.

حالا کاربر یک سفارش با وضعیت Confirmed دارد.

کاربر روی:

Cancel Order

کلیک می‌کند.

سیستم می‌گوید:

❌ امکان لغو این سفارش وجود ندارد.

در حالی که Requirement می‌گوید کاربر باید بتواند سفارش را لغو کند.

اینجا Failure رخ داده است.

چرا؟ چون:

Actual Behavior ≠ Expected Behavior

مرحله بعد: Incident 🚨

کاربر با پشتیبانی تماس می‌گیرد:

«من نمی‌توانم سفارشم را لغو کنم.»

حالا سازمان یک مورد برای بررسی ثبت می‌کند:

Incident #4521
Customer cannot cancel confirmed order.

این یک Incident است؛ یعنی یک رخداد یا وضعیت غیرمنتظره که نیازمند بررسی و رسیدگی است.

Investigation شروع می‌شود 🔎

تیم QA و Development شروع به بررسی می‌کنند.

Expected:
Confirmed → Cancel
Actual:
Confirmed → Cannot Cancel

آن‌ها Code را بررسی می‌کنند و به این شرط می‌رسند:

if order.status == "Pending":

حالا مشخص می‌شود که یک Defect در Code وجود دارد.

اما تیم یک سؤال مهم‌تر می‌پرسد

چرا این Defect اصلاً وارد Production شد؟

اینجاست که Root Cause Analysis شروع می‌شود.

Root Cause Analysis 🧠

تیم بررسی می‌کند و مشخص می‌شود Requirement عبارت مبهمی داشته است:

«سفارش‌های اولیه قابل لغو هستند.»

Developer این عبارت را به Pending تفسیر کرده است.

از طرف دیگر، Test Caseها فقط این سناریو را پوشش داده‌اند:

Pending Order
      ↓
Cancel
      ↓
Success

اما کسی این سناریو را تست نکرده است:

Confirmed Order
      ↓
Cancel
      ↓
Success

بنابراین دو عامل در این اتفاق نقش داشته‌اند:

  • Root Cause احتمالی اول: Requirement مبهم
  • Root Cause احتمالی دوم: Test Coverage ناکافی

Fix انجام می‌شود 🛠️

Developer Code را اصلاح می‌کند:

if order.status in ["Pending", "Confirmed", "Processing"]:
    allow_cancel()

همچنین Test Caseهای جدید اضافه می‌شوند.

Retest 🧪

Tester دوباره سناریو را اجرا می‌کند:

Pending
Cancel → Success ✅
Confirmed
Cancel → Success ✅
Processing
Cancel → Success ✅
Shipped
Cancel → Not Allowed ✅

حالا رفتار سیستم مطابق Requirement است.

Regression Testing 🔄

اما Tester فقط همان Defect را بررسی نمی‌کند.

چون Code تغییر کرده است، باید بررسی شود که آیا این تغییر بخش دیگری را خراب کرده یا نه.

  • Order Status
  • Payment
  • Refund
  • Inventory
  • Notification

بنابراین Regression Testing انجام می‌شود.

در نهایت Defect بسته می‌شود 🔒

اگر همه چیز درست باشد، چرخه می‌تواند به این شکل ادامه پیدا کند:

Defect
   ↓
Fixed
   ↓
Retest
   ↓
Passed
   ↓
Regression Passed
   ↓
Closed

حالا کل داستان را یکجا ببینیم 🧠

Requirement مبهم
       ↓
Human Error / Mistake
خطا یا اشتباه
       ↓
Defect
نقص / اشکال
       ↓
Defect در Static Testing پیدا نشد
       ↓
Execution
       ↓
Failure
شکست / خرابی
       ↓
Customer Impact
       ↓
Incident
رخداد
       ↓
Investigation
       ↓
Root Cause Analysis
       ↓
Fix
       ↓
Retest
       ↓
Regression Testing
       ↓
Closed

این زنجیره یکی از بهترین مدل‌های ذهنی برای فهم ارتباط مفاهیم این مقاله است.

اما یک نکته بسیار مهم ⚠️

این زنجیره همیشه کامل اتفاق نمی‌افتد.

ممکن است Defect قبل از Execution و در Static Testing پیدا و اصلاح شود:

Error
 ↓
Defect
 ↓
Static Testing
 ↓
Found
 ↓
Fixed

در این حالت اصلاً Failure ایجاد نمی‌شود.

همچنین ممکن است Defect در محیط Test فعال شود و Tester آن را قبل از رسیدن به کاربر پیدا کند.

از طرف دیگر، ممکن است Failure مشاهده شود اما بعد از Investigation مشخص شود که Software Defect وجود ندارد و علت از Infrastructure، Network یا یک سرویس خارجی بوده است.

حتی یک Failed Test نیز الزاماً به معنی وجود Defect در Application نیست؛ ممکن است Test Case، Test Data، Environment یا انتظار تست اشتباه باشد.

یک نکته طلایی درباره Bug 🐞

در همین داستان اگر Tester بگوید:

«من یک Bug پیدا کردم.»

از نظر مفهومی، منظورش معمولاً همان Defect است.

در محیط‌های واقعی Software Development، واژه Bug بسیار رایج و غیررسمی است و بسیاری از تیم‌ها آن را به جای Defect استفاده می‌کنند.

بنابراین Bug و Defect در بسیاری از مکالمات روزمره مترادف استفاده می‌شوند و نباید آن‌ها را همیشه دو نوع کاملاً متفاوت از مشکل در نظر گرفت.

اگر Tester بگوید «Failure پیدا کردم» چه؟ 🤔

آیا می‌توانیم فوراً نتیجه بگیریم که یک Defect پیدا شده است؟

نه، هنوز نه.

باید Investigation انجام شود؛ زیرا Failure ممکن است ناشی از موارد مختلفی باشد:

  • Software Defect
  • Infrastructure Problem
  • Network Problem
  • External Service Failure
  • Configuration
  • Test Environment
  • Test Data

پس Tester باید از مشاهده به تحلیل علت حرکت کند.

این دقیقاً تفاوت Tester حرفه‌ای و تست سطحی است 🚀

یک Tester فقط نمی‌گوید:

❌ «سیستم کار نکرد.»

بلکه می‌گوید:

  • ✅ Expected Result این بود و Actual Result این شد.
  • 🔍 شرایط بازتولید مشخص است.
  • 🐞 Defect در این بخش مشاهده شد.
  • 🧠 در صورت نیاز، Root Cause احتمالی این است.

این نوع گزارش‌دادن باعث می‌شود Tester برای Developer، Product و کل تیم ارزش بیشتری ایجاد کند.

⭐ جمع‌بندی سناریو

اگر بخواهیم داستان فروشگاه را در یک جمله خلاصه کنیم:

یک اشتباه انسانی (Error/Mistake) ممکن است وارد محصول شود و به Defect تبدیل شود؛ اگر Defect هنگام اجرای سیستم فعال شود، می‌تواند Failure ایجاد کند؛ اگر این Failure به یک رخداد قابل پیگیری تبدیل شود، Incident شکل می‌گیرد و سپس با Investigation و Root Cause Analysis می‌توان علت را پیدا و Defect را اصلاح کرد.

و البته:

اگر Defect قبل از Execution در Static Testing پیدا شود، ممکن است کل زنجیره Failure و Incident اصلاً اتفاق نیفتد. 🎯

جدول جامع تفاوت Error، Mistake، Bug، Defect، Fault، Failure و Incident 📊

تا اینجا هر مفهوم را جداگانه بررسی کردیم. حالا وقت آن است که همه را کنار هم بگذاریم.

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

جدول اصلی مفاهیم

اصطلاح معادل فارسی پیشنهادی مفهوم ساده معمولاً مربوط به چه چیزی است؟
Error خطا / اشتباه یک عمل یا تصمیم نادرست انسانی انسان
Mistake اشتباه انجام یا انتخاب نادرست توسط انسان انسان
Defect نقص / اشکال نقصی در یک Work Product که می‌تواند باعث رفتار نادرست شود Requirement، Design، Code و…
Bug باگ اصطلاح رایج برای یک مشکل یا Defect در نرم‌افزار نرم‌افزار / محصول
Fault نقص / خطای فنی عاملی در سیستم که می‌تواند باعث Failure شود Software / System
Failure شکست / خرابی ناتوانی سیستم در انجام رفتار مورد انتظار هنگام اجرا سیستم در زمان اجرا
Incident رخداد یک اتفاق یا وضعیت غیرمنتظره که نیاز به بررسی یا رسیدگی دارد سرویس / سیستم / کاربر
Issue مسئله / مورد قابل پیگیری یک مورد ثبت‌شده برای پیگیری مدیریت کار
Problem مشکل علت یا وضعیت بنیادی مرتبط با یک یا چند Incident سیستم / فرآیند

حالا تفاوت‌ها را با یک سؤال ساده به خاطر بسپاریم 🧠

Error

چه کسی اشتباه کرد؟

👤 انسان

Mistake

چه تصمیم یا عمل انسانی اشتباه بود؟

👤 انسان

Defect

چه نقصی وارد محصول یا Work Product شده است؟

🐞 محصول / Requirement / Design / Code

Bug

چه مشکل یا نقصی در نرم‌افزار وجود دارد؟

🐞 Software

Fault

چه عامل یا نقص فنی می‌تواند باعث رفتار نادرست شود؟

⚙️ سیستم

Failure

سیستم هنگام اجرا چه چیزی را اشتباه انجام داد؟

⚠️ Runtime Behavior

Incident

چه اتفاق غیرمنتظره‌ای مشاهده یا گزارش شد؟

🚨 رخداد

Issue

چه موردی باید ثبت و پیگیری شود؟

📋 Work Item

Problem

چه مشکل بنیادی یا علت سیستماتیکی پشت Incidentها وجود دارد؟

🔎 علت / وضعیت بنیادی

Error و Mistake چه تفاوتی دارند؟

این دو واژه در منابع مختلف ممکن است با هم هم‌پوشانی داشته باشند.

در بسیاری از متون Software Testing:

Error برای یک خطا یا اشتباه انسانی استفاده می‌شود.

و:

Mistake نیز به یک تصمیم، عمل یا برداشت نادرست انسانی اشاره می‌کند.

بنابراین نباید تصور کنیم:

Error و Mistake همیشه دو مرحله کاملاً جدا هستند.

در بسیاری از Contextها می‌توان آن‌ها را بسیار نزدیک یا حتی مترادف دانست.

مثلاً:

Developer Requirement را اشتباه متوجه می‌شود.

می‌توانیم بگوییم:

Human Error / Mistake

Bug و Defect چه تفاوتی دارند؟ 🐞

این سؤال احتمالاً برای خیلی از خوانندگان مقاله مطرح می‌شود.

در محیط واقعی:

Bug و Defect اغلب به جای یکدیگر استفاده می‌شوند.

مثلاً Tester می‌گوید:

«یک Bug پیدا کردم.»

و در یک گزارش رسمی ممکن است نوشته شود:

«A Defect was identified.»

در بسیاری از Contextها منظور هر دو:

وجود یک مشکل یا نقص در محصول

است.

بنابراین بهتر است این دو را به‌عنوان دو مفهوم کاملاً جدا معرفی نکنیم.

اما یک تفاوت ظریف وجود دارد

Bug بیشتر یک اصطلاح رایج و غیررسمی در توسعه نرم‌افزار است.

Defect اصطلاح رسمی‌تر و عمومی‌تر در زبان کیفیت و تست است.

به‌خصوص Defect می‌تواند برای Work Productهایی غیر از Code هم استفاده شود:

  • Requirement Defect
  • Design Defect
  • Testware Defect

پس:

Bug معمولاً بیشتر به مشکل نرم‌افزار اشاره دارد، اما Defect دامنه مفهومی گسترده‌تری دارد.

Fault و Defect چطور؟

این دو حتی از Bug و Defect هم پیچیده‌تر هستند.

در برخی منابع، Fault و Defect بسیار نزدیک به هم استفاده می‌شوند.

در برخی مدل‌ها، Fault به یک نقص یا وضعیت داخلی اشاره می‌کند که می‌تواند هنگام اجرای سیستم باعث رفتار نادرست شود.

مثلاً:

Requirement
    ↓
Code
    ↓
Fault / Defect
    ↓
Execution
    ↓
Failure

بنابراین برای مقاله بهتر است خواننده را با یک تفاوت مصنوعی و مطلق گیج نکنیم.

معنای دقیق Fault و Defect می‌تواند بسته به استاندارد و Context متفاوت باشد و در بسیاری از منابع هم‌پوشانی دارند.

Failure کجای داستان است؟ ⚠️

Failure با مفاهیم قبلی یک تفاوت بسیار مهم دارد.

Failure مربوط به:

رفتار واقعی سیستم هنگام اجرا

است.

مثلاً:

Requirement:

«کاربر باید بتواند رمز عبور خود را تغییر دهد.»

Actual:

با کلیک روی Change Password، برنامه Crash می‌کند.

این:

Failure

است.

اما علت آن ممکن است:

Defect

باشد.

Defect
   ↓
Execution
   ↓
Failure

اما همان‌طور که قبلاً گفتیم:

هر Failure الزاماً ناشی از Software Defect نیست.

Incident چه چیزی را اضافه می‌کند؟ 🚨

Incident بیشتر از زاویه رخداد و مدیریت آن دیده می‌شود.

مثلاً:

کاربران گزارش می‌دهند که پرداخت انجام نمی‌شود.

این یک:

Incident

است.

بعد Investigation انجام می‌شود.

ممکن است علت:

  • Software Defect
  • Infrastructure Problem
  • External Service Failure

باشد.

بنابراین:

Incident بیشتر چیزی است که باید بررسی و مدیریت شود؛ Defect یکی از علت‌های احتمالی آن است.

Issue را فراموش نکنیم 📋

Issue حتی عمومی‌تر است.

مثلاً در یک Project Management Tool ممکن است این موارد همگی Issue باشند:

Bug
Task
Feature
Improvement
Story
Question

پس:

Issue یک اصطلاح عمومی برای یک مورد قابل پیگیری است.

بنابراین:

Issue ≠ Bug

ولی:

Bug → می‌تواند به شکل یک Issue ثبت شود.

یک نمودار جامع 🧩

حالا همه مفاهیم را کنار هم قرار دهیم:

                👤 HUMAN
                   │
                   ▼
            ERROR / MISTAKE
             خطا / اشتباه
                   │
                   ▼
             DEFECT / FAULT
              نقص / اشکال
                   │
                   │ Execution
                   ▼
               FAILURE
              شکست / خرابی
                   │
                   ▼
              INCIDENT
                رخداد
                   │
                   ▼
             INVESTIGATION
                   │
                   ▼
             ROOT CAUSE
              علت ریشه‌ای

در کنار این زنجیره:

BUG
 │
 └── معمولاً اصطلاح رایج برای Defect نرم‌افزار

و:

ISSUE
 │
 └── اصطلاح عمومی برای مورد قابل پیگیری

اما یک نکته بسیار مهم ⭐

این نمودار را نباید به شکل یک قانون ریاضی در نظر گرفت.

مثلاً ممکن است:

Requirement Defect
      ↓
Static Testing
      ↓
Found
      ↓
Fixed

و اصلاً:

Failure

رخ ندهد.

یا:

Infrastructure Problem
      ↓
Service unavailable
      ↓
Failure
      ↓
Incident

بدون اینکه:

Software Defect

در Code وجود داشته باشد.

پس این مفاهیم روابط مختلفی با یکدیگر دارند، نه یک زنجیره اجباری.

یک مثال نهایی برای تثبیت مفاهیم 🛒

فرض کنید کاربر نمی‌تواند پرداخت کند.

کاربر می‌گوید:

«پرداخت انجام نمی‌شود.»

📋 Incident

تست نشان می‌دهد:

سیستم HTTP 500 برمی‌گرداند.

⚠️ Failure

بررسی Code:

یک شرط اشتباه در Payment Service وجود دارد.

🐞 Defect / Fault

بررسی بیشتر:

Developer Requirement را اشتباه تفسیر کرده است.

👤 Error / Mistake

بررسی فرآیند:

Requirement از ابتدا مبهم بوده است.

🧠 Root Cause احتمالی

در Jira:

این مورد می‌تواند به صورت:

Issue

ثبت شده باشد.

این یک مثال ساده است که نشان می‌دهد یک مشکل واقعی می‌تواند از چند زاویه مختلف با واژه‌های متفاوت توصیف شود.

🏆 اگر فقط ۹ جمله از این مقاله را به خاطر بسپارید

  1. Error / Mistake = انسان اشتباه می‌کند.
  2. Defect = یک نقص در Work Product وجود دارد.
  3. Bug = اصطلاح رایج برای مشکل یا نقص نرم‌افزار است.
  4. Fault = در برخی منابع به یک نقص/عامل فنی اشاره دارد که می‌تواند باعث رفتار نادرست شود.
  5. Failure = سیستم هنگام اجرا رفتار مورد انتظار را ارائه نمی‌کند.
  6. Incident = یک رخداد یا وضعیت غیرمنتظره که نیاز به بررسی یا رسیدگی دارد.
  7. Issue = یک مورد عمومی که باید ثبت و پیگیری شود.
  8. Problem = یک مشکل یا علت بنیادی مرتبط با یک یا چند Incident.
  9. Root Cause = علت ریشه‌ای که باید برای جلوگیری از تکرار مشکل بررسی شود.

یک جمله نهایی برای به خاطر سپردن 🎯

یک انسان ممکن است Error/Mistake کند؛ این اشتباه ممکن است به Defect منجر شود؛ Defect در صورت فعال شدن هنگام Execution می‌تواند Failure ایجاد کند؛ Failure ممکن است به یک Incident تبدیل شود؛ سپس تیم با Investigation و Root Cause Analysis علت را پیدا می‌کند و با Fix و Prevention تلاش می‌کند از تکرار آن جلوگیری کند.

و البته:

اگر Defect قبل از Execution در Static Testing پیدا شود، ممکن است کل زنجیره Failure و Incident اصلاً اتفاق نیفتد. 🎯

10 اشتباه رایج درباره Error، Defect و Failure که باید بشناسیم ❌

حالا که تمام مفاهیم اصلی را کنار هم گذاشتیم، وقت آن است سراغ اشتباهاتی برویم که حتی بین افراد تازه‌کار و گاهی در تیم‌های واقعی QA دیده می‌شوند.

شناخت این اشتباهات مهم است، چون بسیاری از سردرگمی‌ها نه از پیچیده بودن مفاهیم، بلکه از استفاده نادرست از همین واژه‌ها به وجود می‌آیند.

1. «هر Error حتماً یک Defect ایجاد می‌کند» ❌

این تصور درست نیست.

ممکن است Developer هنگام نوشتن Code اشتباه کند، اما قبل از اینکه این اشتباه وارد محصول شود، خودش یا فرد دیگری آن را پیدا و اصلاح کند.

Developer Mistake
      ↓
Code Review
      ↓
اشتباه پیدا شد
      ↓
Fix

در این حالت:

Error رخ داده، اما Defect ماندگاری در محصول باقی نمانده است.

پس:

Error می‌تواند منجر به Defect شود، اما الزاماً نمی‌شود.

2. «هر Defect حتماً Failure ایجاد می‌کند» ❌

این یکی از مهم‌ترین اشتباهات است.

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

Defect
   ↓
Specific condition never occurs
   ↓
No Failure

پس:

وجود Defect به‌تنهایی به معنی وقوع Failure نیست.

برای ایجاد Failure معمولاً باید:

  1. نرم‌افزار اجرا شود.
  2. شرایط لازم فراهم شود.
  3. Defect فعال شود.
  4. رفتار واقعی با رفتار مورد انتظار متفاوت باشد.

3. «هر Failure یعنی یک Bug داریم» ❌

Failure فقط به ما می‌گوید:

رفتار سیستم مطابق انتظار نبوده است.

اما علت می‌تواند چیزهای مختلفی باشد:

  • Software Defect
  • Network Failure
  • Infrastructure Failure
  • Configuration Problem
  • Third-party Service Failure
  • Test Environment Problem

بنابراین وقتی سیستم در محیط تست بالا نمی‌آید، نباید فوراً بگوییم:

🐞 «Bug است!»

ابتدا باید Investigation انجام شود.

4. «Bug و Defect کاملاً دو چیز متفاوت هستند» ❌

در بسیاری از مکالمات روزمره Software Testing:

Bug و Defect به جای یکدیگر استفاده می‌شوند.

مثلاً Tester می‌گوید:

«I found a bug.»

و در یک گزارش رسمی ممکن است نوشته شود:

«A defect was identified.»

در بسیاری از Contextها منظور همان مشکل است.

تفاوت مهم‌تر این است که:

Defect می‌تواند برای Requirement، Design و سایر Work Productها هم استفاده شود، در حالی که Bug معمولاً بیشتر برای مشکل نرم‌افزار به کار می‌رود.

پس بهتر است این دو را بیش از حد از هم جدا نکنیم.

5. «Failure همان Exception است» ❌

این اشتباه مخصوصاً بین افراد تازه‌کار در Automation و Programming رایج است.

NullPointerException

یک Exception است.

اما آیا الزاماً Failure است؟

نه.

اگر برنامه Exception را به‌درستی مدیریت کند و رفتار مورد انتظار را ارائه دهد، ممکن است از دید کاربر Failure نداشته باشیم.

در مقابل، Exception می‌تواند باعث Failure شود:

Exception
   ↓
Unhandled
   ↓
Application Crash
   ↓
Failure

6. «هر Error Message یعنی سیستم Failure دارد» ❌

فرض کنید کاربر رمز اشتباه وارد می‌کند.

سیستم نمایش می‌دهد:

❌ Invalid password

اگر Requirement دقیقاً همین رفتار را مشخص کرده باشد:

Failure نداریم.

چون سیستم درست کار کرده است.

Error Message ≠ Failure

7. «هر Failed Test یعنی Application Bug» ❌

این یکی برای Testerها بسیار مهم است. 🧪

Expected: 200
Actual: 400

آیا حتماً Application Bug دارد؟

نه.

  • Expected Result اشتباه باشد.
  • Test Case قدیمی باشد.
  • Test Data اشتباه باشد.
  • Environment مشکل داشته باشد.
  • Configuration تغییر کرده باشد.
  • API Contract تغییر کرده باشد.

Failed Test یک Signal برای Investigation است، نه اثبات قطعی Defect.

8. «اگر Bug در Production پیدا شود، پس Tester کارش را درست انجام نداده» ❌

این دیدگاه بیش از حد ساده‌انگارانه است.

هدف Testing این نیست که:

هیچ Defectی هرگز به Production نرسد.

این در سیستم‌های واقعی عملاً تضمین‌شدنی نیست.

هدف این است که:

ریسک را کاهش دهیم و Defectهای مهم را تا حد امکان زودتر کشف کنیم.

حتی سیستم‌هایی با:

  • Automation
  • CI/CD
  • Code Review
  • Extensive Testing

هم ممکن است Defect در Production داشته باشند.

مهم این است که تیم بتواند آن را سریع تشخیص دهد، تحلیل کند و از تکرار آن جلوگیری کند.

9. «Severity و Priority یکی هستند» ❌

این دو مفهوم مهم هستند، اما چون برای آن‌ها مقاله جداگانه‌ای داریم، در اینجا وارد جزئیات نمی‌شویم.

Severity به میزان اثر و شدت Defect مربوط است و Priority به فوریت رسیدگی به آن.

برای بررسی کامل تفاوت این دو مفهوم، می‌توانید به مقاله مستقل Severity و Priority در Defect مراجعه کنید.

نکته: این دو را نباید به جای یکدیگر استفاده کرد.

10. «Root Cause همان Defect است» ❌

این دو هم یکی نیستند.

فرض کنید:

سیستم مبلغ سفارش را اشتباه محاسبه می‌کند.

در Code یک شرط اشتباه پیدا می‌کنیم.

این:

🐞 Defect

است.

اما اگر بررسی کنیم چرا این شرط اشتباه نوشته شده و متوجه شویم:

Requirement مبهم بوده است.

این:

🧠 Root Cause احتمالی

است.

Root Cause
     ↓
Human Error
     ↓
Defect
     ↓
Failure

یک اشتباه مهم دیگر: «اگر Failure را دیدیم، همان Failure را Bug می‌نامیم» ⚠️

فرض کنید کاربر می‌گوید:

«پرداخت انجام نشد.»

این چیزی است که مشاهده شده و ممکن است یک Incident باشد.

بعد با تست مشخص می‌کنیم:

Failure رخ داده است.

بعد Investigation انجام می‌دهیم و در نهایت ممکن است مشخص شود:

🐞 Defect در Payment Service وجود دارد.

پس این اصطلاحات را نباید فقط به خاطر اینکه همه به یک مشکل مربوط هستند، جایگزین یکدیگر کنیم.

یک روش ساده برای جلوگیری از اشتباه 🧠

هر وقت با یک مشکل مواجه شدی، این پنج سؤال را بپرس:

سؤال اول: چه چیزی مشاهده کردم؟

ممکن است:

Incident / Failure

سؤال دوم: رفتار مورد انتظار چه بود؟

Requirement را بررسی کن.

سؤال سوم: علت رفتار واقعی چیست؟

Investigation انجام بده.

سؤال چهارم: آیا Defect وجود دارد؟

اگر بله، آن را مشخص کن.

سؤال پنجم: چرا این Defect ایجاد شد؟

Root Cause Analysis را بررسی کن.

یک مثال نهایی 🔎

کاربر می‌گوید:

«بعد از پرداخت، سفارش من ثبت نشده.»

❌ پاسخ ضعیف Tester

«Bug داریم.»

✅ پاسخ حرفه‌ای‌تر

«یک Incident گزارش شده است. در بررسی مشخص شد پس از Payment Success، Order Service سفارش را ایجاد نکرده است. رفتار واقعی با رفتار مورد انتظار متفاوت است، بنابراین Failure رخ داده و بررسی بیشتر برای شناسایی Defect و Root Cause موردنیاز است.»

⭐ 10 نکته‌ای که باید به خاطر بسپاریم

1. Error ≠ همیشه Defect
2. Defect ≠ همیشه Failure
3. Failure ≠ همیشه Software Bug
4. Bug ≈ Defect در بسیاری از Contextها
5. Exception ≠ Failure
6. Error Message ≠ Failure
7. Failed Test ≠ الزاماً Bug
8. Production Bug ≠ الزاماً شکست کامل فرآیند Testing
9. Severity ≠ Priority
10. Root Cause ≠ Defect

اگر این ده مورد را درست متوجه شده باشی، بخش بزرگی از ابهام رایج درباره Error، Defect و Failure برایت برطرف شده است. 🎯

این مفاهیم در کار واقعی Tester چه کاربردی دارند؟ 👨‍💻🧪

تا اینجا درباره مفاهیم Error، Defect، Bug، Failure، Incident و سایر اصطلاحات صحبت کردیم.

اما یک سؤال مهم باقی می‌ماند:

یک Tester در پروژه واقعی دقیقاً چه زمانی از این مفاهیم استفاده می‌کند؟

پاسخ این است: تقریباً در تمام چرخه کار QA. این مفاهیم فقط برای تعریف‌های تئوری نیستند؛ بلکه به Tester کمک می‌کنند بین مشاهده، Failure، Defect، علت مشکل و اقدام بعدی تفاوت بگذارد.

وقتی یک رفتار عجیب می‌بینی، سریع نگو «Bug است» 🧐

فرض کنیم در حال تست یک فروشگاه اینترنتی هستی.

روی دکمه Pay کلیک می‌کنی و هیچ اتفاقی نمی‌افتد.

اولین واکنش ممکن است این باشد:

«یک Bug پیدا کردم!»

اما Tester حرفه‌ای یک قدم عقب‌تر می‌ایستد و ابتدا سؤال‌های دقیق‌تری می‌پرسد:

  • Expected Result چه بوده است؟
  • Actual Result چیست؟
  • آیا می‌توان این رفتار را دوباره تولید کرد؟
  • آیا این رفتار برخلاف Requirement است؟

مرحله اول: مشاهده 🔍

در ابتدا بهتر است فقط آنچه را مشاهده کرده‌ایم ثبت کنیم و هنوز درباره علت قضاوت نکنیم.

Action:
Click Pay
Expected:
Payment gateway should open.
Actual:
Nothing happens.

در این مرحله هنوز بهتر است عجله نکنیم و نگوییم:

«Defect قطعی پیدا شد.»

فعلاً فقط با یک Unexpected Behavior مواجه شده‌ایم که نیاز به بررسی دارد.

مرحله دوم: بازتولید 🔄

Tester دوباره سناریو را اجرا می‌کند.

بار دوم همان اتفاق رخ می‌دهد.

بار سوم نیز همان رفتار مشاهده می‌شود.

حالا اطمینان ما نسبت به وجود یک رفتار غیرمنتظره بیشتر شده است و می‌توانیم بررسی دقیق‌تری انجام دهیم.

مرحله سوم: بررسی شرایط 🧪

در این مرحله Tester تلاش می‌کند مشخص کند مشکل تحت چه شرایطی رخ می‌دهد.

  • آیا فقط در یک Browser رخ می‌دهد؟
  • آیا فقط برای یک User اتفاق می‌افتد؟
  • آیا فقط برای یک Product رخ می‌دهد؟
  • آیا فقط در Production دیده می‌شود؟
  • آیا فقط با یک Payment Method رخ می‌دهد؟
  • آیا فقط وقتی Cart چند محصول دارد اتفاق می‌افتد؟

مثلاً Tester متوجه می‌شود:

این مشکل فقط در Chrome رخ می‌دهد.

همین اطلاعات می‌تواند برای Investigation و بازتولید مشکل بسیار ارزشمند باشد.

مرحله چهارم: مقایسه با Requirement 📄

حالا Tester Requirement را بررسی می‌کند.

فرض کنیم Requirement می‌گوید:

«بعد از کلیک روی Pay، کاربر باید به Payment Gateway منتقل شود.»

بنابراین:

Expected = Redirect
Actual   = Nothing

حالا شواهد قوی‌تری داریم که نشان می‌دهد هنگام اجرای سیستم، Failure رخ داده است.

مرحله پنجم: ثبت Defect 🐞

پس از بررسی و جمع‌آوری شواهد، Tester می‌تواند یک Defect واضح و قابل بررسی ثبت کند.

Title

Payment button does not redirect Chrome users to the payment gateway

Environment

Chrome 151
Windows
Production-like Environment

Steps to Reproduce

1. Login
2. Add product to cart
3. Open checkout
4. Click Pay

Expected Result

User should be redirected to the payment gateway.

Actual Result

Nothing happens after clicking Pay.

Evidence

  • Screenshot
  • Video
  • Console Log
  • Network Log

در این مرحله می‌توانیم با اطمینان بیشتری بگوییم:

یک Defect گزارش شده است.

Tester لزوماً Root Cause را پیدا نمی‌کند 🔎

یکی از نکات مهم در کار حرفه‌ای Tester این است که وظیفه Tester همیشه پیدا کردن خط دقیق Code یا علت فنی نهایی نیست.

Tester باید بتواند:

  • مشکل را دقیق مشاهده کند.
  • آن را بازتولید کند.
  • شرایط وقوع را مشخص کند.
  • Expected و Actual Result را مقایسه کند.
  • شواهد مناسب جمع‌آوری کند.
  • Defect را به شکل واضح گزارش کند.

Developer ممکن است بعداً مشخص کند:

Payment API
      ↓
Returns 500
      ↓
Frontend ignores error

در این حالت، Investigation فنی علت دقیق‌تری را مشخص کرده است.

چرا این تفاوت مهم است؟ 🎯

فرض کنیم Tester در گزارش خود بنویسد:

«Payment API bug دارد.»

اگر هنوز شواهدی برای این نتیجه وجود نداشته باشد، این گزارش چندان دقیق نیست.

گزارش بهتر می‌تواند این باشد:

«Clicking Pay produces no visible response in Chrome. Network inspection shows the Payment API returns HTTP 500.»

گزارش دوم اطلاعات قابل بررسی‌تری در اختیار تیم قرار می‌دهد و به Developer کمک می‌کند Investigation را سریع‌تر شروع کند.

Tester باید Failure را از Defect جدا کند ⚠️

فرض کنیم نتیجه تست این باشد:

Expected:
200 OK
Actual:
500 Internal Server Error

این نتیجه نشان‌دهنده یک Failure در رفتار مورد انتظار سیستم است.

اما هنوز باید علت آن بررسی شود.

Failure
   ↓
Payment API Defect

ممکن است علت چیز دیگری باشد:

Failure
   ↓
Database Unavailable
Failure
   ↓
Third-party Payment Gateway

بنابراین:

Tester باید بین مشاهده یک Failure و تشخیص علت آن تفاوت بگذارد.

Static Testing در کار Tester 🔍

این مفاهیم حتی قبل از اجرای نرم‌افزار نیز کاربرد دارند.

فرض کنید Tester در حال Review کردن Requirement است:

«کاربر می‌تواند سفارش را در هر زمانی لغو کند.»

Tester سؤال می‌کند:

«حتی بعد از Shipped؟»

Product Owner پاسخ می‌دهد:

«نه، بعد از Shipped نباید امکان لغو وجود داشته باشد.»

Tester در اینجا یک ابهام مهم را قبل از Development پیدا کرده است. این نمونه‌ای از Static Testing است.

جلوگیری از ایجاد Defect قبل از اجرای نرم‌افزار 🛡️

اگر ابهام Requirement برطرف نمی‌شد، ممکن بود چنین زنجیره‌ای ایجاد شود:

Ambiguous Requirement
        ↓
Developer Interpretation
        ↓
Wrong Implementation
        ↓
Defect
        ↓
Failure

اما Tester با بررسی Requirement می‌تواند این مسیر را متوقف کند:

Requirement Review
       ↓
Ambiguity Found
       ↓
Requirement Clarified
       ↓
No Defect
       ↓
No Failure

این یکی از ارزش‌های مهم QA است: کشف زودهنگام مشکلات قبل از تبدیل شدن آن‌ها به Failure و Incident.

در Automation Testing چه اتفاقی می‌افتد؟ 🤖

فرض کنید یک Automated Test داریم:

expect(response.status).toBe(200)

و تست Fail می‌شود:

Expected: 200
Received: 500

آیا Automation Test گفته است که حتماً یک Bug وجود دارد؟

خیر.

Automation فقط نشان داده است که Assertion مورد انتظار برقرار نشده است. حالا باید Investigation انجام شود.

  • ممکن است API Defect وجود داشته باشد.
  • ممکن است Test Environment مشکل داشته باشد.
  • ممکن است Test Data اشتباه باشد.
  • ممکن است Expected Result دیگر معتبر نباشد.

اینجا QA حرفه‌ای اهمیت پیدا می‌کند 🚀

Automation می‌تواند بگوید:

❌ Test Failed

اما Tester باید بتواند سؤال‌های بعدی را مطرح کند:

  • Why? چرا تست Fail شد؟
  • Is it a Defect? آیا واقعاً Defect وجود دارد؟
  • What is the Impact? اثر این مشکل چیست؟
  • What should happen next? اقدام بعدی چیست؟

Severity و Priority در کار روزمره 🎯

در یک Sprint ممکن است تعداد زیادی Defect ثبت شود و تیم نتواند همه آن‌ها را هم‌زمان اصلاح کند.

در اینجا Severity و Priority به تصمیم‌گیری درباره Defectها کمک می‌کنند، اما جزئیات تعریف، سطوح و تفاوت این دو را در مقاله اختصاصی آن‌ها بررسی کرده‌ایم.

برای مطالعه کامل: Severity و Priority را می‌توانید در مقاله اختصاصی مربوط به این موضوع بررسی کنید.

وقتی Defect به Production می‌رسد چه می‌کنیم؟ 🚨

فرض کنیم یک Defect از تست‌ها عبور کرده و وارد Production شده است و کاربر آن را گزارش می‌کند.

در چنین شرایطی تیم معمولاً باید:

  1. Incident را ثبت و بررسی کند.
  2. Impact را مشخص کند.
  3. Failure را بررسی کند.
  4. علت احتمالی را پیدا کند.
  5. در صورت وجود Defect، آن را اصلاح کند.
  6. Retest انجام دهد.
  7. Regression Testing انجام دهد.
  8. اقدامات Prevention را بررسی کند.

Prevention؛ فقط Fix کردن کافی نیست 🛡️

QA فقط نباید بپرسد:

«Bug را چطور Fix کنیم؟»

یک سؤال مهم‌تر این است:

«چطور کاری کنیم این مشکل دوباره اتفاق نیفتد؟»

مثلاً اگر علت مشکل Requirement مبهم بوده است، شاید نیاز به بهبود Requirement Review داشته باشیم.

اگر مشکل به دلیل نبودن Regression Test ایجاد شده باشد، ممکن است اضافه کردن Test Case یا Automated Test مناسب باشد.

اگر Configuration اشتباه باعث مشکل شده باشد، شاید Deployment Process نیاز به بهبود داشته باشد.

یک Tester حرفه‌ای فقط Bug Finder نیست 🚀

نگاه سنتی ممکن است Tester را فقط به‌عنوان فردی ببیند که Bug پیدا می‌کند.

اما در یک تیم مدرن QA، Tester می‌تواند در بخش‌های مختلف چرخه کیفیت نقش داشته باشد:

  • Review کردن Requirement
  • تحلیل Risk
  • پیشنهاد Test Strategy
  • شناسایی و گزارش Defect
  • تحلیل Failure
  • ایجاد یا بهبود Automation Test
  • اجرای Regression Testing
  • پشتیبانی از بررسی Production Incident
  • مشارکت در Root Cause Analysis
  • پیشنهاد اقدامات Prevention

بنابراین:

Tester فقط کسی نیست که Bug پیدا می‌کند؛ Tester یکی از افراد مؤثر در کاهش ریسک کیفیت محصول است.

🧠 مدل ذهنی کاربردی برای Tester

هر زمان در یک پروژه واقعی با رفتار غیرمنتظره‌ای مواجه شدی، می‌توانی این مسیر ذهنی را دنبال کنی:

مشاهده مشکل
     ↓
Expected vs Actual
     ↓
Reproduce
     ↓
بررسی شرایط
     ↓
بررسی Requirement
     ↓
Failure یا رفتار مورد انتظار؟
     ↓
Investigation
     ↓
آیا Defect وجود دارد؟
     ↙             ↘
   Yes              No
    ↓                ↓
اقدام مناسب       بررسی سایر علت‌ها
    ↓
Fix
    ↓
Retest
    ↓
Regression
    ↓
Closed
    ↓
Prevention

⭐ مهم‌ترین درس این بخش

وقتی در پروژه واقعی با یک مشکل مواجه شدی، فوراً اسم آن را Bug نگذار.

اول بپرس:

چه چیزی مشاهده کردم؟

بعد:

رفتار مورد انتظار چه بوده است؟

سپس:

آیا Failure رخ داده است؟

بعد از آن:

علت چیست و آیا Defect وجود دارد؟

این رویکرد کمک می‌کند به جای اینکه فقط مشکل پیدا کنی، بتوانی آن را درست تحلیل و توصیف کنی.

و این دقیقاً یکی از مهارت‌هایی است که یک Tester را از یک Bug Reporter ساده به یک QA حرفه‌ای نزدیک می‌کند. 🎯

منابع و مراجع مقاله 📚

مفاهیم مطرح‌شده در این مقاله، به‌ویژه رابطه میان Error، Defect و Failure، تفاوت Static و Dynamic Testing و اصطلاحات مرتبط با تست نرم‌افزار، بر اساس منابع معتبر حوزه Software Testing تدوین شده‌اند.

  1. ISTQB — Certified Tester Foundation Level (CTFL) v4.0.1
    مرجع اصلی مقاله برای مفاهیمی مانند Error، Defect، Failure، Root Cause و همچنین Static و Dynamic Testing.
  2. ISTQB — Official Glossary
    مرجع رسمی برای بررسی و درک اصطلاحات تخصصی Software Testing و Quality Assurance.
  3. ISTQB — CTFL v4.0 Sample Exam & Answers
    نمونه سؤالات و پاسخ‌های رسمی برای درک کاربردی‌تر مفاهیم مطرح‌شده در CTFL.

⭐ برای مطالعه عمیق‌تر مفاهیم این مقاله، پیشنهاد می‌شود ابتدا CTFL v4.0.1 و سپس ISTQB Official Glossary را بررسی کنید.

سوالات متداول درباره Error، Defect و Failure

آیا Error و Mistake یکی هستند؟

در بسیاری از منابع و مکالمات Software Testing، Error و Mistake برای اشاره به یک خطا یا اشتباه انسانی استفاده می‌شوند و مرز کاملاً ثابتی بین آن‌ها وجود ندارد. بنابراین بهتر است آن‌ها را به‌عنوان دو مرحله کاملاً جدا و اجباری در یک زنجیره در نظر نگیریم.

آیا هر Error به Defect تبدیل می‌شود؟

خیر. ممکن است یک Developer هنگام انجام کار دچار اشتباه شود، اما خودش یا فرد دیگری آن را در Code Review یا Static Testing پیدا و قبل از ورود به محصول اصلاح کند. بنابراین Error می‌تواند منجر به Defect شود، اما الزاماً این اتفاق رخ نمی‌دهد.

آیا Bug و Defect با هم فرق دارند؟

در بسیاری از Contextهای Software Testing، Bug و Defect به جای یکدیگر استفاده می‌شوند. Bug بیشتر یک اصطلاح رایج و غیررسمی در صنعت نرم‌افزار است، در حالی که Defect اصطلاح رسمی‌تر و گسترده‌تری است و می‌تواند برای Requirement، Design، Code و سایر Work Productها نیز استفاده شود.

چرا بعضی‌ها به Defect می‌گویند Bug؟

Bug یک اصطلاح بسیار رایج در صنعت نرم‌افزار است و به مرور زمان به واژه‌ای عمومی برای اشاره به مشکل یا نقص نرم‌افزار تبدیل شده است. به همین دلیل در مکالمات روزمره Tester و Developer ممکن است به یک Defect، Bug گفته شود.

آیا هر Defect باعث Failure می‌شود؟

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

آیا برای پیدا کردن Defect حتماً باید نرم‌افزار را اجرا کنیم؟

خیر. Defectها می‌توانند از طریق Requirement Review، Design Review، Code Review و Static Analysis نیز قبل از اجرای نرم‌افزار شناسایی شوند. این فعالیت‌ها در حوزه Static Testing قرار می‌گیرند.

Static Defect و Dynamic Defect یعنی چه؟

اصطلاحات رسمی‌تر و رایج‌تر، Static Testing و Dynamic Testing هستند. بهتر است به جای اینکه بگوییم «Static Defect»، بگوییم یک Defect با استفاده از Static Testing شناسایی شده است یا یک Defect هنگام Dynamic Testing و اجرای سیستم آشکار شده است.

آیا Failure همان Defect است؟

خیر. Defect به یک نقص موجود در یک Work Product یا سیستم اشاره دارد، در حالی که Failure زمانی رخ می‌دهد که سیستم هنگام اجرا نتواند رفتار مورد انتظار را ارائه کند. یک Defect ممکن است در صورت فعال شدن هنگام Execution باعث Failure شود.

آیا Failure همان Incident است؟

خیر. Failure به رفتار نامطلوب سیستم هنگام اجرا اشاره دارد، در حالی که Incident یک رخداد یا وضعیت غیرمنتظره است که نیاز به بررسی یا رسیدگی دارد. یک Failure می‌تواند منجر به ثبت یا مدیریت یک Incident شود.

آیا هر Incident ناشی از Defect نرم‌افزار است؟

خیر. Incident می‌تواند ناشی از Software Defect، مشکل زیرساخت، Network Problem، Configuration، سرویس‌های شخص ثالث، Deployment یا مشکلات داده باشد. بنابراین Incident به‌تنهایی علت مشکل را مشخص نمی‌کند.

آیا Exception همان Failure است؟

خیر. Exception یک رویداد در سطح برنامه یا Runtime است که ممکن است توسط نرم‌افزار به‌درستی مدیریت شود. Exception زمانی می‌تواند به Failure منجر شود که باعث شود سیستم رفتار مورد انتظار را ارائه نکند.

آیا هر Error Message نشانه وجود Bug است؟

خیر. برای مثال اگر کاربر رمز عبور اشتباه وارد کند و سیستم پیام «Invalid password» نمایش دهد، اگر این رفتار مطابق Requirement باشد، Bug یا Failure نداریم. بنابراین Error Message را نباید با Error انسانی، Defect یا Failure یکی دانست.

آیا هر Failed Test یعنی Bug داریم؟

خیر. Failed Test فقط نشان می‌دهد نتیجه تست با انتظار تعریف‌شده مطابقت نداشته است. علت می‌تواند Application Defect، Test Case اشتباه، Test Data، Environment، Configuration یا حتی Expected Result نادرست باشد. بنابراین Failed Test یک سیگنال برای Investigation است، نه اثبات قطعی Bug.

اگر Bug در Production پیدا شود، یعنی Testing شکست خورده است؟

نه لزوماً. هدف Testing این نیست که تضمین کند هیچ Defectی وارد Production نمی‌شود. هدف اصلی Testing کاهش ریسک و شناسایی هرچه زودتر Defectهای مهم است. اگر Defectی وارد Production شود، باید علاوه بر رفع آن، علت کشف نشدن و راه‌های جلوگیری از تکرار آن نیز بررسی شود.

Severity و Priority چه تفاوتی دارند؟

Severity نشان می‌دهد یک Defect از نظر تأثیر و شدت چقدر جدی است، در حالی که Priority نشان می‌دهد اصلاح آن چقدر فوریت دارد. بنابراین یک Defect می‌تواند Severity پایین اما Priority بالا داشته باشد.

آیا Root Cause همان Defect است؟

خیر. Defect خودِ نقص موجود در محصول یا Work Product است، اما Root Cause به علت ریشه‌ای ایجاد آن مشکل اشاره می‌کند. برای مثال یک شرط اشتباه در Code می‌تواند Defect باشد، در حالی که Requirement مبهمی که باعث نوشته شدن آن Code شده، ممکن است یکی از Root Causeها باشد.

آیا Tester باید همیشه Root Cause را پیدا کند؟

خیر. وظیفه Tester این است که رفتار غیرمنتظره را به‌درستی مشاهده، بررسی، بازتولید و گزارش کند. پیدا کردن Root Cause ممکن است با همکاری Tester، Developer، DevOps، Product و سایر اعضای تیم انجام شود.

طبقه بندی شده در:

دسته‌بندی نشده,

اخرین بروزرسانی: مرداد 27, 1405