الاختبار الإيجابي والسلبي

الاختبار الإيجابي (Positive Testing) يتحقق من أن النظام يفعل ما يجب عليه حين يُستخدم كما صُمّم: بيانات صالحة، وإجراءات مسموح بها، وخطوات بالترتيب المتوقع. أما الاختبار السلبي (Negative Testing)، كما يعرّفه مسرد ISTQB، فيختبر النظام بطريقة لم يُقصد استخدامه بها: بيانات ناقصة أو غير صالحة، أو إجراء في حالة خاطئة، أو مستخدم بلا صلاحية. وتُدرج فرق كثيرة فيه أيضاً ظروف الأعطال، مثل خدمة لا تستجيب.

في صفحة الدفع، إدخال رمز الخصم الحالي SAVE20 ورؤية الخصم اختبار إيجابي. وإدخال RAMADAN24، الذي انتهت صلاحيته أمس، ثم التحقق من رفضه برسالة واضحة مع بقاء الإجمالي كما هو، اختبار سلبي.

لماذا يهم

يخطئ المستخدمون في الكتابة، ويتركون الحقول فارغة، ويضغطون «رجوع» في اللحظة الخطأ، وتتأخر الأنظمة الأخرى في الرد. والمنتج الذي لا يعمل إلا على المسار السعيد قد يُضيّع ما أدخله المستخدم بسبب خطأ واحد، أو يردّ على طلب غير صالح بخطأ في الخادم، أو يخصم من العميل مرتين. هذه عيوب في الشيفرة التي تعالج غير المتوقع، وتصل إلى بيئة الإنتاج حين لا يصمّم أحد اختباراً لها.

يجرّب المطورون المسار السعيد عادةً قبل تسليم الميزة، أما مسارات الرفض فاحتمال تجربتها أقل، لذا تكشف الاختبارات السلبية جزءاً كبيراً من المخاطر الخفية. ومع ذلك تبقى الاختبارات الإيجابية أساسية: فهي تثبت أن الميزة تحقق غرضها.

الاختبار الإيجابي والمسار السعيد

يستخدم الاختبار الإيجابي بيانات صالحة وتسلسلاً مسموحاً به من الإجراءات، ويتوقع النجاح: مخرجات صحيحة، وبيانات محفوظة بشكل صحيح، وآثاراً جانبية صحيحة مثل رسالة التأكيد بالبريد. وكما في درس الاختبار الوظيفي، تأتي النتيجة المتوقعة من أساس الاختبار، لا مما يفعله النظام صدفةً.

المسار السعيد (Happy Path) هو السيناريو الرئيسي الذي يسير فيه كل شيء كما خُطّط له: بيانات معتادة، وخيارات افتراضية، بلا أخطاء. وتسميه بعض الفرق «سيناريو النجاح الرئيسي» (Main success scenario). وللميزة مسار سعيد واحد، لكن لها عادةً عدة اختبارات إيجابية، لأن هناك أكثر من طريقة صالحة للنجاح.

  • المسار السعيد: سلة بقيمة ⁦250.00⁩ ريالاً مع الرمز SAVE20 (خصم ⁦20%⁩) تعطي خصماً قدره ⁦50.00⁩ ريالاً وإجمالياً قدره ⁦200.00⁩ ريال.
  • تنويعات صالحة: save20 بأحرف صغيرة يعمل أيضاً، لأن الرموز لا تميّز بين الأحرف الكبيرة والصغيرة؛ وإزالة الرمز تعيد الإجمالي إلى ⁦250.00⁩ ريالاً.

جرّبها: مولّد الاختبارات الإيجابية

الاختبار السلبي: مدخلات غير صالحة واستخدام غير مقصود

يعطي الاختبار السلبي النظامَ عمداً شيئاً لا ينبغي أن يقبله، ويتوقع رفضاً مضبوطاً. ينجح الاختبار حين يرفض النظام تماماً كما هو محدد، ويفشل حين يقبل النظام المدخل، أو ينهار، أو يرفض بطريقة مؤذية، كأن يمسح النموذج كله.

أساس الاختبار هو ما يحدد ما يُعدّ غير صالح، وستقابل الفكرة نفسها باسم أقسام التكافؤ غير الصالحة في وحدة تصميم الاختبار. ابحث عن الاختبارات السلبية في هذه الفئات:

  • بيانات ناقصة: حقل إلزامي فارغ، أو طلب API بلا جسم.
  • صيغة أو نوع خاطئ: أحرف في حقل المبلغ، أو بريد إلكتروني بلا @، أو التاريخ ⁦31/02/2026⁩.
  • خارج النطاق: كمية ⁦0⁩ أو ⁦-1⁩.
  • حالة أو ترتيب خاطئ: RAMADAN24 بعد تاريخ انتهائه، أو دفع ثمن طلب مدفوع مسبقاً.
  • بلا صلاحية: فتح طلب عميل آخر، على أنظمة تملكها أو لديك إذن مكتوب باختبارها فقط.
  • تعطّل خدمة يعتمد عليها النظام: انتهاء مهلة مزوّد الدفع.
رمز الخصم في صفحة الدفع: ينجح الاختبار الإيجابي حين يُطبَّق SAVE20، وينجح الاختبار السلبي حين يُرفض الرمز المنتهي RAMADAN24 برسالة واضحة ويبقى الإجمالي ⁦250.00⁩ ريالاً.

الاختبار الإيجابي

مدخلات صالحة واستخدام مقصود

السؤال الذي يجيب عنه:
هل يعمل حين يُستخدم كما صُمّم؟
المدخلات المعتادة:
بيانات صالحة، وإجراءات مسموح بها، والترتيب المتوقع
مثال:
SAVE20 على سلة بقيمة ⁦250.00⁩ ريالاً
النتيجة المتوقعة:
خصم ⁦50.00⁩، والإجمالي ⁦200.00⁩، والرمز يظهر مطبَّقاً
ينجح الاختبار حين:
ينجح الإجراء كما هو محددنجاح
يظهر العيب في صورة:
نتيجة خاطئة، أو رفض مدخلات صالحةفشل

الاختبار السلبي

مدخلات غير صالحة أو استخدام غير مقصود

السؤال الذي يجيب عنه:
هل يرفض بأمان حين يُستخدم خطأً؟
المدخلات المعتادة:
بيانات ناقصة، وصيغة خاطئة، وخارج النطاق، وحالة خاطئة، وبلا صلاحية، وتعطّل خدمة
مثال:
RAMADAN24 الذي انتهى أمس
النتيجة المتوقعة:
«انتهت صلاحية هذا الرمز»، والإجمالي ما زال ⁦250.00⁩، ولا تظهر تفاصيل داخلية
ينجح الاختبار حين:
يُرفض الإجراء كما هو محددنجاح
يظهر العيب في صورة:
قبول مدخلات غير صالحة، أو خطأ 500، أو رسالة مبهمة، أو بيانات تغيّرتفشل

كلاهما اختبار يُفترض أن ينجح: كلمة «سلبي» تصف المدخلات والقصد، لا النتيجة.

جرّبها: مولّد الاختبارات السلبية جرّبها: مولّد اختبارات التحقق

معالجة الأخطاء المتوقعة: كيف يبدو الرفض الصحيح

عبارة «تظهر رسالة خطأ» ليست نتيجة متوقعة، لأن أي سلوك تقريباً سيجتازها. اكتب أجزاء الرفض الصحيح:

على مستوى الواجهة البرمجية (API) يرسل الطلب أدناه الرمز المنتهي. ويتحقق الاختبار من رمز الحالة ومن جسم الرد، ثم يؤكد طلب ثانٍ، GET /api/cart، أن الإجمالي ما زال ⁦250.00⁩ ريالاً.

  • رسالة محددة، مكتوبة نصاً بجوار الحقل، تقول ما الذي يجب تصحيحه. والتحديد لا يعني الكشف: فنموذج تسجيل الدخول يقول إن البريد أو كلمة المرور غير صحيحة، لا أيهما.
  • لا تغيير آخر: لا يُنشأ سجل، ولا تتحرك أموال، ولا تُرسل رسالة بريد، ويبقى ما أدخله المستخدم.
  • لا تفاصيل داخلية: لا تتبّع مكدس (stack trace) ولا خطأ SQL. وتوصي ورقة OWASP المرجعية لمعالجة الأخطاء (Error Handling Cheat Sheet) برسالة عامة للمستخدم وبحفظ التفاصيل في سجل الخادم.
  • رمز الحالة الذي يحدده عقد الواجهة البرمجية. ويستخدم RFC 9110 الفئة 4xx للأخطاء في طلب العميل والفئة 5xx لأخطاء الخادم، لذا تحصل البيانات غير الصالحة على رمز من فئة 4xx مثل 400 أو 422، وليس 500 أبداً.
  • التعافي: بعد تصحيح المدخل، يعمل المسار الإيجابي دون البدء من جديد.
POST /api/cart/discount HTTP/1.1
Host: shop.example.com
Content-Type: application/json

{"code": "RAMADAN24"}

HTTP/1.1 422 Unprocessable Content
Content-Type: application/json

{"error": "code_expired", "message": "This discount code has expired."}

جرّبها: محاكي رموز حالة API جرّبها: مولّد استجابات خطأ وهمية

مثال تطبيقي: اختبارات رمز الخصم

المتطلب: «في صفحة الدفع يستطيع العميل تطبيق رمز خصم واحد. يعمل الرمز فقط بين تاريخَي بدايته ونهايته، ومرة واحدة لكل عميل، ولا يميّز بين الأحرف الكبيرة والصغيرة». وتحتوي السلة على منتجات مؤهلة بقيمة ⁦250.00⁩ ريالاً.

ابدأ بالمسار السعيد، ثم اجعل في كل اختبار سلبي شرطاً واحداً غير صالح، حتى يشير أي فشل إلى قاعدة واحدة بعينها. وفي الاختبارات من DC-03 إلى DC-06 يجب أن يبقى الإجمالي ⁦250.00⁩ ريالاً. وتصميم الاختبارات السلبية يكشف أيضاً ثغرات في المتطلب، كما يُظهر DC-07.

  • DC-01، إيجابي (المسار السعيد): SAVE20 ← خصم ⁦50.00⁩، والإجمالي ⁦200.00⁩.
  • DC-02، إيجابي: save20 ← النتيجة نفسها كما في DC-01.
  • DC-03، سلبي: الضغط على «تطبيق» والحقل فارغ ← «أدخل رمز الخصم».
  • DC-04، سلبي: NOPE99، وهو رمز غير موجود ← «هذا الرمز غير صالح».
  • DC-05، سلبي: RAMADAN24 الذي انتهى أمس ← «انتهت صلاحية هذا الرمز».
  • DC-06، سلبي: SAVE20 للمرة الثانية من العميل نفسه ← «لقد استخدمت هذا الرمز من قبل».
  • DC-07، سؤال مفتوح: WELCOME10 بينما SAVE20 مطبَّق. هل يحل محل الرمز الأول أم يُرفض؟ اسأل مالك المنتج قبل كتابة النتيجة المتوقعة.

أخطاء شائعة

  • اختبار المسار السعيد وحده، لأنه ما يظهر في العرض التوضيحي وفي معايير القبول.
  • كتابة «تظهر رسالة خطأ» نتيجةً متوقعة، دون نص الرسالة بالضبط أو ما يجب أن يبقى دون تغيير.
  • وضع عدة قيم غير صالحة في اختبار واحد: فالخطأ الأول يُخفي البقية.
  • تسجيل الاختبار السلبي فاشلاً لأن رسالة خطأ ظهرت، مع أن تلك الرسالة هي النتيجة المتوقعة.
  • فحص الشاشة وحدها: تظهر الرسالة، لكن الطلب أُنشئ رغم ذلك.
  • اختبار المدخلات غير الصالحة عبر النموذج فقط، بينما تقبل الواجهة البرمجية خلفه البيانات نفسها. أرسلها إلى الواجهة البرمجية أيضاً، على نظام مسموح لك باختباره.

من منظور ضمان الجودة

يبدأ الاختبار السلبي أثناء تنقيح قائمة المهام (Backlog refinement). اسأل عند كل معيار قبول: «وماذا لو لم يحدث ذلك؟»: مدخل ناقص، أو حالة خاطئة، أو غياب الصلاحية، أو تعطّل خدمة الدفع. كثيراً ما تصف قصص المستخدم المسار السعيد وحده، لذا تكشف هذه الأسئلة سلوك أخطاء لم يحدده أحد بعد. اتفق على نصوص الرسائل مع مالك المنتج، وعلى رموز الحالة مع المطورين، قبل بدء البرمجة.

صنّف كل حالة اختبار إيجابيةً أو سلبيةً حتى يمكن تصفية حزم الاختبارات. ونفّذ المسار السعيد أولاً: فإن كان معطلاً فأبلغ عنه فوراً، لأنه يعيق تنفيذ معظم الاختبارات الأخرى. ويذكر تقرير الخطأ لاختبار سلبي فاشل المدخل بالضبط، والرفض المتوقع، والسلوك الفعلي، وأي أثر جانبي. وتتبع الخطورة العاقبة: الرسالة غير الواضحة عادةً ثانوية (Minor)، أما حفظ بيانات غير صالحة أو تحريك أموال فحرج (Critical).

تمرين عملي

صمّم اختبارات إيجابية وسلبية لتحويل مالي

المطلوب

في تطبيق مصرفي المتطلب التالي: «يستطيع العميل المسجَّل دخوله تحويل المال بين حسابين من حساباته. يجب أن يكون المبلغ أكبر من ⁦0⁩، وبمنزلتين عشريتين على الأكثر، وألا يتجاوز الرصيد المتاح ولا ⁦20,000.00⁩ ريال مجموعاً في اليوم. ويجب أن يختلف الحساب المصدر عن الحساب الوجهة. وبعد التحويل الناجح يُحدَّث الرصيدان ويظهر رقم مرجعي».

صمّم الاختبارات على الورق، ثم قارن قائمتك بأداتي Positive Test Generator وNegative Test Generator.

الخطوات
  1. اكتب المسار السعيد ببيانات محددة ونتيجة متوقعة، ثم اختبارين إيجابيين آخرين.
  2. اكتب اختباراً سلبياً واحداً على الأقل لكل فئة من فئات هذا الدرس، بشرط واحد غير صالح في كل منها.
  3. اكتب لكل اختبار سلبي معالجة الأخطاء المتوقعة.
  4. اكتب الأسئلة التي يتركها المتطلب دون إجابة.
إظهار الإجابة النموذجية
الإجابة النموذجية

إيجابية: تحويل ⁦500.00⁩ ريال من الحساب الجاري (المتاح ⁦2,000.00⁩) إلى التوفير ينجح مع رقم مرجعي؛ ويصبح رصيد الجاري ⁦1,500.00⁩ ويزيد التوفير بمقدار ⁦500.00⁩. هذا هو المسار السعيد. وأيضاً: تحويل ⁦125.50⁩ ريالاً ينجح، والتحويل من التوفير إلى الجاري ينجح.

سلبية: مبلغ فارغ («أدخل المبلغ»)؛ abc («أدخل مبلغاً صالحاً»)؛ ⁦0⁩ و⁦-100⁩ («يجب أن يكون المبلغ أكبر من ⁦0⁩»)؛ ⁦12.345⁩ («استخدم منزلتين عشريتين على الأكثر»)؛ ⁦2,500.00⁩ والمتاح ⁦2,000.00⁩ («الرصيد غير كافٍ»)؛ الحساب نفسه في الطرفين («اختر حساباً مختلفاً»)؛ ⁦600.00⁩ بعد تحويل ⁦19,800.00⁩ اليوم («تم تجاوز الحد اليومي»).

الحالة والصلاحية والخدمات: تنتهي الجلسة قبل «تأكيد» (لا تحويل)؛ رقم حساب لعميل آخر يُرسل عبر الواجهة البرمجية في بيئة الاختبار الخاصة بك (يُرفض برمز من فئة 4xx ولا يتحرك شيء)؛ خدمة النظام المصرفي الأساسي لا تستجيب (رسالة واضحة «حاول لاحقاً»، ولا يخرج المال من الجاري دون أن يصل إلى التوفير).

معالجة الأخطاء في كل اختبار سلبي: الرصيدان دون تغيير، ولا رقم مرجعي، ولا قيد في السجل، ويبقى ما أدخله المستخدم، ولا تفاصيل تقنية.

أسئلة: أي منطقة زمنية تحدد «اليوم»؟ هل الحد لكل عميل أم لكل حساب؟ ماذا يرى العميل إذا انقطع الاتصال بعد «تأكيد»؟

أسئلة شائعة

إذا نجح اختبار سلبي، فهل يعني ذلك أن النظام فشل؟

لا. ينجح الاختبار حين تطابق النتيجة الفعلية النتيجة المتوقعة. والنتيجة المتوقعة في الاختبار السلبي هي رفض صحيح، فينجح الاختبار حين يرفض النظام المدخل كما هو محدد. أما إذا قبل النظام الرمز المنتهي، فيفشل الاختبار وتكون قد رصدت إخفاقاً (Failure) سببه عيب في التحقق من صحة المدخلات.

كم اختباراً سلبياً أكتب مقارنةً بالاختبارات الإيجابية؟

لا توجد نسبة ثابتة. فطرق استخدام الميزة استخداماً خاطئاً أكثر عادةً من طرق استخدامها استخداماً صحيحاً، لذا تميل الاختبارات السلبية إلى أن تفوق الإيجابية عدداً. اخترها حسب المخاطر: كل ما يمس المال أو البيانات الشخصية أو الصلاحيات أولاً، ثم الأخطاء التي يقع فيها المستخدمون الحقيقيون أكثر من غيرها.

هل الاختبار السلبي هو نفسه اختبار الحالات الحدّية؟

لا. الاختبار السلبي يتعلق بالقصد: التحقق من رفض المدخلات غير الصالحة أو الاستخدام غير المقصود. أما الحالة الحدّية (Edge Case) فقيمة أو ظرف عند طرف أقصى، مثل أطول اسم مسموح به أو قائمة فارغة، وقد تكون صالحة أو غير صالحة. والاسم الذي يزيد حرفاً واحداً على الحد قيمة حدّية واختبار سلبي في آنٍ واحد.

المراجع

  • ISTQB GlossaryISTQBالتعريفات القياسية لمصطلحات الاختبار — حالة الاختبار واختبار الانحدار والخطورة والأولوية وتحليل القيم الحدّية وغيرها.
  • ISTQB Certified Tester Foundation Level (CTFL) v4.0ISTQB · 2023المنهج التأسيسي لاختبار البرمجيات: مستويات الاختبار وأنواعه وتقنيات تصميم الاختبارات وإدارة الاختبار والأدوات.
  • OWASP Cheat Sheet Series: Error HandlingOWASP Foundationاستجابات خطأ تساعد المستدعي دون تسريب تتبّعات الأخطاء أو الإصدارات أو المسارات الداخلية.
  • RFC 9110: HTTP SemanticsIETF · 2022معاني أساليب HTTP وحقول الترويسات ورموز الحالة والتفاوض على المحتوى، بغضّ النظر عن إصدار البروتوكول.

تدرّب بأدوات متقن

ولّد حالات اختبار إيجابية (المسار الطبيعي) تؤكد أن كل متطلب وكل تركيبة مدخلات صالحة تعمل كما ينبغي.

تصميم الاختبارات

ولّد حالات اختبار سلبية لحقول النماذج وواجهات API: قيم فارغة وnull ونوع خاطئ وطول زائد وحقن وصيغة غير صالحة.

تصميم الاختبارات

ولّد حالات اختبار للتحقق من حقول النماذج: الإلزامية والصيغة والطول والنطاق والنمط والقواعد المشتركة بين الحقول.

تصميم الاختبارات

احصل على نقطة نهاية عامة تعيد أي رمز حالة HTTP، مع تأخير اختياري وجسم JSON مخصّص، لاختبار معالجة الأخطاء في العميل.

اختبار واجهات API

ولّد استجابات خطأ منظّمة (التحقق والمصادقة وعدم العثور وتحديد المعدّل وخطأ الخادم) بالصيغ الشائعة.

المحاكاة

للتعمّق أكثر

تقدّمك في هذا الموضوع

جزء من مسار تعلم ضمان الجودة