التقسيم المكافئ وتحليل القيم الحدّية
كيف نغطّي آلاف المدخلات بحفنة حالاتٍ مختارة بذكاء؟ ⏱ نحو 40 دقيقة.
- تقسّم المدخلات إلى شرائح مكافئة.
- تختبر ممثّلًا من كل شريحة.
- تحلّل القيم الحدّية (الحدّ وجارتيه).
- تدمج الأسلوبين لتغطيةٍ عالية بأقلّ حالات.
١لا تختبر كل قيمة: قسّمها
دالةٌ تقبل عمرًا من 0 إلى 120. أتختبر 121 قيمة؟ لا. التقسيم المكافئ Equivalence Partitioning يقسم المدخلات إلى فئاتٍ تتصرّف الدالة معها بالطريقة نفسها، فيكفي ممثّلٌ واحد من كل فئة.
| الفئة (شريحة مكافئة) | ممثّل | المتوقَّع |
|---|---|---|
| أقل من 0 (غير صالح) | -5 | مرفوض |
| 0 إلى 120 (صالح) | 45 | مقبول |
| أكبر من 120 (غير صالح) | 200 | مرفوض |
ثلاث حالاتٍ تغطّي كل الاحتمالات سلوكيًّا، بدل 121. المبدأ: كل قيمةٍ في شريحةٍ واحدة تكشف ما تكشفه أخواتها، فلا داعي لتكرارها.
٢تحليل القيم الحدّية
التقسيم يختار ممثّلًا من وسط الشريحة، لكن العيوب على الحواف. لذا نكمّله بـ تحليل القيم الحدّية Boundary Value Analysis: اختبر القيمة الحدّية وجارتيها (الحدّ، وقبله، وبعده):
def is_valid_age(age): return 0 <= age <= 120 # الحدود: حول 0 وحول 120boundaries = [-1, 0, 1, 119, 120, 121]expected = [False, True, True, True, True, False]for age, exp in zip(boundaries, expected): got = is_valid_age(age) print(f"{'✓' if got == exp else '✗'} عمر {age}: {got}")
هذه الست قيمٍ تكشف أشهر عيبٍ: استخدام < بدل <=. لو كان الكود age < 120 لفشلت الحالة 120 فورًا.
٣دمج الأسلوبين: تغطية ذكية
معًا يعطيان تغطيةً عالية بأقلّ عدد: ممثّلٌ من كل شريحة + القيم الحدّية. انظر دالة خصمٍ بشرائح:
def discount_rate(qty): "خصم حسب الكمية" if qty <= 0: return 0.0 # غير صالح if qty < 10: return 0.05 # شريحة صغيرة if qty < 50: return 0.10 # شريحة متوسطة return 0.15 # شريحة كبيرة # ممثّل + حدود كل شريحةcases = [(0, 0.0), (1, 0.05), (9, 0.05), (10, 0.10), (49, 0.10), (50, 0.15)]passed = sum(1 for q, exp in cases if discount_rate(q) == exp)print("نجح", passed, "من", len(cases), "— حدود الشرائح الثلاث مغطّاة")
توقّع وتحقّق
التقسيم المكافئ يقسم المدخلات إلى:
تحليل القيم الحدّية يختبر:
أشهر عيب تكشفه الحدود:
من كل شريحة مكافئة نختبر:
الخلاصة
- التقسيم المكافئ يجمع المدخلات المتشابهة سلوكيًّا في شريحة، فيكفي ممثّلٌ منها.
- تحليل القيم الحدّية يختبر الحدّ وقبله وبعده، حيث تكمن أكثر العيوب.
- العيب الأشهر الذي يكشفانه: < بدل
<=عند الحدود. - معًا: ممثّل من كل شريحة + القيم الحدّية = تغطية عالية بأقلّ حالات.
تحدٍّ برمجي: غطِّ الشرائح
متوسطدالة ship_fee: مجانًا فوق 200، و15 من 1 إلى 200، و0 للصفر أو أقل. اختبر الحالات المعطاة (تشمل الحدّ 200) واطبع عدد الناجحة.
- مرّ على الحالات وقارن.
- اطبع عدد الحالات الناجحة.
ابدأ من هذا الكود، واضغط ▶ شغّل هنا لتكتب حلّك وتجرّبه مباشرة:
def ship_fee(total): if total <= 0: return 0 if total <= 200: return 15 return 0cases = [(0, 0), (1, 15), (200, 15), (201, 0), (500, 0)]# اطبع عدد الحالات الناجحة
💡 تلميح 1
sum(1 for t, exp in cases if ship_fee(t) == exp).💡 تلميح 2
حاول بنفسك أولًا؛ للمسألة أكثر من حلّ صحيح.
def ship_fee(total): if total <= 0: return 0 if total <= 200: return 15 return 0cases = [(0, 0), (1, 15), (200, 15), (201, 0), (500, 0)]passed = sum(1 for t, exp in cases if ship_fee(t) == exp)print(passed)