تنجح اختبارات Playwright لديك: يتم النقر على زر تسجيل الدخول، تظهر لوحة التحكم، ويرسم الرسم البياني. ثم يبلغ عميل عن خطأ: أرقام الرسم البياني غير صحيحة. عند الفحص تجد أن الـ API أعادت 200 OK مع حمولة مشوهة، لكن اختبار E2E لم يلتقط ذلك لأنه تحقق فقط من ظهور عناصر الواجهة. هذه هي الفجوة التي لا تسدها اختبارات المتصفح وحدها. تحتاج إلى تأكيدات API تتحقق من العقد، المخطط، ودلالات الاستجابة. أدوات مثل Apidog تساعدك على اختبار مواصفات OpenAPI وسيناريوهات API وتشغيلها بجانب Playwright داخل CI.
ملخص سريع
أفضل نمط عملي هو تشغيل طبقتين من الاختبارات:
- 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);
هذا جيد كبداية، لكنه لا يكفي عند التوسع. غالبًا تنتهي بمئات الاختبارات التي تتحقق من status code فقط، بينما تتسرب أخطاء مثل:
تراجع شكل الحمولة
تغير الحقل منtotal_countإلىtotalCount. الواجهة قد تعرض صفرًا أو تحول القيمة ضمنيًا، فيمر اختبار UI.انحراف منطق العمل
نقطة نهاية الخصم تعيد10%بدل15%. الواجهة تعرض ما وصلها، والاختبار ينجح رغم أن النتيجة خاطئة.ضعف تغطية مسارات الأخطاء
اختبارات 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
القواعد:
-
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 };
بعد ذلك، استورد 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,
);
});
هذا الاختبار لا يكتفي بـ 201. بل يتحقق من دلالة مهمة: discount_pct يجب أن تكون 15.
ربط نفس البيانات داخل Apidog
في Apidog:
- افتح المشروع.
- اختر Import.
- استورد
openapi.yaml. - أنشئ سيناريو مثل
Checkout. - أضف خطوة
POST /orders. - استخدم نفس حمولة
fixtures/order.jsonكـ body أو Data Set. - فعّل JSON Schema validation مقابل مكوّن
Orderفي OpenAPI. - أضف تأكيدًا على
discount_pct = 15.
بهذا تحصل على طبقتين:
- Playwright يلتقط التأكيد الدلالي المرتبط بتدفق المستخدم.
- Apidog يلتقط أي انحراف في المخطط، الحقول المطلوبة، الأنواع، أو enum values.
إذا كنت تستخدم Postman حاليًا وتفكر في الانتقال، راجع بدائل Postman المستضافة ذاتيًا.
إعداد سير عمل Apidog + Playwright
الخطوة 1: اجعل OpenAPI هو العقد
ضع ملف المواصفات في جذر المستودع:
openapi.yaml
وتعامل معه ككود:
- كل تغيير يمر عبر PR.
- التغييرات الكاسرة تحتاج مراجعة واضحة.
- لا تعدّل fixtures بمعزل عن spec.
- إذا لم يكن لديك spec، أنشئ مسودة من إطار العمل المستخدم مثل FastAPI أو NestJS، ثم حسّنها يدويًا.
يمكن لـ Apidog أيضًا المساعدة في بناء مواصفات من حركة API عند استيراد ملفات HAR.
الخطوة 2: ثبّت Playwright
npm init playwright@latest
أضف سكريبتات الاختبار:
{
"scripts": {
"test:e2e": "playwright test",
"test:e2e:smoke": "playwright test --grep @smoke"
}
}
مثال 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',
},
});
الخطوة 3: ابنِ سيناريوهات Apidog
أنشئ سيناريو لكل رحلة حرجة:
- التسجيل.
- تسجيل الدخول.
- إنشاء طلب.
- الدفع.
- رد الأموال.
- webhook delivery.
- idempotency checks.
داخل كل سيناريو:
- نفّذ request.
- خزّن قيمًا مثل
order_idأوpayment_id. - استخدمها في الخطوات التالية.
- شغّل schema validation.
- أضف assertions لمنطق العمل.
مثال تدفق:
POST /auth/token
POST /orders
GET /orders/{id}
POST /payments
GET /payments/{id}
ثم صدّر السيناريو للتشغيل عبر CLI:
apidog-cli run ./apidog/scenarios/checkout.json
استخدام 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);
});
هذا مفيد لعزل الواجهة، لكنه ليس بديلًا لاختبار 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 }}
أي فشل في Playwright أو Apidog يمنع الدمج.
تغطي وثائق GitHub Actions إعداد المصفوفات، التخزين المؤقت، وتشغيل jobs بالتوازي.
اكتشاف انحراف العقد مبكرًا
أضف مهمة يومية تقارن المواصفات الحالية بالنسخة المستخدمة في الاختبارات. الفكرة:
openapi-diff old-openapi.yaml openapi.yaml
إذا تغيّر نوع حقل أو اختفى حقل مطلوب، افشل البناء قبل تشغيل الاختبارات.
هذا يلتقط فئة أخطاء مثل:
200 OK
لكن body لا يطابق العقد
وهي المشكلة التي لا تلتقطها اختبارات UI غالبًا.
تقنيات عملية لتحسين الاستقرار
فعّل Playwright trace
في playwright.config.ts:
use: {
trace: 'on-first-retry',
}
عند الفشل تحصل على:
- 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
إذا احتاج الاختبار إلى 5 محاولات، فالمشكلة ليست في CI فقط. لديك test flaky أو backend غير مستقر. في سيناريوهات Apidog، اجعل retry لكل request محدودًا.
افشل عند انحراف المخطط
لا تجعل schema mismatch مجرد warning. يجب أن يفشل CI.
إذا احتجت إلى فترة انتقالية، اجعلها صريحة:
ALLOW_SCHEMA_DRIFT=true
واطلب تعليقًا في PR يشرح السبب.
صنّف الاختبارات
استخدم tags:
test('checkout @smoke', async ({ page }) => {
// ...
});
استراتيجية تشغيل مقترحة:
-
@smokeعلى كل push. - regression على PR إلى
main. - سيناريوهات Apidog الكاملة ليلًا.
- الاختبارات ذات الحالة stateful تعمل serial.
test.describe.configure({ mode: 'serial' });
أخطاء شائعة يجب تجنبها
- الاكتفاء بـ
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
إذا تغيّر حقل مثل 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 },
});
ثم خزّنه في 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)