تغطية الاختبار Coverage
اختباراتك خضراء؛ لكن أيّ جزءٍ من الكود لم يمسّه اختبارٌ قطّ؟ ⏱ نحو 40 دقيقة.
- تفهم التغطية كقياسٍ لما نفّذته الاختبارات.
- تميّز تغطية الأسطر من الفروع.
- تكتشف الفروع غير المُجرَّبة.
- تدرك أن 100% لا تكفي وحدها.
١ما الذي لم تختبره؟
مرّت كل اختباراتك خضراء. هل انتهيت؟ ليس بعد. السؤال الأخطر: أيّ أجزاء من الكود لم يمسّها أيّ اختبار؟ تغطية الاختبار Coverage تقيس نسبة الكود الذي نفّذته اختباراتك. الجزء غير المُغطّى أرضٌ مجهولة قد تخبّئ عيوبًا.
| نوع التغطية | يقيس | الأقوى |
|---|---|---|
| تغطية الأسطر | نسبة الأسطر المُنفَّذة | الأساس |
| تغطية الفروع | نسبة فروع if المُجرَّبة (صح وخطأ) | أقوى من الأسطر |
| تغطية المسارات | نسبة المسارات الكاملة | الأشمل والأصعب |
تغطية الأسطر قد تخدع: سطر if يُعَدّ «مُغطّى» ولو لم تجرّب إلا فرعه الصحيح. تغطية الفروع أصدق: تتطلّب تجربة الشرط صحيحًا وخاطئًا.
٢قياس تغطية الفروع يدويًّا
لنفهم الفكرة، نعدّ الفروع التي لمستها حالاتنا. الدالة فيها فرعان (شرطٌ واحد = فرعا صح وخطأ):
def shipping(total): if total >= 200: # فرعان: >=200 و <200 return 0 return 15 # حالاتنا: هل لمسنا الفرعين؟cases = [250, 300] # كلها >= 200 !branches_hit = set()for t in cases: branches_hit.add(t >= 200) # True فقط print("الفروع الملموسة:", branches_hit)print("تغطية الفروع:", len(branches_hit), "من 2")print("ناقص: لم نجرّب total < 200 (الشحن 15)")
التغطية هنا 50% فقط: جرّبنا حالة المجانيّة ونسينا حالة الشحن المدفوع. لو كان فيها عيبٌ لما كشفناه. أضف حالةً < 200 لتكتمل.
٣100% ليست ضمانًا
في العمل تُقاس التغطية آليًّا بأدوات مثل coverage.py في بايثون أو JaCoCo في جافا؛ تضع هدفًا معقولًا (مثلًا ≥85% كما في مواصفة هذا المقرر) وتركّز على تغطية المنطق الحرج.
توقّع وتحقّق
التغطية تقيس:
الأصدق من تغطية الأسطر:
تغطية 100%:
أداة قياس التغطية في بايثون:
الخلاصة
- التغطية تقيس نسبة الكود الذي نفّذته اختباراتك؛ غير المُغطّى أرضٌ مجهولة.
- تغطية الفروع أصدق من الأسطر: تتطلّب تجربة الشرط صحيحًا وخاطئًا.
- 100% تغطية لا تضمن الصحّة؛ تكشف ما لم يُختبَر لا تثبت صحّة ما اختُبر.
- تُقاس آليًّا (
coverage.py،JaCoCo)؛ اجعل الهدف معقولًا وركّز على المنطق الحرج.
تحدٍّ برمجي: احسب التغطية
متوسطللدالة ذات الشرط n % 2 == 0، احسب تغطية الفروع لمجموعة المدخلات: اطبع عدد الفروع الملموسة (من 2).
- اجمع نتائج
n % 2 == 0لكل مدخل في مجموعة. - اطبع عدد القيم المختلفة (الفروع الملموسة).
ابدأ من هذا الكود، واضغط ▶ شغّل هنا لتكتب حلّك وتجرّبه مباشرة:
def is_even(n): return n % 2 == 0inputs = [2, 4, 6] # كلها زوجية!# احسب عدد الفروع الملموسة (True/False) من 2
💡 تلميح 1
branches = set(n % 2 == 0 for n in inputs).💡 تلميح 2
حاول بنفسك أولًا؛ للمسألة أكثر من حلّ صحيح.
def is_even(n): return n % 2 == 0inputs = [2, 4, 6]branches = set(n % 2 == 0 for n in inputs)print(len(branches))