DEV Community

Cover image for التحقق من استجابات API في اختبارات بلاي رايت
Yusuf Khalidd
Yusuf Khalidd

Posted on • Originally published at apidog.com

التحقق من استجابات API في اختبارات بلاي رايت

تنجح اختبارات Playwright لديك: يتم النقر على زر تسجيل الدخول، تظهر لوحة التحكم، ويرسم الرسم البياني. ثم يبلغ عميل عن خطأ: أرقام الرسم البياني غير صحيحة. عند الفحص تجد أن الـ API أعادت 200 OK مع حمولة مشوهة، لكن اختبار E2E لم يلتقط ذلك لأنه تحقق فقط من ظهور عناصر الواجهة. هذه هي الفجوة التي لا تسدها اختبارات المتصفح وحدها. تحتاج إلى تأكيدات API تتحقق من العقد، المخطط، ودلالات الاستجابة. أدوات مثل Apidog تساعدك على اختبار مواصفات OpenAPI وسيناريوهات API وتشغيلها بجانب Playwright داخل CI.

جرّب Apidog اليوم

ملخص سريع

أفضل نمط عملي هو تشغيل طبقتين من الاختبارات:

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

اجعل مصدر الحقيقة واحدًا: ملف openapi.yaml أو openapi.json. استخدمه في Playwright لتوليد fixtures وطلبات متوقعة، واستورده في Apidog لبناء السيناريوهات والتأكيدات. بعد ذلك شغّل المجموعتين في CI بحيث يفشل أي تغيير غير متوافق في العقد بسرعة.

لماذا لا تكفي اختبارات Playwright وحدها؟

توثيق Playwright يوضح أن اختبار API ممكن عبر أداة request:

const response = await request.get('/api/orders');
expect(response.status()).toBe(200);
Enter fullscreen mode Exit fullscreen mode

هذا جيد كبداية، لكنه لا يكفي عند التوسع. غالبًا تنتهي بمئات الاختبارات التي تتحقق من status code فقط، بينما تتسرب أخطاء مثل:

  1. تراجع شكل الحمولة

    تغير الحقل من total_count إلى totalCount. الواجهة قد تعرض صفرًا أو تحول القيمة ضمنيًا، فيمر اختبار UI.

  2. انحراف منطق العمل

    نقطة نهاية الخصم تعيد 10% بدل 15%. الواجهة تعرض ما وصلها، والاختبار ينجح رغم أن النتيجة خاطئة.

  3. ضعف تغطية مسارات الأخطاء

    اختبارات Playwright تميل إلى happy path. لكنها لا تغطي عادةً حالات 401، 409، 429، أو الفشل الجزئي.

الحل العملي: لا تجعل Playwright مسؤولًا عن كل شيء. استخدمه للواجهة، واستخدم Apidog لاختبار API كسيناريوهات مستقلة مبنية على نفس OpenAPI spec. إذا أردت تجهيز الأداة أولًا، يمكنك تنزيل Apidog.

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

البنية المقترحة

استخدم هذا التقسيم:

repo/
├─ openapi.yaml
├─ fixtures/
│  └─ order.json
├─ tests/
│  ├─ fixtures/
│  │  └─ api.ts
│  ├─ orders.spec.ts
│  └─ dashboard.spec.ts
└─ apidog/
   └─ scenarios/
      └─ checkout.json
Enter fullscreen mode Exit fullscreen mode

القواعد:

  • openapi.yaml هو العقد الرسمي.
  • ملفات fixtures/ هي بيانات الاختبار المشتركة.
  • Playwright يقرأ fixtures لتنفيذ UI/API smoke checks.
  • Apidog يستورد نفس OpenAPI ويبني عليها السيناريوهات.
  • CI يشغّل Playwright و Apidog معًا.

للمزيد حول نهج التصميم أولًا، راجع سير عمل واجهة برمجة التطبيقات القائمة على التصميم أولاً.

إنشاء fixture مشترك في Playwright

ابدأ بملف fixture واحد يجهز APIRequestContext، يجلب token جديدًا، ويحمّل بيانات الطلب من fixtures/order.json.

// tests/fixtures/api.ts
import { test as base, APIRequestContext, expect } from '@playwright/test';
import { readFileSync } from 'fs';
import path from 'path';

type ApiFixtures = {
  apiRequest: APIRequestContext;
  authToken: string;
  sampleOrder: Record<string, unknown>;
};

export const test = base.extend<ApiFixtures>({
  apiRequest: async ({ playwright }, use) => {
    const ctx = await playwright.request.newContext({
      baseURL: process.env.API_BASE_URL ?? 'https://api.staging.example.com',
      extraHTTPHeaders: {
        Accept: 'application/json',
        'Content-Type': 'application/json',
      },
    });

    await use(ctx);
    await ctx.dispose();
  },

  authToken: async ({ apiRequest }, use) => {
    const res = await apiRequest.post('/auth/token', {
      data: {
        email: 'qa@example.com',
        password: process.env.QA_PASSWORD,
      },
    });

    expect(res.status()).toBe(200);

    const body = await res.json();
    await use(body.access_token);
  },

  sampleOrder: async ({}, use) => {
    const raw = readFileSync(
      path.join(__dirname, '..', '..', 'fixtures', 'order.json'),
      'utf8',
    );

    await use(JSON.parse(raw));
  },
});

export { expect };
Enter fullscreen mode Exit fullscreen mode

بعد ذلك، استورد test من هذا الملف بدلًا من @playwright/test:

// tests/orders.spec.ts
import { test, expect } from './fixtures/api';

test('POST /orders returns a valid order with 15 percent discount', async ({
  apiRequest,
  authToken,
  sampleOrder,
}) => {
  const res = await apiRequest.post('/orders', {
    headers: { Authorization: `Bearer ${authToken}` },
    data: { ...sampleOrder, coupon: 'SAVE15' },
  });

  expect(res.status()).toBe(201);

  const body = await res.json();

  expect(body).toMatchObject({
    id: expect.any(String),
    status: 'pending',
    discount_pct: 15,
    total_cents: expect.any(Number),
  });

  expect(body.total_cents).toBeLessThan(
    sampleOrder.subtotal_cents as number,
  );
});
Enter fullscreen mode Exit fullscreen mode

هذا الاختبار لا يكتفي بـ 201. بل يتحقق من دلالة مهمة: discount_pct يجب أن تكون 15.

ربط نفس البيانات داخل Apidog

في Apidog:

  1. افتح المشروع.
  2. اختر Import.
  3. استورد openapi.yaml.
  4. أنشئ سيناريو مثل Checkout.
  5. أضف خطوة POST /orders.
  6. استخدم نفس حمولة fixtures/order.json كـ body أو Data Set.
  7. فعّل JSON Schema validation مقابل مكوّن Order في OpenAPI.
  8. أضف تأكيدًا على discount_pct = 15.

بهذا تحصل على طبقتين:

  • Playwright يلتقط التأكيد الدلالي المرتبط بتدفق المستخدم.
  • Apidog يلتقط أي انحراف في المخطط، الحقول المطلوبة، الأنواع، أو enum values.

إذا كنت تستخدم Postman حاليًا وتفكر في الانتقال، راجع بدائل Postman المستضافة ذاتيًا.

إعداد سير عمل Apidog + Playwright

الخطوة 1: اجعل OpenAPI هو العقد

ضع ملف المواصفات في جذر المستودع:

openapi.yaml
Enter fullscreen mode Exit fullscreen mode

وتعامل معه ككود:

  • كل تغيير يمر عبر PR.
  • التغييرات الكاسرة تحتاج مراجعة واضحة.
  • لا تعدّل fixtures بمعزل عن spec.
  • إذا لم يكن لديك spec، أنشئ مسودة من إطار العمل المستخدم مثل FastAPI أو NestJS، ثم حسّنها يدويًا.

يمكن لـ Apidog أيضًا المساعدة في بناء مواصفات من حركة API عند استيراد ملفات HAR.

الخطوة 2: ثبّت Playwright

npm init playwright@latest
Enter fullscreen mode Exit fullscreen mode

أضف سكريبتات الاختبار:

{
  "scripts": {
    "test:e2e": "playwright test",
    "test:e2e:smoke": "playwright test --grep @smoke"
  }
}
Enter fullscreen mode Exit fullscreen mode

مثال playwright.config.ts مختصر:

import { defineConfig } from '@playwright/test';

export default defineConfig({
  testDir: './tests',
  retries: 2,
  workers: 4,
  use: {
    baseURL: process.env.APP_BASE_URL ?? 'https://staging.example.com',
    trace: 'on-first-retry',
  },
});
Enter fullscreen mode Exit fullscreen mode

الخطوة 3: ابنِ سيناريوهات Apidog

أنشئ سيناريو لكل رحلة حرجة:

  • التسجيل.
  • تسجيل الدخول.
  • إنشاء طلب.
  • الدفع.
  • رد الأموال.
  • webhook delivery.
  • idempotency checks.

داخل كل سيناريو:

  1. نفّذ request.
  2. خزّن قيمًا مثل order_id أو payment_id.
  3. استخدمها في الخطوات التالية.
  4. شغّل schema validation.
  5. أضف assertions لمنطق العمل.

مثال تدفق:

POST /auth/token
POST /orders
GET /orders/{id}
POST /payments
GET /payments/{id}
Enter fullscreen mode Exit fullscreen mode

ثم صدّر السيناريو للتشغيل عبر CLI:

apidog-cli run ./apidog/scenarios/checkout.json
Enter fullscreen mode Exit fullscreen mode

استخدام page.route لعزل الواجهة

عندما تريد اختبار UI دون الاعتماد على backend مباشر، استخدم page.route مع نفس fixtures:

// tests/dashboard.spec.ts
import { test, expect } from './fixtures/api';

test('dashboard renders cached order list when offline', async ({
  page,
  sampleOrder,
}) => {
  await page.route('**/api/orders', async (route) => {
    await route.fulfill({
      status: 200,
      contentType: 'application/json',
      body: JSON.stringify({ orders: [sampleOrder] }),
    });
  });

  await page.goto('/dashboard');

  await expect(page.getByTestId('order-row')).toHaveCount(1);
});
Enter fullscreen mode Exit fullscreen mode

هذا مفيد لعزل الواجهة، لكنه ليس بديلًا لاختبار API الحقيقي. لذلك شغّل في Apidog سيناريو GET /orders مقابل backend الفعلي أو mock server.

تشغيل Playwright و Apidog في GitHub Actions

أضف workflow يشغّل المجموعتين:

name: tests

on: [push, pull_request]

jobs:
  playwright:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v4

      - uses: actions/setup-node@v4
        with:
          node-version: '20'

      - run: npm ci

      - run: npx playwright install --with-deps

      - run: npx playwright test
        env:
          APP_BASE_URL: ${{ secrets.APP_BASE_URL }}
          API_BASE_URL: ${{ secrets.API_BASE_URL }}
          QA_PASSWORD: ${{ secrets.QA_PASSWORD }}

  apidog:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v4

      - uses: actions/setup-node@v4
        with:
          node-version: '20'

      - run: npm i -g apidog-cli

      - run: apidog-cli run ./apidog/scenarios/checkout.json --reporters cli,junit
        env:
          API_BASE_URL: ${{ secrets.API_BASE_URL }}
          QA_PASSWORD: ${{ secrets.QA_PASSWORD }}
Enter fullscreen mode Exit fullscreen mode

أي فشل في Playwright أو Apidog يمنع الدمج.

تغطي وثائق GitHub Actions إعداد المصفوفات، التخزين المؤقت، وتشغيل jobs بالتوازي.

اكتشاف انحراف العقد مبكرًا

أضف مهمة يومية تقارن المواصفات الحالية بالنسخة المستخدمة في الاختبارات. الفكرة:

openapi-diff old-openapi.yaml openapi.yaml
Enter fullscreen mode Exit fullscreen mode

إذا تغيّر نوع حقل أو اختفى حقل مطلوب، افشل البناء قبل تشغيل الاختبارات.

هذا يلتقط فئة أخطاء مثل:

200 OK
لكن body لا يطابق العقد
Enter fullscreen mode Exit fullscreen mode

وهي المشكلة التي لا تلتقطها اختبارات UI غالبًا.

تقنيات عملية لتحسين الاستقرار

فعّل Playwright trace

في playwright.config.ts:

use: {
  trace: 'on-first-retry',
}
Enter fullscreen mode Exit fullscreen mode

عند الفشل تحصل على:

  • network timeline.
  • DOM snapshots.
  • console logs.
  • screenshots.

ادمج ذلك مع تقارير Apidog لتعرف هل الانهيار بدأ من الواجهة أم من API.

استخدم mock server من Apidog

عندما تكون بيئة staging غير مستقرة، شغّل mock server من OpenAPI spec، ثم وجّه تطبيقك إليه محليًا.

النمط المقترح:

  • Playwright يعمل ضد mock server عند الحاجة لعزل UI.
  • Apidog يعمل ضد backend الحقيقي للتحقق من العقد.
  • نفس fixtures تُستخدم في الحالتين.

للمزيد حول توليد اختبارات API، راجع إنشاء اختبارات واجهة برمجة التطبيقات بمساعدة الذكاء الاصطناعي.

لا ترفع retries أكثر من اللازم

استخدم:

retries: 2
Enter fullscreen mode Exit fullscreen mode

إذا احتاج الاختبار إلى 5 محاولات، فالمشكلة ليست في CI فقط. لديك test flaky أو backend غير مستقر. في سيناريوهات Apidog، اجعل retry لكل request محدودًا.

افشل عند انحراف المخطط

لا تجعل schema mismatch مجرد warning. يجب أن يفشل CI.

إذا احتجت إلى فترة انتقالية، اجعلها صريحة:

ALLOW_SCHEMA_DRIFT=true
Enter fullscreen mode Exit fullscreen mode

واطلب تعليقًا في PR يشرح السبب.

صنّف الاختبارات

استخدم tags:

test('checkout @smoke', async ({ page }) => {
  // ...
});
Enter fullscreen mode Exit fullscreen mode

استراتيجية تشغيل مقترحة:

  • @smoke على كل push.
  • regression على PR إلى main.
  • سيناريوهات Apidog الكاملة ليلًا.
  • الاختبارات ذات الحالة stateful تعمل serial.
test.describe.configure({ mode: 'serial' });
Enter fullscreen mode Exit fullscreen mode

أخطاء شائعة يجب تجنبها

  • الاكتفاء بـ status === 200.
  • تخزين bearer tokens داخل fixtures.
  • استخدام fixtures مختلفة بين Playwright و Apidog.
  • تجاهل تشغيل Apidog CLI في CI.
  • اعتبار page.route بديلًا لاختبار API الحقيقي.
  • تعديل OpenAPI بدون تحديث السيناريوهات.
  • بناء assertions كثيرة داخل اختبار UI بدل نقلها إلى طبقة API.

للاختبارات غير الحتمية، خصوصًا مع وكلاء الذكاء الاصطناعي، راجع كيفية اختبار واجهة برمجة تطبيقات وكلاء الذكاء الاصطناعي.

مقارنة الأدوات

المكدس نقاط القوة نقاط الضعف الأفضل لـ
Playwright وحده أداة واحدة، سريع، مدمج مع اختبارات UI تحقق محدود من المخطط، سيناريوهات API متسلسلة أصعب فرق صغيرة وواجهات API بسيطة
Playwright + Postman نظام Postman ناضج، Newman CLI احتمال وجود مصدرين للحقيقة وانحراف collections عن OpenAPI فرق تستخدم Postman بالفعل
Playwright + Apidog OpenAPI كمصدر واحد، schema validation، mock server، CLI لـ CI أداتان للتعلم، ويتطلب انضباطًا في المواصفات فرق تريد اختبارًا موجهًا بالمواصفات
Cypress + cy-api مألوف لمستخدمي Cypress اختبار API أقل مرونة، والاعتماد على plugins مشاريع Cypress الحالية
Pact عقود قوية بين الخدمات منحنى تعلم أعلى ولا يركز على UI منظمات microservices كثيرة المستهلكين

إذا كنت تنتقل من أدوات أقدم، راجع:

حالات استخدام واقعية

checkout في التجارة الإلكترونية

Playwright يتحقق من رحلة المستخدم من السلة إلى صفحة التأكيد. Apidog يتحقق من سلسلة API:

POST /orders
POST /payments
GET /inventory
POST /refunds
Enter fullscreen mode Exit fullscreen mode

إذا تغيّر حقل مثل error_code إلى errorCode، يلتقط Apidog انحراف المخطط بسرعة، بينما قد يعرض Playwright رسالة عامة مثل "فشل الدفع".

لوحة تحكم SaaS للرسوم البيانية

Playwright يتحقق من ظهور الرسم البياني. Apidog يتحقق من أن endpoints التجميع تعيد:

  • المجاميع الصحيحة.
  • النسب المئوية.
  • السلاسل الزمنية المتوقعة.
  • الحقول المطلوبة حسب OpenAPI.

بهذا لا تمر شاشة جميلة فوق بيانات خاطئة.

webhooks في fintech

Playwright يغطي البوابة المرئية. Apidog يغطي:

  • webhook delivery.
  • retry behavior.
  • idempotency.
  • signature validation.
  • رفض webhook مكرر.
  • نافذة eventual consistency أقل من 30 ثانية.

الخلاصة

Playwright ممتاز لاختبارات المتصفح، لكنه ليس كافيًا لاختبار API بعمق. الإعداد العملي هو:

  • OpenAPI spec واحد كمصدر حقيقة.
  • fixtures مشتركة بين Playwright و Apidog.
  • Playwright لتدفقات UI وnetwork stubbing.
  • Apidog للتحقق من schema، السيناريوهات المتسلسلة، ومسارات الأخطاء.
  • CI واحد يشغّل المجموعتين ويفشل عند أي انحراف.

ابدأ برحلة حرجة واحدة مثل التسجيل أو الدفع. اربط fixture في Playwright، أنشئ سيناريو Apidog مطابقًا، ثم شغّلهما معًا في CI. بعد ذلك وسّع التغطية endpoint تلو الآخر.

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

هل يمكنني التحقق من API داخل Playwright بدون Apidog؟

نعم. يمكنك استخدام أداة request في Playwright مع expect. هذا مناسب لفحوصات بسيطة مثل status code وبعض الحقول. لكن للتحقق من المخطط، السيناريوهات المتسلسلة، المحاكاة، ومسارات الأخطاء على نطاق أوسع، أداة مخصصة مثل Apidog ستكون أكثر عملية. راجع مقارنة أدوات اختبار واجهة برمجة التطبيقات لمهندسي ضمان الجودة.

هل أحتاج إلى OpenAPI spec؟

نعم إذا أردت الفائدة الكاملة. بدون OpenAPI يمكنك تشغيل Playwright و Apidog جنبًا إلى جنب، لكنك ستفقد المصدر المشترك للحقيقة وستضطر لصيانة الأمثلة في أكثر من مكان.

كيف أتعامل مع المصادقة؟

اجلب token جديدًا في بداية الاختبار:

const res = await apiRequest.post('/auth/token', {
  data: { email, password },
});
Enter fullscreen mode Exit fullscreen mode

ثم خزّنه في Playwright fixture وفي متغير بيئة داخل Apidog. لا تحفظ tokens ثابتة داخل المستودع.

هل يمكن أن يحل Apidog محل Playwright؟

لا. Apidog يختبر API workflows، لكنه لا يشغّل متصفحًا ولا يتحقق من عناصر الواجهة. استخدم Playwright للنصوص المرئية، النقرات، التنقل، والتخطيط. استخدم Apidog للعقد والمخططات وسلاسل API.

ماذا أفعل إذا لم تكن بيئة staging مستقرة؟

استخدم mock server من Apidog مبنيًا على OpenAPI. شغّل Playwright ضد mock server لعزل الواجهة، وشغّل سيناريوهات Apidog ضد backend الحقيقي عندما تكون البيئة متاحة.

كيف أحافظ على سرعة CI؟

  • شغّل @smoke على كل push.
  • شغّل regression على PRs.
  • شغّل سيناريوهات Apidog الكاملة ليلًا.
  • استخدم workers: 4 في Playwright.
  • شغّل سيناريوهات Apidog بالتوازي إذا كان CLI يدعم ذلك في إعدادك.

هل أحتاج إلى خطة مدفوعة من Apidog لتشغيل CI؟

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

Top comments (0)