ما هو اختبار API؟ وكيف تختبر REST API

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

يشرح هذا الدليل أنواع اختبارات API، وتشريح الطلب والاستجابة، وطريقة قابلة للتكرار لاختبار نقطة نهاية REST، والأعطال الأكثر شيوعاً، وكيفية تنفيذ كل ذلك من المتصفح دون تثبيت أي شيء.

ما الذي يغطيه اختبار API

«اختبار API» عائلة من الفحوصات لا نشاط واحد. تنفّذ معظم الفرق الأنواع الثلاثة الأولى مع كل تغيير والبقية قبل كل إصدار.

  • الاختبار الوظيفي — هل تعيد كل نقطة نهاية الاستجابة الصحيحة للمدخلات الصالحة؟ هل ينشئ POST السجل، وهل يعيده GET، وهل يحذفه DELETE؟
  • اختبار التحقق والاختبار السلبي — ماذا يحدث مع الحقول الناقصة، أو الأنواع الخاطئة، أو القيم خارج النطاق، أو JSON مشوّه، أو رمز منتهي الصلاحية، أو طلب كبير جداً؟ يجب أن تجيب الواجهة بخطأ 4xx واضح، ولا تعيد 500 أبداً.
  • اختبار العقد — هل ما زالت الاستجابة تطابق المخطط المتفق عليه (OpenAPI أو JSON Schema)؟ الحقول المحذوفة والأنواع المتغيّرة تعطّل كل المستهلكين.
  • المصادقة والتفويض — هل ترفض نقاط النهاية المحمية الطلبات المجهولة (401) والطلبات من المستخدم أو الدور الخطأ (403)؟
  • الأداء — كم يستغرق الطلب، وما حجم الحمولة، وكيف تتصرف نقطة النهاية تحت حمل متزامن؟
  • الأمان — الترويسات، والحقن في معاملات الاستعلام والأجسام، وتحديد المعدل، وما إذا كانت استجابات الأخطاء تسرّب تتبّع المكدس أو التفاصيل الداخلية.

تشريح الطلب والاستجابة

لكل تبادل HTTP الأجزاء نفسها، وكل جزء منها شيء يمكن التحقق منه.

  • الطريقة (Method) — GET يقرأ، وPOST ينشئ، وPUT يستبدل، وPATCH يعدّل جزءاً من المورد، وDELETE يحذف. استخدام الطريقة الخاطئة خطأ بحد ذاته.
  • عنوان URL وسلسلة الاستعلام — مسار المورد (‎/orders/42) مع المرشّحات والتصفّح (‎?status=paid&page=2).
  • ترويسات الطلب — Content-Type تخبر الخادم بما ترسله، وAccept بما تتوقعه، وAuthorization بمن أنت.
  • جسم الطلب — عادةً JSON في REST؛ ويجب أن يطابق المخطط الموثّق.
  • رمز الحالة — 2xx نجاح، و3xx إعادة توجيه، و4xx خطأ من العميل، و5xx فشل في الخادم. الرمز الدقيق مهم: 201 للإنشاء، و204 لعدم وجود محتوى، و400 للمدخلات السيئة، و404 لغير الموجود، و409 للتعارض، و422 لأخطاء التحقق.
  • ترويسات الاستجابة — Content-Type، والتخزين المؤقت، وعدّادات تحديد المعدل، وترويسات CORS والأمان.
  • جسم الاستجابة — البيانات، أو كائن خطأ متسق برمز قابل للقراءة آلياً ورسالة مفهومة للبشر.
كل جزء من تبادل HTTP شيء يمكن التحقق منه، من طريقة الطلب وعنوان URL إلى رمز الحالة وترويسات الاستجابة وجسمها.

الطلب

الجزء 1:POST الجزء 2:/api/v1/orders HTTP/1.1
الجزء 3:Host: api.example.com
Content-Type: application/json
Authorization: Bearer eyJhbGciOi...

الجزء 4:{"customerId": 7, "items": [{"sku": "A-100", "qty": 2}]}

الاستجابة

HTTP/1.1 الجزء 5:201 Created
الجزء 6:Content-Type: application/json
Location: /api/v1/orders/9021

الجزء 7:{"id": 9021, "status": "pending", "total": 249.90}
  1. 1الطريقة (Method)POST ينشئ؛ واستخدام الطريقة الخاطئة خطأ بحد ذاته.
  2. 2عنوان URL وسلسلة الاستعلاممسار المورد، مع المرشّحات والتصفّح، كما في:/orders/42?status=paid&page=2
  3. 3ترويسات الطلبContent-Type: ما ترسله إلى الخادم؛ Accept: ما تتوقعه؛ Authorization: من أنت.
  4. 4جسم الطلبعادةً JSON في REST؛ ويجب أن يطابق المخطط الموثّق.
  5. 5رمز الحالةالرمز الدقيق مهم: 201 للإنشاء، 400 للمدخلات السيئة، 422 لأخطاء التحقق.
  6. 6ترويسات الاستجابةهنا Content-Type، Location؛ ومعها التخزين المؤقت، وعدّادات تحديد المعدل، وترويسات CORS والأمان.
  7. 7جسم الاستجابةالبيانات، أو كائن خطأ متسق برمز قابل للقراءة آلياً ورسالة مفهومة للبشر.
النسخة النصية
POST /api/v1/orders HTTP/1.1
Host: api.example.com
Content-Type: application/json
Authorization: Bearer eyJhbGciOi...

{"customerId": 7, "items": [{"sku": "A-100", "qty": 2}]}

HTTP/1.1 201 Created
Content-Type: application/json
Location: /api/v1/orders/9021

{"id": 9021, "status": "pending", "total": 249.90}

جرّبها: منشئ طلبات API

كيف تختبر REST API خطوة بخطوة

  • اقرأ العقد أولاً. افتح مستند OpenAPI/Swagger أو توثيق الواجهة وأعدّ قائمة بكل نقطة نهاية ومعاملاتها واستجابة النجاح وكل خطأ موثّق.
  • أرسل المسار السعيد. لكل نقطة نهاية أرسل طلباً صالحاً وتحقق من رمز الحالة ومخطط الاستجابة والقيم الأساسية. احفظ الاستجابة — فهي خط الأساس لديك.
  • اكسر المدخلات عمداً. احذف الحقول المطلوبة، وأرسل النوع الخاطئ، وتجاوز الأطوال، واستخدم القيم الحدّية (0 و-1 والحد الأقصى + 1)، وأرسل أجساماً فارغة وضخمة، وأرسل JSON مشوّهاً. توقّع رموز 4xx دقيقة ورسائل خطأ تسمّي المشكلة.
  • اختبر المصادقة. استدعِ نقاط النهاية المحمية دون رمز، وبرمز منتهي الصلاحية، وبرمز لمستخدم آخر، وبرمز بنطاق خاطئ. توقّع 401 أو 403، ولا تتوقع بيانات أبداً.
  • تحقق من تغيّر الحالة. بعد POST نفّذ GET على المورد وتأكد من وجوده؛ وبعد DELETE تأكد من اختفائه؛ وبعد PUT تأكد من تغيّر كل حقل وعدم تغيّر أي شيء آخر.
  • تحقق من الترويسات لا من الأجسام فقط. يجب أن يكون Content-Type هو application/json، وأن يكون التخزين المؤقت صحيحاً للبيانات الخاصة، وأن يكون CORS مناسباً لعملاء المتصفح.
  • قِس. سجّل زمن استجابة كل استدعاء؛ فأي زمن يتصاعد بين الإصدارات هو انحدار حتى لو كان «يعمل».
  • أتمت ما كرّرته. حوّل الطلبات والتحققات إلى مجموعة أو سكربت يعمل مع كل بناء.

جرّبها: مختبِر REST API جرّبها: مختبِر نقاط نهاية API جرّبها: مختبِر مصادقة API

ما الذي تتحقق منه في كل استجابة

  • رمز الحالة هو بالضبط الرمز الموثّق.
  • ترويسة Content-Type صحيحة والجسم قابل للتحليل.
  • الجسم يطابق المخطط: الحقول المطلوبة موجودة، والأنواع صحيحة، ولا حقول غير متوقعة في العقود الصارمة.
  • القيم صحيحة: المعرّفات والمجاميع والتواريخ بصيغة ISO 8601 والتعدادات ضمن المجموعة المسموحة.
  • الأخطاء متسقة: الشكل نفسه في كل نقطة نهاية، ورمز آلي ثابت، ولا تتبّع مكدس أو SQL في الرسالة.
  • زمن الاستجابة ضمن الميزانية المتفق عليها.

جرّبها: مدقّق استجابات API جرّبها: مدقّق مخططات API

الأعطال الأكثر شيوعاً

  • 200 OK مع خطأ داخل الجسم — لا يستطيع العملاء التمييز بين النجاح والفشل دون تحليل النص.
  • 500 للمدخلات السيئة بدلاً من 400/422 — طبقة التحقق مفقودة أو تنهار.
  • أشكال خطأ مختلفة في نقاط نهاية مختلفة — كل مستهلك يحتاج معالجة مخصصة.
  • تغييرات صامتة في العقد — حقل أُعيدت تسميته أو نوع تغيّر دون رفع الإصدار.
  • فحوصات تفويض مفقودة — الرمز صالح لكنه يخص مستخدماً لا يجب أن يرى المورد.
  • تقسيم صفحات غير متسق — أحجام الصفحات والإزاحات والمجاميع تختلف بين نقاط النهاية.
  • أخطاء المناطق الزمنية — طوابع زمنية بلا إزاحة، أو تواريخ تنزاح يوماً كاملاً.

جرّبها: محاكي رموز حالة API جرّبها: مقارنة عقود الاستجابات

اختبار Webhooks والاستدعاءات العكسية

تعكس Webhooks الاتجاه: الواجهة هي التي تستدعيك. ولاختبارها تحتاج إلى رابط يقبل الاستدعاء ويعرض لك بالضبط ما وصل — الترويسات والتوقيع والجسم والتوقيت — لتتحقق من الحمولة مقابل التوثيق وتتأكد من التوقيع بالسر المشترك قبل كتابة سطر واحد من كود المعالجة.

جرّبها: مختبِر Webhook جرّبها: محلّل توقيعات Webhook

أدوات اختبار API: تطبيقات سطح المكتب مقابل أدوات المتصفح

تطبيقات Postman وInsomnia وBruno ممتازة للمجموعات الكبيرة طويلة العمر. أما للعمل اليومي — فحص نقطة نهاية، أو إعادة إنتاج خطأ، أو التحقق من استجابة، أو التقاط Webhook — فأداة المتصفح أسرع لأنه لا يوجد ما يُثبَّت أو يُسجَّل الدخول إليه. تغطي أدوات API في متقن تلك الحلقة اليومية: إنشاء الطلبات وإرسالها، والتحقق من الاستجابات وفق قواعد أو مخطط، ومحاكاة رموز الحالة، والتقاط Webhooks، وتوليد حالات اختبار مباشرة من ملف OpenAPI.

جرّبها: مولّد حالات اختبار من OpenAPI جرّبها: محلّل زمن الاستجابة

الأسئلة الشائعة

ما الفرق بين اختبار API واختبار الوحدة؟

اختبارات الوحدة تنفّذ دالة بمعزل داخل الكود. أما اختبارات API فترسل طلبات HTTP حقيقية إلى خدمة تعمل وتفحص الاستجابة، فتغطي التوجيه والتسلسل والتحقق والمصادقة وقاعدة البيانات معاً.

هل يمكنني اختبار API دون Postman؟

نعم. أي أداة تستطيع إرسال طلب HTTP وعرض الاستجابة تفي بالغرض — cURL في سطر الأوامر، أو منشئ طلبات في المتصفح، أو سكربت. المهم هو ما تتحقق منه لا العميل الذي تستخدمه.

ما رمز الحالة الذي يجب أن يعيده خطأ التحقق؟

400 Bad Request هو الجواب العام؛ ويُستخدم 422 Unprocessable Content (سابقاً Unprocessable Entity) على نطاق واسع عندما يكون JSON سليم البنية لكن القيم تفشل في التحقق. أيهما اخترت، استخدمه باتساق عبر الواجهة كلها.

كيف أختبر واجهة API تتطلب مصادقة؟

احصل على رمز بالطريقة التي يحصل بها عميل حقيقي (نقطة نهاية تسجيل الدخول، أو تدفق OAuth، أو مفتاح API)، وأرسله في ترويسة Authorization، واختبر أيضاً الحالات السلبية: دون رمز، وبرمز منتهي، وبنطاق خاطئ، وبرمز مستخدم آخر.

ما هو اختبار العقد؟

التحقق من أن الاستجابات الفعلية لواجهة API تطابق عقدها المنشور — عادةً مستند OpenAPI أو JSON Schema — حتى يُكتشف أي تغيير قد يعطّل المستهلكين قبل الإصدار.

كم حالة اختبار تحتاج نقطة النهاية الواحدة؟

كحد أدنى: مسار سعيد واحد، وحالة لكل خطأ موثّق، وحالة فشل مصادقة، والقيم الحدّية لكل معامل. يمكن لأداة أن تولّد خط الأساس هذا من مواصفة OpenAPI، ثم يضيف المختبِر السيناريوهات الخاصة بمنطق العمل.

المراجع

  • RFC 9110: HTTP SemanticsIETF · 2022معاني أساليب HTTP وحقول الترويسات ورموز الحالة والتفاوض على المحتوى، بغضّ النظر عن إصدار البروتوكول.
  • OpenAPI SpecificationOpenAPI Initiativeالمعيار لوصف واجهات REST: المسارات والعمليات والمعاملات والمخططات والاستجابات وأنظمة الأمان.
  • OWASP API Security Top 10 (2023)OWASP Foundation · 2023أكثر عشر نقاط ضعف شيوعاً في واجهات API: خلل التفويض على مستوى الكائن، وخلل التوثيق، والاستهلاك غير المقيد للموارد، وغيرها.
  • Postman DocsPostmanالتوثيق الرسمي لعميل API المستخدم لإرسال الطلبات وكتابة سكربتات الاختبار وتشغيل المجموعات.

تمرين عملي

اختبر نقطة نهاية الإرجاع في متجر إلكتروني

المطلوب

تختبر واجهة REST API لمتجر إلكترونيات خيالي على الإنترنت في بيئة Staging. أنهى المطوّر نقطة النهاية POST /api/v1/orders/{orderId}/returns التي تتيح للعميل طلب إرجاع منتجات من طلبية مسلَّمة واسترداد ثمنها، ولم يتحقق إلا من المسار السعيد. تجد أدناه مقتطفاً من العقد (بالإنجليزية كما يكتبه الفريق)، وبيانات الاختبار الاصطناعية، وطلب المطوّر، ونتائج ثلاثة فحوصات أخرى من التشغيل الأول.

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

تكفي الورقة والقلم؛ وخصّص لذلك نحو ⁦45⁩ دقيقة. ويمكنك إن شئت التحقق من قيم الكمية وطول التعليق بأداة «تحليل القيم الحدّية»، وأخذ مدخلات غير صالحة إضافية لأي حقل من أداة «مولّد الاختبارات السلبية»، ومعرفة معنى أي رمز حالة في RFC 9110 بأداة «مرجع رموز حالة HTTP».

المادة
Fictional online electronics store - Returns API on staging. Today: Thu 1 Oct 2026.
Every response is JSON (Content-Type: application/json) with Cache-Control: no-store.
Every error has the same shape ("field" is sent with VALIDATION_ERROR only):
  {"error": {"code": "VALIDATION_ERROR", "message": "...", "field": "items[0].qty"}}

POST /api/v1/orders/{orderId}/returns   Request a return of items from an order
  Auth     Bearer token of the order's customer, with the scope returns:write
  Body     items    required, at least one entry: {"sku": string, "qty": integer}
                    each SKU once, and only SKUs of this order
                    qty: 1 to the returnable quantity of the SKU
                    (quantity delivered minus quantity already in returns)
           reason   required: DAMAGED | WRONG_ITEM | NOT_AS_DESCRIBED | CHANGED_MIND
           comment  optional text, at most 500 characters
           id, status, refundAmount and createdAt are set by the server;
           if the client sends them, they are ignored.
           refundAmount = the sum of qty x unit price of the returned items.
  Rule     The order must be delivered, and the return requested within 14 days
           of delivery.
  201  Created                 the return; header Location: /api/v1/returns/{id}
  400  MALFORMED_JSON          the body is not valid JSON
  401  UNAUTHENTICATED         no token, or the token is invalid or expired
  403  FORBIDDEN               the order belongs to another customer
  403  INSUFFICIENT_SCOPE      the token does not have the scope returns:write
  404  ORDER_NOT_FOUND         no order with this id
  409  ORDER_NOT_RETURNABLE    the order is not delivered, or the 14 days have passed
  415  UNSUPPORTED_MEDIA_TYPE  Content-Type is not application/json
  422  VALIDATION_ERROR        a field is missing or invalid; "field" names it
  Target response time on staging: under 800 ms.

GET /api/v1/orders/{orderId}/returns    The returns of an order (same auth rules)

Test data (synthetic; restored before each test, after which no returns exist)
  CUS-101  TOKEN_A (returns:write), TOKEN_A_EXPIRED, TOKEN_A_READ (orders:read only)
  CUS-202  TOKEN_B (returns:write)
  O-5001   CUS-101  delivered 24 Sep 2026   A-100 x 2 at 49.95, B-200 x 1 at 120.00
  O-5002   CUS-101  shipped, not delivered  A-100 x 1 at 49.95
  O-5003   CUS-101  delivered 10 Sep 2026   A-100 x 1 at 49.95
  O-6001   CUS-202  delivered 28 Sep 2026   C-300 x 1 at 75.00

The developer's happy-path check
POST /api/v1/orders/O-5001/returns HTTP/1.1
Host: staging-api.example.com
Content-Type: application/json
Authorization: Bearer TOKEN_A

{"items": [{"sku": "A-100", "qty": 1}], "reason": "DAMAGED"}

HTTP/1.1 201 Created
Content-Type: application/json
Cache-Control: no-store
Location: /api/v1/returns/R-9001

{"id": "R-9001", "orderId": "O-5001", "status": "requested",
 "items": [{"sku": "A-100", "qty": 1}], "reason": "DAMAGED", "comment": null,
 "refundAmount": 49.95, "createdAt": "2026-10-01T10:15:00+03:00"}

First run of three more checks (each on restored data)
R1  O-5001, TOKEN_A, items [{"sku": "A-100", "qty": 3}], reason DAMAGED
    -> 500 Internal Server Error
       {"error": "IllegalStateException at ReturnService.java:88"}
R2  O-5001, TOKEN_B, items [{"sku": "A-100", "qty": 1}], reason DAMAGED
    -> 201 Created, Location: /api/v1/returns/R-9002, body with "orderId": "O-5001"
R3  O-5001, TOKEN_A, items [{"sku": "A-100", "qty": 1}], reason OTHER
    -> 200 OK
       {"success": false, "message": "Invalid reason"}
الخطوات
  1. اقرأ العقد أولاً: أعدّ قائمة بكل استجابة موثّقة وكل قاعدة لها حدّ، وتحقق هل تتيح بيانات الاختبار اختبار كل حدّ.
  2. المسار السعيد: اجعل طلب المطوّر اختبارك الأول مع كل ما تتحقق منه في استجابته، وأضف طلباً صالحاً ثانياً يُرجع كل ما في الطلبية.
  3. اكسر المدخلات عمداً: صيغة الجسم، وكل حقل، وكل حدّ، وحالات الطلبية الواردة في القاعدة. ولكل اختبار اذكر رمز الحالة ورمز الخطأ وقيمة field المتوقعة.
  4. المصادقة: دون رمز (Token)، وبرمز منتهي الصلاحية، وبرمز عميل آخر، وبرمز بنطاق (Scope) خاطئ.
  5. تغيّر الحالة والترويسات: ما تتحقق منه بعد الطلب بطلب GET منفصل، والترويسات التي يجب أن تحملها كل استجابة. وأضف كيف ستقيس زمن المجموعة وتؤتمتها.
  6. احكم على R1 وR2 وR3: ناجح أم فاشل، وأي الأعطال الشائعة في الدليل هو، وما الاستجابة المتوقعة. وقرّر أيها تبلّغ عنه أولاً، ثم اكتب أسئلتك لمالك المنتج.
إظهار الإجابة النموذجية
الإجابة النموذجية

الخطوة 1: اقرأ العقد. يوثّق العقد تسع نتائج: 201 و400 و401 و403 FORBIDDEN و403 INSUFFICIENT_SCOPE و404 و409 و415 و422؛ فتحتاج المجموعة إلى تسعة اختبارات على الأقل قبل أي قيمة حدّية. والقواعد التي لها حدود هي: qty (من ⁦1⁩ إلى الكمية القابلة للإرجاع: ⁦2⁩ للمنتج A-100 و⁦1⁩ للمنتج B-200 في الطلبية O-5001)، وcomment (⁦500⁩ حرف)، وitems (عنصر واحد على الأقل، وكل SKU مرة واحدة، ومن منتجات الطلبية فقط)، ومهلة الأيام الأربعة عشر. ولا تحوي بيانات الاختبار طلبية على حدّ المهلة، فاطلب طلبيتين اصطناعيتين إضافيتين للعميل CUS-101، مثل O-5004 المسلَّمة في ⁦17⁩ سبتمبر ⁦2026⁩ (قبل ⁦14⁩ يوماً من اليوم) وO-5005 المسلَّمة في ⁦16⁩ سبتمبر ⁦2026⁩ (قبل ⁦15⁩ يوماً)، وفي كل منهما ⁦A-100 × 1⁩ حتى يصلح لهما طلب المطوّر دون تغيير. ونفّذ كل اختبار على بيانات مستعادة، لأن كل إرجاع ناجح يُنقص الكمية القابلة للإرجاع في الاختبار التالي. وترقّم المجموعة النموذجية أدناه الاختبارات من RT-01 إلى RT-25؛ وقد يختلف ترقيمك وصياغتك.

الخطوة 2: المسار السعيد. RT-01 طلب المطوّر (⁦A-100 × 1⁩، DAMAGED)، والمتوقع 201؛ وقيمة Location هي /api/v1/returns/ متبوعةً بقيمة id الواردة في الجسم؛ وContent-Type: application/json وCache-Control: no-store؛ والجسم يحوي كل حقول الإرجاع بالأنواع الصحيحة — refundAmount رقم لا نص، وcomment قيمته null، وcreatedAt بصيغة ISO 8601 مع الإزاحة الزمنية — وبالقيم الصحيحة: orderId هو O-5001، وstatus هو requested، والعناصر والسبب كما أُرسلت، وrefundAmount هو ⁦49.95⁩؛ وزمن الاستجابة أقل من ⁦800⁩ ميلي ثانية. احفظ هذه الاستجابة خطَّ أساس. RT-02 إرجاع كل ما في الطلبية: ⁦A-100 × 2⁩ و⁦B-200 × 1⁩، والسبب WRONG_ITEM، مع تعليق قصير، والمتوقع 201 مع العنصرين كليهما، وعودة التعليق كما أُرسل، وrefundAmount بقيمة ⁦219.90⁩ (⁦2 × 49.95 + 120.00⁩)، وهي قيمة لا يكشفها التحقق من رمز الحالة وحده أبداً.

الخطوة 3: اكسر المدخلات؛ وكل اختبار هنا هو RT-01 مع تغيير واحد. RT-03 جسم مقطوع بعد {"items": [، والمتوقع 400 MALFORMED_JSON. RT-04 الجسم الصالح نفسه مع Content-Type: text/plain، والمتوقع 415 UNSUPPORTED_MEDIA_TYPE. RT-05 حذف items، والمتوقع 422 VALIDATION_ERROR مع field بقيمة items. RT-06 القيمة "items": []، والمتوقع 422 مع field بقيمة items. RT-07 حدود qty للمنتج A-100 الذي كميته القابلة للإرجاع ⁦2⁩ (الصيغة الثنائية من تحليل القيم الحدّية، 2-value BVA: كل قيمة حدّية وأقرب قيمة مجاورة لها في القسم المجاور): ⁦0⁩ يعطي 422 مع field بقيمة items[0].qty، و⁦1⁩ يعطي 201 (RT-01)، و⁦2⁩ يعطي 201، و⁦3⁩ يعطي 422. RT-08 قيم وأنواع غير صالحة لـqty: -1 و1.5 و"1" (نص)، والمتوقع 422 لكل منها. RT-09 المنتج C-300 الذي ينتمي إلى طلبية أخرى، والمتوقع 422 مع field بقيمة items[0].sku. RT-10 المنتج A-100 مرتين في items، والمتوقع 422. RT-11 حذف reason، ثم reason بقيمة OTHER، والمتوقع 422 مع field بقيمة reason. RT-12 تعليق comment من ⁦500⁩ حرف بالضبط يعطي 201 ويعود التعليق كاملاً، و⁦501⁩ حرف يعطي 422 مع field بقيمة comment.

RT-13 الطلبية O-9999، والمتوقع 404 ORDER_NOT_FOUND. RT-14 الطلبية O-5002 التي شُحنت ولم تُسلَّم، والمتوقع 409 ORDER_NOT_RETURNABLE، وهي الاستجابة التي يحددها العقد للطلبية غير المسلَّمة (انظر Q4). RT-15 المهلة: O-5004 (اليوم ⁦14⁩) تعطي 201 إن كان اليوم الرابع عشر محسوباً (السؤال Q1)، وO-5005 (اليوم ⁦15⁩) وO-5003 (اليوم ⁦21⁩) تعطيان 409. RT-16 تعليق فيه علامات تنصيص وأقواس زاوية، مثل O'Brien "test" <b>x</b>، والمتوقع 201 وعودة التعليق كما أُرسل تماماً، دون 500 ودون SQL أو تتبّع مكدس في أي رسالة. ولا ترسل مثل هذه المدخلات إلا إلى أنظمة مأذون لك باختبارها، وهي هنا بيئة Staging الخاصة بفريقك.

الخطوة 4: المصادقة. RT-17 دون ترويسة Authorization، والمتوقع 401 UNAUTHENTICATED دون أي بيانات إرجاع؛ ويشترط RFC 9110 أيضاً أن تحمل كل استجابة 401 ترويسة WWW-Authenticate. RT-18 الرمز TOKEN_A_EXPIRED، والمتوقع 401 UNAUTHENTICATED. RT-19 الرمز TOKEN_B الخاص بالعميل CUS-202 على الطلبية O-5001، والمتوقع 403 FORBIDDEN دون أي معلومة عن O-5001 في الجسم؛ وبعده يُظهر الطلب GET /api/v1/orders/O-5001/returns بالرمز TOKEN_A أنه لا إرجاع جديداً، والطلب GET نفسه بالرمز TOKEN_B يُرفض بـ403. ويسمح RFC 9110 للخادم بأن يجيب بـ404 بدلاً من ذلك ليخفي وجود الطلبية؛ لكن هذا العقد اختار 403، فهو النتيجة المتوقعة. RT-20 الرمز TOKEN_A_READ الذي لا يملك إلا النطاق orders:read، والمتوقع 403 INSUFFICIENT_SCOPE.

الخطوة 5: تغيّر الحالة والترويسات. RT-21 بعد RT-01 يعيد GET /api/v1/orders/O-5001/returns رمز الحالة 200 مع إرجاع واحد بالضبط تطابق قيمُ id والعناصر والسبب وrefundAmount فيه جسمَ استجابة 201. RT-22 الكمية القابلة للإرجاع تنقص: بعد RT-01 يعطي المنتج A-100 مع qty بقيمة ⁦2⁩ الرمز 422 (لم يبقَ إلا ⁦1⁩)، ومع qty بقيمة ⁦1⁩ يعطي 201، ثم مع qty بقيمة ⁦1⁩ مرة أخرى يعطي 422. RT-23 طلب RT-01 مضافاً إليه "status": "approved", "refundAmount": 999، والمتوقع 201 مع status بقيمة requested وrefundAmount بقيمة ⁦49.95⁩: يجب ألا يستطيع العميل تحديد المبلغ المسترد بنفسه (ويغطي OWASP API Security Top 10 2023 ذلك تحت API3، أي Broken Object Property Level Authorization). RT-24 الطلبات المرفوضة لا تغيّر شيئاً: بعد RT-07 مع qty بقيمة ⁦3⁩، وRT-11، وRT-14 تبقى قائمة إرجاعات الطلبية كما هي. RT-25 إرسال طلب RT-02 مرتين في اللحظة نفسها، والمتوقع استجابة 201 واحدة واستجابة 422 واحدة؛ فاستجابتا 201 تعنيان استرداد ثمن المنتجات نفسها مرتين. وفي كل استجابة، بما فيها الأخطاء، تحقق من Content-Type: application/json وCache-Control: no-store (فالبيانات خاصة)، ومن شكل الخطأ المحدد في العقد، ومن أن Location لا يظهر إلا مع 201.

وتنطبق أيضاً الخطوتان الأخيرتان من الطريقة: سجّل زمن استجابة كل اختبار وعلّم كل زمن يتجاوز ⁦800⁩ ميلي ثانية حتى لو كانت الاستجابة صحيحة، وقارن الأزمنة بين البناءات، فالزمن الذي يواصل الارتفاع انحدار حتى لو بقي دون ⁦800⁩ ميلي ثانية. ثم حوّل المجموعة إلى مجموعة طلبات (Collection) تستعيد بيانات الاختبار وتعمل مع كل بناء وتقارن RT-01 بخط الأساس المحفوظ. هذه ⁦25⁩ اختباراً لنقطة نهاية واحدة. ويذكر قسم الأسئلة الشائعة في الدليل الحدّ الأدنى: مسار سعيد واحد، واختبار لكل خطأ موثّق، وحالة فشل في المصادقة، والقيم الحدّية لكل معامل؛ أما RT-21 إلى RT-25 فهي ما تفوته مجموعة مبنية على الاستجابات المنفردة وحدها.

الخطوة 6: التشغيل الأول. R1 فاشل لثلاثة أسباب يذكرها الدليل كلها: 500 لمدخلات سيئة بدلاً من 422، وشكل خطأ يخالف العقد (نص بدلاً من الكائن error بحقوله code وmessage وfield)، وهذان من الأعطال الشائعة في الدليل؛ ورسالة تسرّب تفاصيل داخلية (اسم استثناء وملفاً مصدرياً ورقم سطر)، وهو ما تمنعه قائمة الدليل لما تتحقق منه في كل استجابة. المتوقع: 422 VALIDATION_ERROR مع field بقيمة items[0].qty.

R2 فاشل وهو الأخطر: فحص تفويض مفقود، فالرمز صالح لكنه يخص عميلاً لا حق له في هذه الطلبية. فأي عميل مسجّل الدخول يستطيع طلب الإرجاع، ومن ثَمّ استرداد المبالغ، على طلبية غيره، والاستجابة تكشف بيانات تلك الطلبية. ويصنّف OWASP API Security Top 10 2023 هذا تحت API1، أي Broken Object Level Authorization. المتوقع: 403 FORBIDDEN وعدم إنشاء أي إرجاع. بلّغ عنه أولاً بخطورة حرج (Critical)، مع الطلب كما أُرسل بالرمز TOKEN_B واستجابة 201 والإرجاع R-9002 الذي أنشأه؛ وبعد الإصلاح أعد تنفيذ RT-19 اختبارَ تأكيد (Confirmation testing)، بما فيه طلب GET بالرمز TOKEN_B. وR3 فاشل: 200 OK مع خطأ داخل الجسم، فالتطبيق الذي يعتمد على رمز الحالة يخبر العميل بأن الإرجاع قُبل، والجسم بشكل خطأ آخر مختلف. المتوقع: 422 VALIDATION_ERROR مع field بقيمة reason، وعدم إنشاء أي إرجاع.

أسئلة لمالك المنتج والمطوّر. Q1 هل تشمل عبارة العقد "within 14 days of delivery" اليوم الرابع عشر، وهل تُحسب المهلة بالأيام التقويمية في المنطقة الزمنية للمتجر أم بفترات من ⁦24⁩ ساعة تبدأ من وقت التسليم؟ Q2 كيف تُعدّ أحرف comment الخمسمئة في النص العربي وفي الرموز التعبيرية (Emoji)، وهل يُقبل تعليق فارغ؟ Q3 هل reason حساس لحالة الأحرف، أي هل تُرفض القيمة damaged؟ Q4 حين يخالف الطلب قاعدتين، فأي خطأ يأتي أولاً؟ مثل طلبية عميل آخر مع جسم غير صالح، أو الطلبية O-5002 التي لم تُسلَّم، فلا كمية قابلة للإرجاع فيها بعد (409 أم 422؟). والمتوقع عادةً أن يأتي فحص التفويض أولاً، حتى لا تكشف رسائل التحقق شيئاً عن طلبية شخص آخر.

راجع عملك: يجب أن يظهر كل رمز حالة موثّق في مجموعتك مرة واحدة على الأقل؛ وأن يغيّر كل اختبار سلبي شيئاً واحداً فقط في RT-01؛ وأن تذكر كل نتيجة متوقعة رمز الحالة ورمز الخطأ، لا مجرد «خطأ». وبمصطلحات ISTQB، فإن العقد هو أساس الاختبار (Test basis)، وكل استجابة موثّقة وكل قاعدة شرط اختبار (Test condition)، والاختبارات RT-07 وRT-12 وRT-15 تطبّق الصيغة الثنائية من تحليل القيم الحدّية. وإن لم تكن في مجموعتك فحوصات بعد الاستجابة، أي RT-21 إلى RT-25، فأضفها: فقد تبدو الاستجابة صحيحة بينما البيانات التي خلفها خاطئة.

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

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

الأدوات المذكورة في هذا الدليل

أنشئ طلبات HTTP وأرسلها (الطريقة وعنوان URL والترويسات والمصادقة والجسم) وافحص الاستجابة — بديل خفيف لـ Postman داخل متصفحك.

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

اختبر نقاط نهاية REST بتحكم كامل في الطريقة والترويسات وجسم JSON، ثم أضف تأكيدات على الحالة والترويسات ومسارات JSON.

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

تحقّق سريعاً من إمكانية الوصول إلى نقطة نهاية API: الحالة وزمن الاستجابة والحجم ونوع المحتوى وTLS.

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

تحقّق من استجابة API وفق التوقعات: الحالة والترويسات المطلوبة وJSON Schema وقواعد الحقول.

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

تحقّق من استجابات API وفق JSON Schema أو مخطط استجابة OpenAPI.

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

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

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

احصل على عنوان URL فريد، وأرسل إليه طلبات webhook، وافحص الطريقة والترويسات والجسم والتوقيت في الوقت الفعلي.

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

اختبر مصادقة Bearer وBasic ومفتاح API والترويسات المخصّصة على نقطة نهاية وقارن الاستجابات المصرّح بها بغير المصرّح بها.

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

قِس زمن استجابة نقطة نهاية عبر عدة عيّنات: الحد الأدنى والأقصى والمتوسط والوسيط وp95.

الأداء

كيف تساعدك متقن سوفت

أدلة أخرى

أدلة أخرى
اختبار واجهات API

مقارنة أساليب اختبار الواجهات البرمجية

خمس طرق لاختبار واجهة برمجية — الاستكشافية والمكتوبة والعقد والمحاكاة والحمل — مقارنة فيما يلتقطه كل منها، وكيف تختلف REST وGraphQL وSOAP وWebhooks.

وقت القراءة 6 دقائق
تصميم الاختبارات

ضمان جودة المنتج من البداية إلى النهاية

ما الذي يشمله ضمان الجودة الشامل — مراجعة المتطلبات وتصميم الاختبارات والاختبار الوظيفي واختبار الأداء والأمان وبوابات الإصدار والمقاييس — وكيف تنفّذه.

وقت القراءة 8 دقائق
الأمان

ما هو JWT؟ شرح رموز JSON Web Token

شرح مبسّط لـ JWT: الأجزاء الثلاثة للرمز، والمطالبات مثل exp وsub، وكيفية فك ترميزه والتحقق منه، ولماذا فك الترميز ليس تحققاً، وقواعد الأمان.

وقت القراءة 4 دقائق
تصميم الاختبارات

الاختبار اليدوي مقابل الاختبار الآلي

مقارنة بين الاختبار اليدوي والآلي في التكلفة والسرعة وما يجده كل منهما وما يفوته والصيانة — مع قاعدة عملية لتقرير ما يُؤتمت وما يُترك للبشر.

وقت القراءة 6 دقائق
الويب

شرح رموز حالة HTTP

شرح كل فئة من رموز حالة HTTP مع الرموز التي تقابلها فعلاً — 200 و301 و400 و401 و403 و404 و422 و429 و500 و502 و503 و504 — وسبب كل منها وأيها تعيده.

وقت القراءة 5 دقائق
الأداء

اختبار مرونة الأداء والأمان

كيف تختبر المنتج أمام الحمل والاعتماديات الفاشلة والهجمات: اختبارات الحمل والإجهاد والتحمّل بأهداف حقيقية، وحقن الأعطال، وخط أساس OWASP، والأرقام التي تُسجَّل.

وقت القراءة 8 دقائق