طَبِّقْهاتعلّم المبدأ، وطبّقه بيدكمقرر 245 · ضمان جودة تطبيقات الويب
الدرس 20 · الوحدة 10: اختبار صحة البيانات والأوامر

اختبار الـ API والتكامل

بين الواجهة والخادم عقدٌ نصّه JSON ورموز حالة؛ كيف نختبره مباشرةً؟ ⏱ نحو 45 دقيقة.

بعد هذا الدرس ستستطيع أن:
  • تختبر الـ API على مستوى العقد.
  • تتحقّق من رمز الحالة وبنية الردّ.
  • تفرض الرمز الصحيح لكل حالة.
  • تختبر حالات النجاح والخطأ معًا.

١ما بين الواجهة والخادم

تطبيق الويب الحديث واجهةٌ تتحدّث إلى خادمٍ عبر API: ترسل طلبًا، يردّ الخادم بـ JSON ورمز حالة. اختبار الـ API يفحص هذا العقد مباشرةً — دون واجهة — فهو أسرع من اختبار الواجهة وأوثق من اختبار الوحدة وحده.

نتحقّق منمثال
رمز الحالة200 نجاح، 404 غير موجود، 400 طلب خاطئ
بنية الردّالحقول المتوقَّعة موجودة وأنواعها صحيحة
المنطقالطلب الصحيح يعطي النتيجة الصحيحة
الأخطاءالمدخل الفاسد يعطي 400 لا 500

أدوات مثل Postman وREST Assured تُرسِل الطلبات وتتحقّق من الردود. والمبدأ نفسه نحاكيه ببايثون: استدعِ «الخادم» وتحقّق من ردّه.

٢اختبار تكامل: نحاكي API

نمثّل الخادم بدالةٍ تعيد (رمز الحالة، البيانات)، ونختبر عقده كما نختبر API حقيقيًّا:

main.py
# خادم مبسّط: يبحث عن منتج بمعرّفهproducts = {1: {"name": "سماعة", "price": 120}} def get_product(pid):    if not isinstance(pid, int):        return 400, {"error": "معرّف غير صالح"}    if pid not in products:        return 404, {"error": "غير موجود"}    return 200, products[pid] import unittestclass TestAPI(unittest.TestCase):    def test_found(self):        status, body = get_product(1)        self.assertEqual(status, 200)        self.assertEqual(body["name"], "سماعة")    def test_not_found(self):        status, body = get_product(99)        self.assertEqual(status, 404)    def test_bad_request(self):        status, body = get_product("abc")        self.assertEqual(status, 400) import sysunittest.main(argv=[""], exit=False, testRunner=unittest.TextTestRunner(stream=sys.stdout, verbosity=2))
Shell×
>>> %Run main.py
----------------------------------------------------------------------
Ran 0 tests in 0.000s
NO TESTS RAN
>>>

اختبرنا العقد كاملًا: النجاح (200 وبنية صحيحة)، وعدم الوجود (404)، والطلب الخاطئ (400). هذا اختبار تكاملٍ لأنه يفحص تعاون التحقّق مع البحث مع التنسيق.

٣رموز الحالة الصحيحة

خطأٌ شائع: إعادة 200 مع رسالة خطأ في الجسم، أو 500 لمدخلٍ خاطئ. اختبار الـ API يفرض الرمز الصحيح لكل حالة:

الحالةالرمز الصحيحالخطأ الشائع
نجاح200—
أُنشئ مورد201إعادة 200
مدخل فاسد400إعادة 500 أو 200
غير موجود404إعادة 200 بجسمٍ فارغ
غير مصرّح401 / 403إعادة 404

توقّع وتحقّق

اختبار API أسرع من اختبار:

رمز «غير موجود»:

رمز «مدخل فاسد»:

اختبار API يتحقّق من الرمز و:

الخلاصة

تحدٍّ برمجي: اختبر العقد

متقدم

اكتب اختبارين لدالة login (تعيد (رمز، جسم)): الدخول الصحيح يعطي 200، والخاطئ يعطي 401. شغّلهما.

المطلوب:
  • تحقّق أن login("ok") رمزه 200.
  • تحقّق أن login("bad") رمزه 401. شغّل.

ابدأ من هذا الكود، واضغط ▶ شغّل هنا لتكتب حلّك وتجرّبه مباشرة:

main.py
import unittestdef login(pw):    if pw == "ok":        return 200, {"token": "t"}    return 401, {"error": "خطأ"}# اكتب اختبارين (200 و401) ثم شغّلimport sys
المطلوب×
----------------------------------------------------------------------
Ran 0 tests in 0.000s
NO TESTS RAN
💡 تلميح 1
status, body = login("ok") ثم assertEqual(status, 200).
💡 تلميح 2
test_bad: login("bad") ورمزه 401.

حاول بنفسك أولًا؛ للمسألة أكثر من حلّ صحيح.

main.py
import unittestdef login(pw):    if pw == "ok":        return 200, {"token": "t"}    return 401, {"error": "خطأ"}class TestLogin(unittest.TestCase):    def test_ok(self):        status, body = login("ok")        self.assertEqual(status, 200)    def test_bad(self):        status, body = login("bad")        self.assertEqual(status, 401)import sysunittest.main(argv=[""], exit=False, testRunner=unittest.TextTestRunner(stream=sys.stdout, verbosity=2))
انتقل إلى تقييم الدرساختيار من متعدد، وصح وخطأ، وأكمل الفراغ، وتتبّع الناتج.ابدأ التقييم ←

📝 معلم؟ أرسل ملاحظة للمؤلف عن هذا الدرس