تنفيذ اختبار العقود للواجهة البرمجية API: أفضل الممارسات لواجهات برمجية موثوقة

Ashley Goolam

Ashley Goolam

18 نوفمبر 2025

تنفيذ اختبار العقود للواجهة البرمجية API: أفضل الممارسات لواجهات برمجية موثوقة

enterprise.banner.title

enterprise.banner.feature1

enterprise.banner.feature2

enterprise.banner.feature3

enterprise.banner.ctaB

هل واجهت من قبل موقفًا يتعطل فيه تطبيق الواجهة الأمامية (frontend) فجأة لأن واجهة برمجة التطبيقات الخلفية (backend API) تغيرت بشكل غير متوقع؟ يمكن أن تتسبب مثل هذه الاضطرابات في تأثير متتالي عبر نظامك بأكمله، مما يؤدي إلى إحباط المستخدمين وجلسات تصحيح الأخطاء المحمومة. هذا هو بالضبط المكان الذي يأتي فيه اختبار عقد واجهة برمجة التطبيقات (API Contract Testing)—نهج منهجي يضمن الانسجام بين منتجي ومستهلكي واجهة برمجة التطبيقات. في هذا الدليل، سنتعمق في تفاصيل اختبار عقد واجهة برمجة التطبيقات، مستكشفين أسسه وتحدياته واستراتيجيات الأتمتة. بحلول النهاية، ستدرك لماذا اختبار عقد واجهة برمجة التطبيقات ليس مجرد ميزة لطيفة يجب توفرها، بل هو حجر الزاوية في تطوير البرامج القوية. دعنا نبدأ هذه الرحلة معًا، كاشفين كيف يمكن دمج اختبار عقد واجهة برمجة التطبيقات بسلاسة في سير عملك.

💡
هل تريد أداة رائعة لاختبار واجهة برمجة التطبيقات (API Testing) تولد وثائق API جميلة؟

هل تريد منصة متكاملة وشاملة لفريق المطورين لديك للعمل معًا بأقصى قدر من الإنتاجية؟

يلبي Apidog جميع متطلباتك، ويحل محل Postman بسعر أكثر بأسعار معقولة بكثير!
زر

ما هو اختبار عقد واجهة برمجة التطبيقات (API Contract Testing)؟

يضمن اختبار عقد واجهة برمجة التطبيقات أن تظل الواجهة المتفق عليها بين مزود واجهة برمجة التطبيقات ومستهلكيها متسقة مع تطور الأنظمة. يصف هذا العقد، المحدد من خلال مواصفات OpenAPI أو Swagger، بنية الطلب والاستجابة المتوقعة—نقاط النهاية، والأساليب، والمخططات، والرؤوس، وأكواد الحالة—تمامًا مثل اتفاق رسمي يعتمد عليه الطرفان.

يتخذ اختبار عقد واجهة برمجة التطبيقات عمومًا شكلين. تحدد العقود التي يقودها المستهلك (CDCs) التوقعات من وجهة نظر المستهلك لمنع فشل التكامل في الخدمات المصغرة. تغطي العقود المحددة من قبل المزود، التي أنشأها فريق واجهة برمجة التطبيقات، جميع التفاعلات المدعومة للتحقق الأوسع. على عكس الاختبارات الوظيفية أو اختبارات الوحدات، تركز هذه الاختبارات بشكل صارم على واجهة واجهة برمجة التطبيقات، وليس على المنطق الأساسي.

أهمية اختبار عقد واجهة برمجة التطبيقات (API Contract Testing)

لماذا يجب إعطاء الأولوية لاختبار عقد واجهة برمجة التطبيقات في دورة حياة التطوير الخاصة بك؟ يمكن لتغيير بسيط في واجهة برمجة التطبيقات أن يتسبب في فشل كبير في المراحل اللاحقة. يضمن التحقق من العقود مبكرًا التواصل المتسق بين الخدمات ويمنع المشكلات قبل وقت طويل من وصولها إلى مرحلة الإنتاج.

تشمل الفوائد الرئيسية لاختبار عقد واجهة برمجة التطبيقات ما يلي:

في البيئات السريعة التطور والتكرارية مثل التجارة الإلكترونية أو SaaS، يصبح اختبار عقد واجهة برمجة التطبيقات ضروريًا لتقديم تطبيقات مستقرة، ومتوقعة، وسهلة الاستخدام.

تحديات اختبار عقد واجهة برمجة التطبيقات يدويًا

يصبح التنفيذ اليدوي لاختبار عقد واجهة برمجة التطبيقات غير عملي بسرعة مع نمو واجهات برمجة التطبيقات. إن صياغة الطلبات يدويًا، والتحقق من الاستجابات مقابل المواصفات، والتحقق من الرؤوس أو رموز الأخطاء بطيء، وعرضة للخطأ، ويصعب توسيعه.

تشمل التحديات الرئيسية لاختبار عقد واجهة برمجة التطبيقات يدويًا ما يلي:

تسلط هذه القيود الضوء على سبب كون اختبار عقد واجهة برمجة التطبيقات المؤتمت ضروريًا لتطوير واجهة برمجة تطبيقات سريعة وموثوقة. تقوض الفحوصات اليدوية البطيئة وغير المتسقة الثقة في استقرار واجهة برمجة التطبيقات.

البدء باختبار عقد واجهة برمجة التطبيقات في Apidog

هل أنت مستعد لتسخير اختبار عقد واجهة برمجة التطبيقات في مشاريعك؟ Apidog، وهي منصة شاملة لتطوير واجهة برمجة التطبيقات، تبسط هذا الأمر من خلال إمكانيات التحقق من المخطط والبرمجة النصية المضمنة، مما يجعلها نقطة دخول مثالية.

لتمكين اختبار عقد واجهة برمجة التطبيقات في Apidog، ابدأ باستيراد مواصفات OpenAPI الخاصة بك أو إنشاء مشروع جديد—يقوم Apidog بتوليد الاختبارات تلقائيًا من المخططات، مما يبسط عملية الإعداد.

إنشاء مشروع جديد في Apidog

للحصول على مثال عملي، دعنا نستخدم مشروع "متجر الحيوانات الأليفة التجريبي" في Apidog، وهو مثال كلاسيكي لاستكشاف واجهة برمجة التطبيقات. قم بتشغيل Apidog، وحدد مشروع "Demo Pet"، وانتقل إلى نقطة نهاية GET "/pet/{petId}" (ملاحظة: يستخدم الاستعلام "/get/pets/{id}"، ولكن تماشيًا مع معيار Petstore، فهو "/pet/{petId}"). قم بتعيين البيئة إلى "petstore env" أو "localmock" عبر القائمة المنسدلة العلوية اليسرى،

تحديد بيئة

ثم قم بتنفيذ الطلب. يجب أن تتلقى استجابة مثل:

{
  "id": 1,
  "category": {
    "id": 1,
    "name": "dogs"
  },
  "name": "doggie",
  "photoUrls": [],
  "tags": [],
  "status": "available"
}

هذا يمهد الطريق للتحقق من العقد.

توجه إلى علامة التبويب "Test Cases" (حالات الاختبار) وأنشئ مجموعة جديدة بالنقر على "Add Case" (إضافة حالة).

إضافة حالات اختبار

في قسم المعالجات المسبقة (pre-processors)، أضف نصًا برمجيًا مخصصًا لتحديد مخطط JSON والمتغيرات الخاصة بك:

الخطوة 1: توجه إلى المعالجات المسبقة (Pre-Processors)

إنشاء نص برمجي اختبار مخصص في Apidog

الخطوة 2: أضف كود JS المخصص

إضافة كود نص برمجي اختبار js مخصص في Apidog
// Set petId if not set (as string)
if (!pm.environment.get("petId")) {
  pm.environment.set("petId", "1");
}

// Define JSON schema for the pet response
const petSchema = {
  "$schema": "http://json-schema.org/draft-07/schema#",
  "type": "object",
  "properties": {
    "id": { "type": "integer" },
    "category": {
      "type": "object",
      "properties": {
        "id": { "type": "integer" },
        "name": { "type": "string" }
      },
      "required": ["id", "name"],
      "additionalProperties": true
    },
    "name": { "type": "string" },
    "photoUrls": {
      "type": "array",
      "items": { "type": "string", "format": "uri" },
      "minItems": 0
    },
    "tags": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "id": { "type": "integer" },
          "name": { "type": "string" }
        },
        "required": ["id", "name"],
        "additionalProperties": true
      },
      "minItems": 0
    },
    "status": {
      "type": "string",
      "enum": ["available", "pending", "sold"]
    }
  },
  "required": ["id", "name", "photoUrls", "status"],
  "additionalProperties": true
};

// Store the schema in an environment variable (stringify it)
pm.environment.set("pet_schema", JSON.stringify(petSchema));

// (Optional) log to console for debugging
console.log("Pre-processor: petId =", pm.environment.get("petId"));

بعد ذلك، في المعالجات اللاحقة (post-processors)، الصق النص البرمجي للتحقق من الصحة:

إضافة نص برمجي مخصص للمعالجات اللاحقة
// Use AJV for schema validation
var Ajv = require('ajv');
var ajv = new Ajv({ allErrors: true, logger: console });

// Retrieve schema from environment
var raw = pm.environment.get("pet_schema");
var schema;
try {
  schema = (typeof raw === 'string') ? JSON.parse(raw) : raw;
} catch (err) {
  pm.test('Schema is valid JSON', function() {
    pm.expect(false, 'pet_schema is not valid JSON: ' + err.message).to.be.true;
  });
  // Stop further tests
  return;
}

// Parse the response body as JSON
var responseData;
try {
  responseData = pm.response.json();
} catch (err) {
  pm.test('Response is valid JSON', function() {
    pm.expect(false, 'Response body is not JSON: ' + err.message).to.be.true;
  });
  return;
}

// Test status code
pm.test('Status code is 200', function() {
  pm.expect(pm.response.status).to.eql("OK");
});

// Validate schema
pm.test('Response matches pet schema', function() {
  var valid = ajv.validate(schema, responseData);
  if (!valid) {
    console.log('AJV Errors:', ajv.errors);
  }
  pm.expect(valid, 'Response does not match schema, see console for errors').to.be.true;
});

// Additional assertions
pm.test('Returned id matches requested petId', function() {
  var requested = pm.environment.get("petId");
  // petId is stored as string, but id in response is integer
  var requestedNum = Number(requested);
  if (!isNaN(requestedNum)) {
    pm.expect(responseData.id).to.eql(requestedNum);
  } else {
    pm.expect(String(responseData.id)).to.eql(String(requested));
  }
});

pm.test('Name is a string', function() {
  pm.expect(responseData.name).to.be.a('string');
});

pm.test('Status is one of expected values', function() {
  pm.expect(responseData.status).to.be.oneOf(['available', 'pending', 'sold']);
});

// Optional: more detailed checks (category, photoUrls, tags)
pm.test('Category has id and name', function() {
  pm.expect(responseData.category).to.have.property('id');
  pm.expect(responseData.category).to.have.property('name');
});

pm.test('At least one photo URL', function() {
  pm.expect(responseData.photoUrls).to.be.an('array').that.is.not.empty;
});

pm.test('Tags are valid objects', function() {
  pm.expect(responseData.tags).to.be.an('array');
  if (responseData.tags.length > 0) {
    responseData.tags.forEach(function(tag) {
      pm.expect(tag).to.have.property('id');
      pm.expect(tag).to.have.property('name');
    });
  }
});

انقر على "Run" (تشغيل) للتنفيذ. يعرض Apidog النتائج على اليمين: "Passed" (نجح) أو "Failed" (فشل)، مع تفاصيل قابلة للتوسيع. قد تظهر عملية تشغيل ناجحة ما يلي:

استجابة واجهة برمجة التطبيقات:

استجابة واجهة برمجة التطبيقات
{
  "id": 1,
  "category": {
    "id": 1,
    "name": "dog"
  },
  "name": "Jasper",
  "photoUrls": [
    "https://loremflickr.com/400/400?lock=7187959506185006"
  ],
  "tags": [
    {
      "id": 3,
      "name": "Yellow"
    }
  ],
  "status": "available"
}

الاختبارات التي نجحت:

  1. رمز الحالة هو 200
  2. الاستجابة تطابق مخطط الحيوان الأليف
  3. المعرف الذي تم إرجاعه يطابق petId المطلوب
  4. الاسم هو سلسلة نصية
  5. الحالة هي إحدى القيم المتوقعة
  6. الفئة لديها معرف واسم
  7. عنوان URL لصورة واحد على الأقل
  8. العلامات هي كائنات صالحة
عرض نتائج اختبار عقد واجهة برمجة التطبيقات

لمحاكاة الفشل، قم بتغيير اختبار رمز الحالة ليتوقع رقمًا (200) بدلاً من "OK"،

تغيير نص اختبار js

ثم أعد التشغيل ولاحظ خطأ التأكيد.

خطأ التأكيد

احفظ المجموعة لعمليات تشغيل الانحدار. إن واجهة Apidog البديهية، مع تكامل AJV للتحقق من المخطط، تعمل على ديمقراطية اختبار عقد واجهة برمجة التطبيقات، وتحول عمليات التحقق المعقدة إلى مهام روتينية.

الأسئلة المتكررة

س1. ما الذي يميز اختبار عقد واجهة برمجة التطبيقات عن اختبار التكامل؟

الإجابة: يتحقق اختبار عقد واجهة برمجة التطبيقات من عقد الواجهة دون تنفيذ منطق الأعمال، بينما يفحص اختبار التكامل كيفية تفاعل الخدمات، بما في ذلك تدفق البيانات والتبعيات.

س2. هل يمكن تطبيق اختبار عقد واجهة برمجة التطبيقات على واجهات برمجة تطبيقات GraphQL؟

الإجابة: نعم، على الرغم من أنها مصممة بشكل أساسي لـ REST، إلا أن أدوات مثل Pact تدعم مخططات GraphQL، مع التركيز على هياكل الاستعلام/الاستجابة والطفرات.

س3. كم مرة يجب تشغيل اختبار عقد واجهة برمجة التطبيقات في مسار CI/CD؟

الإجابة: من الناحية المثالية، عند كل عملية التزام (commit) أو طلب سحب (pull request) لاكتشاف المشكلات مبكرًا، مع تشغيل ليلي لتغطية شاملة.

س4. ماذا لو افتقر فريقي إلى مواصفات OpenAPI لاختبار العقد؟

الإجابة: ابدأ بإنشاء واحدة من الكود الحالي باستخدام أدوات مثل Swagger Codegen، ثم قم بتحسينها بالتعاون لتحديد الأساس.

س5. هل اختبار عقد واجهة برمجة التطبيقات مناسب لواجهات برمجة التطبيقات القديمة؟

الإجابة: بالتأكيد—قم بتعديل المواصفات لتوثيق السلوك الحالي، ثم أتمتة الاختبارات للحماية من التراجعات أثناء التحديث.

الخاتمة

بينما نختتم استكشافنا، يتضح أن اختبار عقد واجهة برمجة التطبيقات هو الدعامة الأساسية لواجهات برمجة التطبيقات الموثوقة والقابلة للتوسع في عالم مترابط. من تخفيف العمل اليدوي الشاق إلى تمكين الضمانات الآلية، فإنه يزود الفرق بالقدرة على الابتكار دون خوف. احتضن أدوات مثل Apidog للارتقاء بممارستك، وشاهد كيف تكتسب تطبيقاتك المرونة والكفاءة. سواء كنت تقوم بتحسين العقود الحالية أو صياغة عقود جديدة، فإن الطريق إلى حوكمة واجهة برمجة تطبيقات متفوقة يبدأ باختبار واحد محدد جيدًا.

💡
هل تريد أداة رائعة لاختبار واجهة برمجة التطبيقات (API Testing) تولد وثائق API جميلة؟

هل تريد منصة متكاملة وشاملة لفريق المطورين لديك للعمل معًا بأقصى قدر من الإنتاجية؟

يلبي Apidog جميع متطلباتك، ويحل محل Postman بسعر أكثر بأسعار معقولة بكثير!
زر

ممارسة تصميم API في Apidog

اكتشف طريقة أسهل لبناء واستخدام واجهات برمجة التطبيقات