اختبار الـ API والتكامل
بين الواجهة والخادم عقدٌ نصّه JSON ورموز حالة؛ كيف نختبره مباشرةً؟ ⏱ نحو 45 دقيقة.
- تختبر الـ
APIعلى مستوى العقد. - تتحقّق من رمز الحالة وبنية الردّ.
- تفرض الرمز الصحيح لكل حالة.
- تختبر حالات النجاح والخطأ معًا.
١ما بين الواجهة والخادم
تطبيق الويب الحديث واجهةٌ تتحدّث إلى خادمٍ عبر API: ترسل طلبًا، يردّ الخادم بـ JSON ورمز حالة. اختبار الـ API يفحص هذا العقد مباشرةً — دون واجهة — فهو أسرع من اختبار الواجهة وأوثق من اختبار الوحدة وحده.
| نتحقّق من | مثال |
|---|---|
| رمز الحالة | 200 نجاح، 404 غير موجود، 400 طلب خاطئ |
| بنية الردّ | الحقول المتوقَّعة موجودة وأنواعها صحيحة |
| المنطق | الطلب الصحيح يعطي النتيجة الصحيحة |
| الأخطاء | المدخل الفاسد يعطي 400 لا 500 |
أدوات مثل Postman وREST Assured تُرسِل الطلبات وتتحقّق من الردود. والمبدأ نفسه نحاكيه ببايثون: استدعِ «الخادم» وتحقّق من ردّه.
٢اختبار تكامل: نحاكي API
نمثّل الخادم بدالةٍ تعيد (رمز الحالة، البيانات)، ونختبر عقده كما نختبر API حقيقيًّا:
# خادم مبسّط: يبحث عن منتج بمعرّفه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))
اختبرنا العقد كاملًا: النجاح (200 وبنية صحيحة)، وعدم الوجود (404)، والطلب الخاطئ (400). هذا اختبار تكاملٍ لأنه يفحص تعاون التحقّق مع البحث مع التنسيق.
٣رموز الحالة الصحيحة
خطأٌ شائع: إعادة 200 مع رسالة خطأ في الجسم، أو 500 لمدخلٍ خاطئ. اختبار الـ API يفرض الرمز الصحيح لكل حالة:
| الحالة | الرمز الصحيح | الخطأ الشائع |
|---|---|---|
| نجاح | 200 | — |
| أُنشئ مورد | 201 | إعادة 200 |
| مدخل فاسد | 400 | إعادة 500 أو 200 |
| غير موجود | 404 | إعادة 200 بجسمٍ فارغ |
| غير مصرّح | 401 / 403 | إعادة 404 |
توقّع وتحقّق
اختبار API أسرع من اختبار:
رمز «غير موجود»:
رمز «مدخل فاسد»:
اختبار API يتحقّق من الرمز و:
الخلاصة
- اختبار الـ
APIيفحص عقد الواجهة-الخادم مباشرةً: رمز الحالة، والبنية، والمنطق، والأخطاء. - أسرع من اختبار الواجهة وأوثق من اختبار الوحدة وحده (اختبار تكامل).
- افرض الرمز الصحيح:
200/201للنجاح، 400 للفاسد، 404 لغير الموجود،401/403للتصريح. - الرمز الخاطئ يربك مستهلك الـ
API؛ اختبر الرمز لا الجسم فقط.
تحدٍّ برمجي: اختبر العقد
متقدماكتب اختبارين لدالة login (تعيد (رمز، جسم)): الدخول الصحيح يعطي 200، والخاطئ يعطي 401. شغّلهما.
- تحقّق أن
login("ok")رمزه 200. - تحقّق أن
login("bad")رمزه 401. شغّل.
ابدأ من هذا الكود، واضغط ▶ شغّل هنا لتكتب حلّك وتجرّبه مباشرة:
import unittestdef login(pw): if pw == "ok": return 200, {"token": "t"} return 401, {"error": "خطأ"}# اكتب اختبارين (200 و401) ثم شغّلimport sys
💡 تلميح 1
status, body = login("ok") ثم assertEqual(status, 200).💡 تلميح 2
test_bad: login("bad") ورمزه 401.حاول بنفسك أولًا؛ للمسألة أكثر من حلّ صحيح.
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))