وقتی وارد دنیای تست نرمافزار میشوید، خیلی زود با چند واژه روبهرو میشوید که در ظاهر شبیه هم هستند:
- Error — خطا یا اشتباه
- Defect — نقص یا اشکال
- Bug — باگ
- Failure — شکست یا خرابی
- Incident — رخداد یا رویداد
در گفتوگوی روزمره تیمهای نرمافزاری، ممکن است همه این مفاهیم را با یک جمله ساده بیان کنیم:
«یه مشکلی توی نرمافزار هست.»
اما در تست نرم افزار، این مشکل میتواند در مراحل مختلف ایجاد یا مشاهده شود و هر اصطلاح، زاویه متفاوتی از آن را توصیف میکند.
خطا(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 Testing | Dynamic Testing |
|---|---|---|
| اجرای نرمافزار | ❌ بدون اجرا | ✅ با اجرا |
| هدف | پیدا کردن مشکلات در Work Product | بررسی رفتار سیستم |
| مثال | Review، Inspection، Static Analysis | Functional 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 پیدا کردم» نیست؛ بلکه باید بتواند:
- رفتار نادرست را مشاهده کند.
- Failure را دقیق توصیف کند.
- شرایط بازتولید را مشخص کند.
- شواهد جمعآوری کند.
- در صورت امکان 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 مواجه شدی، این چهار سؤال را از خودت بپرس:
- چه چیزی را مشاهده کردیم؟
→ Failure - چه نقصی باعث آن شد؟
→ Defect - چرا این Defect ایجاد شد؟
→ Root Cause - چرا زودتر پیدا نشد و چگونه از تکرار آن جلوگیری کنیم؟
→ 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 پیدا کردم!»
بهتر است چند سؤال پشت سر هم بپرسی:
- رفتار مورد انتظار چه بوده؟
- رفتار واقعی چه بوده؟
- آیا واقعاً Failure رخ داده؟
- علت این Failure چیست؟
- آیا Defectی وجود دارد؟
- این Defect در کدام Work Product قرار دارد؟
- چرا این Defect زودتر پیدا نشده؟
- چگونه از تکرار آن جلوگیری کنیم؟
این نوع تفکر باعث میشود 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
ثبت شده باشد.
این یک مثال ساده است که نشان میدهد یک مشکل واقعی میتواند از چند زاویه مختلف با واژههای متفاوت توصیف شود.
🏆 اگر فقط ۹ جمله از این مقاله را به خاطر بسپارید
- Error / Mistake = انسان اشتباه میکند.
- Defect = یک نقص در Work Product وجود دارد.
- Bug = اصطلاح رایج برای مشکل یا نقص نرمافزار است.
- Fault = در برخی منابع به یک نقص/عامل فنی اشاره دارد که میتواند باعث رفتار نادرست شود.
- Failure = سیستم هنگام اجرا رفتار مورد انتظار را ارائه نمیکند.
- Incident = یک رخداد یا وضعیت غیرمنتظره که نیاز به بررسی یا رسیدگی دارد.
- Issue = یک مورد عمومی که باید ثبت و پیگیری شود.
- Problem = یک مشکل یا علت بنیادی مرتبط با یک یا چند Incident.
- 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 معمولاً باید:
- نرمافزار اجرا شود.
- شرایط لازم فراهم شود.
- Defect فعال شود.
- رفتار واقعی با رفتار مورد انتظار متفاوت باشد.
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 شده است و کاربر آن را گزارش میکند.
در چنین شرایطی تیم معمولاً باید:
- Incident را ثبت و بررسی کند.
- Impact را مشخص کند.
- Failure را بررسی کند.
- علت احتمالی را پیدا کند.
- در صورت وجود Defect، آن را اصلاح کند.
- Retest انجام دهد.
- Regression Testing انجام دهد.
- اقدامات 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 تدوین شدهاند.
-
ISTQB — Certified Tester Foundation Level (CTFL) v4.0.1
مرجع اصلی مقاله برای مفاهیمی مانند Error، Defect، Failure، Root Cause و همچنین Static و Dynamic Testing. -
ISTQB — Official Glossary
مرجع رسمی برای بررسی و درک اصطلاحات تخصصی Software Testing و Quality Assurance. -
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 و سایر اعضای تیم انجام شود.
