مجموعة الاختبارات مقابل حالة الاختبار: ما الفرق؟

Ashley Innocent

Ashley Innocent

4 مارس 2026

مجموعة الاختبارات مقابل حالة الاختبار: ما الفرق؟

Apidog للمؤسسات

النشر على الخوادم المحلية

SSO و RBAC

متوافق مع SOC 2

استكشف Apidog للمؤسسات

باختصار

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

مقدمة

أنت تبني واجهة برمجة تطبيقات (API). تكتب اختبارك الأول. ثم آخر. سرعان ما أصبح لديك 50 اختبارًا منتشرة عبر ملفات مختلفة. أي منها يختبر المصادقة؟ أي منها يتم تشغيله قبل النشر؟ كيف تقوم بتشغيل الاختبارات الحرجة فقط؟

يحدث هذا الارتباك عندما لا يفهم المطورون الفرق بين حالات الاختبار ومجموعات الاختبار. وجدت دراسة استقصائية أجريت عام 2023 وشملت 1200 مطور أن 67% منهم يواجهون صعوبة في تنظيم الاختبارات، مما يؤدي إلى تباطؤ خطوط أنابيب CI/CD وصعوبة في تصحيح الأخطاء. يشكل هذان المفهومان أساس الاختبار المنظم، لكنهما غالبًا ما يستخدمان بالتبادل أو يساء فهمهما.

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

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

ما هي حالة الاختبار؟

حالة الاختبار هي سيناريو اختبار واحد ومحدد يتحقق من سلوك أو متطلب واحد لبرنامجك. فكر في الأمر على أنه سؤال واحد تطرحه على الكود الخاص بك: "هل يعمل هذا بشكل صحيح؟"

تحتوي كل حالة اختبار على ما يلي:

تشريح حالة الاختبار

فيما يلي حالة اختبار بسيطة لنقطة نهاية API:

معرف حالة الاختبار: TC_AUTH_001
العنوان: التحقق من تسجيل دخول المستخدم ببيانات اعتماد صالحة
الشروط المسبقة: حساب المستخدم موجود في قاعدة البيانات
خطوات الاختبار:
  1. إرسال طلب POST إلى /api/auth/login
  2. تضمين بريد إلكتروني وكلمة مرور صالحين في نص الطلب
  3. التحقق من رمز حالة الاستجابة
  4. التحقق من إرجاع رمز JWT
النتيجة المتوقعة:
  - رمز الحالة: 200
  - الاستجابة تحتوي على رمز JWT صالح
  - ينتهي صلاحية الرمز خلال 24 ساعة
النتيجة الفعلية: [يتم تعبئتها أثناء التنفيذ]
الحالة: [نجاح/فشل]

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

مثال على حالة الاختبار في الكود

إليك كيف تبدو نفس حالة الاختبار في JavaScript باستخدام Jest:

describe('Authentication API', () => {
  test('TC_AUTH_001: should login user with valid credentials', async () => {
    const response = await fetch('https://api.example.com/auth/login', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({
        email: 'user@example.com',
        password: 'SecurePass123'
      })
    });

    expect(response.status).toBe(200);
    const data = await response.json();
    expect(data.token).toBeDefined();
    expect(data.expiresIn).toBe(86400); // 24 hours in seconds
  });
});

لاحظ كيف تركز حالة الاختبار هذه على سيناريو واحد: تسجيل الدخول بنجاح. لا تختبر تسجيل الدخول الفاشل، أو إعادة تعيين كلمة المرور، أو تسجيل الخروج. ستكون هذه حالات اختبار منفصلة.

لماذا حالات الاختبار مهمة

تمنحك حالات الاختبار ما يلي:

بدون حالات اختبار واضحة، ينتهي بك الأمر باختبارات غامضة تتحقق من عدة أشياء في وقت واحد. وعندما تفشل، تهدر الوقت في معرفة أي جزء تعطل.

ما هي مجموعة الاختبار؟

مجموعة الاختبار هي مجموعة من حالات الاختبار المجمعة معًا للتنفيذ المنظم. إذا كانت حالات الاختبار أسئلة فردية، فإن مجموعة الاختبار هي الامتحان الذي يحتوي على أسئلة ذات صلة.

تقوم مجموعات الاختبار بتنظيم حالات الاختبار حسب:

هيكل مجموعة الاختبار

إليك كيف تنظم مجموعات الاختبار حالات الاختبار:

مجموعة الاختبار: وحدة المصادقة
├── حالة الاختبار 1: تسجيل الدخول ببيانات اعتماد صالحة
├── حالة الاختبار 2: تسجيل الدخول بكلمة مرور غير صالحة
├── حالة الاختبار 3: تسجيل الدخول ببريد إلكتروني غير موجود
├── حالة الاختبار 4: تسجيل الدخول برمز منتهي الصلاحية
├── حالة الاختبار 5: تسجيل الخروج بنجاح
└── حالة الاختبار 6: تحديث رمز الوصول

مجموعة الاختبار: وحدة ملف تعريف المستخدم
├── حالة الاختبار 1: الحصول على ملف تعريف المستخدم
├── حالة الاختبار 2: تحديث معلومات الملف الشخصي
├── حالة الاختبار 3: تحميل صورة الملف الشخصي
└── حالة الاختبار 4: حذف حساب المستخدم

تحتوي كل مجموعة اختبار على حالات اختبار متعددة ذات صلة. يمكنك تشغيل مجموعة كاملة دفعة واحدة أو اختيار حالات اختبار فردية لتشغيلها.

مثال على مجموعة الاختبار في الكود

إليك كيف تبدو مجموعات الاختبار في JavaScript:

// مجموعة اختبار المصادقة
describe('Authentication API Test Suite', () => {

  test('TC_AUTH_001: Login with valid credentials', async () => {
    // تنفيذ الاختبار
  });

  test('TC_AUTH_002: Login with invalid password', async () => {
    // تنفيذ الاختبار
  });

  test('TC_AUTH_003: Login with non-existent email', async () => {
    // تنفيذ الاختبار
  });

  test('TC_AUTH_004: Logout successfully', async () => {
    // تنفيذ الاختبار
  });
});

// مجموعة اختبار ملف تعريف المستخدم
describe('User Profile API Test Suite', () => {

  test('TC_PROFILE_001: Get user profile', async () => {
    // تنفيذ الاختبار
  });

  test('TC_PROFILE_002: Update profile information', async () => {
    // تنفيذ الاختبار
  });
});

تُنشئ كتل describe() مجموعات اختبار. كل test() بداخلها هو حالة اختبار. يمكنك تشغيل جميع اختبارات المصادقة بأمر واحد أو تشغيل ملف الاختبار بأكمله.

مجموعات الاختبار المتداخلة

يمكن أن تحتوي مجموعات الاختبار على مجموعات اختبار أخرى للمشاريع المعقدة:

describe('API Test Suite', () => {

  describe('Authentication', () => {
    describe('Login', () => {
      test('with valid credentials', () => {});
      test('with invalid password', () => {});
    });

    describe('Registration', () => {
      test('with valid data', () => {});
      test('with duplicate email', () => {});
    });
  });

  describe('User Management', () => {
    test('get user list', () => {});
    test('update user role', () => {});
  });
});

ينشئ هذا تسلسلًا هرميًا: مجموعة رئيسية → مجموعات فرعية → حالات اختبار. هذا الهيكل يعكس بنية واجهة برمجة التطبيقات الخاصة بك.

الاختلافات الرئيسية بين مجموعات الاختبار وحالات الاختبار

إليك مقارنة واضحة:

الجانب حالة الاختبار مجموعة الاختبار
التعريف سيناريو اختبار واحد مجموعة من حالات الاختبار
النطاق يختبر سلوكًا محددًا واحدًا يختبر سلوكيات متعددة ذات صلة
الدقة ذرية (لا يمكن تقسيمها) مركبة (تحتوي على عناصر متعددة)
التنفيذ يشغل اختبارًا واحدًا يشغل اختبارات متعددة
الغرض التحقق من متطلب واحد تنظيم وتجميع الاختبارات
النتيجة نجاح أو فشل ملخص لجميع نتائج الاختبارات
مثال "تسجيل الدخول ببيانات اعتماد صالحة" "اختبارات وحدة المصادقة"
الكود دالة test() أو it() واحدة كتلة describe() أو suite() واحدة
قابلية إعادة الاستخدام يمكن إضافتها إلى مجموعات متعددة يمكن أن تحتوي على حالات اختبار مشتركة
الصيانة تحديث اختبار واحد تحديث اختبارات متعددة في وقت واحد

تشبيه الحاوية

فكر في الأمر بهذه الطريقة:

يمكن أن يكون لديك ملفات بدون مجلدات (حالات اختبار بدون مجموعات)، لكن المجلدات تساعد في تنظيم الملفات (تساعد المجموعات في تنظيم حالات الاختبار). يمكنك أيضًا أن يكون لديك مجلدات داخل مجلدات (مجموعات اختبار متداخلة).

اختلافات التنفيذ

عند تشغيل حالة اختبار:

# تشغيل اختبار واحد محدد
npm test -- --testNamePattern="Login with valid credentials"

عند تشغيل مجموعة اختبار:

# تشغيل جميع الاختبارات في مجموعة المصادقة
npm test -- --testPathPattern="authentication"

تتيح لك مجموعات الاختبار تشغيل مجموعات من الاختبارات ذات الصلة دون تشغيل مجموعة الاختبارات بأكملها.

كيف تعمل مجموعات الاختبار وحالات الاختبار معًا

حالات الاختبار ومجموعات الاختبار ليست مفاهيم متنافسة. بل تعمل معًا لإنشاء كود اختبار منظم وقابل للصيانة.

العلاقة

المشروع
└── مجموعات الاختبار (مجلدات)
    └── حالات الاختبار (ملفات)
        └── خطوات الاختبار (كود)

تنتمي كل حالة اختبار إلى مجموعة اختبار واحدة على الأقل. ويمكن أن تنتمي حالة الاختبار إلى مجموعات متعددة:

// smoke-tests.suite.js
describe('Smoke Tests', () => {
  test('TC_SMOKE_001: API health check', () => {});
  test('TC_SMOKE_002: Database connection', () => {});
  test('TC_AUTH_001: Login with valid credentials', () => {}); // مشترك
});

// authentication.suite.js
describe('Authentication Tests', () => {
  test('TC_AUTH_001: Login with valid credentials', () => {}); // مشترك
  test('TC_AUTH_002: Login with invalid password', () => {});
  test('TC_AUTH_003: Password reset flow', () => {});
});

تظهر حالة الاختبار TC_AUTH_001 في كل من مجموعة اختبار الدخان ومجموعة اختبار المصادقة. تتيح لك قابلية إعادة الاستخدام هذه تشغيل نفس الاختبار في سياقات مختلفة دون تكرار.

تكامل سير العمل

إليك كيف يعملان في سير عمل تطوير نموذجي:

  1. كتابة حالات الاختبار للميزات الجديدة
  2. تجميع حالات الاختبار في مجموعات اختبار منطقية
  3. تشغيل مجموعات محددة أثناء التطوير (ملاحظات سريعة)
  4. تشغيل جميع المجموعات قبل النشر (تحقق شامل)
  5. تحليل نتائج المجموعة لتحديد مناطق المشكلة

استراتيجية التنفيذ

تتطلب المواقف المختلفة استراتيجيات تنفيذ مختلفة:

# أثناء التطوير: تشغيل حالة اختبار واحدة
npm test -- --testNamePattern="TC_AUTH_001"

# قبل الالتزام (Commit): تشغيل مجموعة الاختبار ذات الصلة
npm test -- authentication.test.js

# في CI/CD: تشغيل جميع مجموعات الاختبار الحرجة
npm test -- --testPathPattern="(smoke|critical)"

# قبل الإصدار: تشغيل كل شيء
npm test

يوفر هذا النهج الطبقي الوقت. قم بتشغيل 5 اختبارات دخان في 10 ثوانٍ بدلاً من 200 اختبار في 5 دقائق أثناء التطوير. احتفظ بالمجموعة الكاملة لـ CI/CD.

مجموعة الاختبار مقابل حالة الاختبار في اختبار API

يتميز اختبار واجهات برمجة التطبيقات (API) بخصائص فريدة تؤثر على كيفية تنظيم حالات الاختبار ومجموعات الاختبار.

هيكل حالة اختبار API

عادةً ما تتحقق حالات اختبار API مما يلي:

إليك حالة اختبار API كاملة:

test('TC_USER_001: Create new user via POST /api/users', async () => {
  // الترتيب
  const newUser = {
    name: 'John Doe',
    email: 'john@example.com',
    role: 'user'
  };

  // الإجراء
  const response = await fetch('https://api.example.com/users', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'Authorization': 'Bearer test-token'
    },
    body: JSON.stringify(newUser)
  });

  const data = await response.json();

  // التحقق
  expect(response.status).toBe(201);
  expect(data.id).toBeDefined();
  expect(data.name).toBe(newUser.name);
  expect(data.email).toBe(newUser.email);
  expect(data.createdAt).toBeDefined();
});

تتحقق حالة الاختبار هذه من عملية API واحدة: إنشاء مستخدم. لا تختبر تحديث المستخدمين، أو حذفهم، أو إدراجهم.

تنظيم مجموعة اختبار API

بالنسبة لواجهات برمجة التطبيقات (APIs)، قم بتنظيم مجموعات الاختبار حسب:

1. نقطة النهاية

مجموعة الاختبار: /api/users
├── GET /api/users (قائمة المستخدمين)
├── POST /api/users (إنشاء مستخدم)
├── GET /api/users/:id (الحصول على مستخدم)
├── PUT /api/users/:id (تحديث مستخدم)
└── DELETE /api/users/:id (حذف مستخدم)

2. الميزة

مجموعة الاختبار: إدارة المستخدمين
├── تسجيل المستخدم
├── مصادقة المستخدم
├── إدارة الملف الشخصي
└── حذف الحساب

3. نوع الاختبار

مجموعة الاختبار: اختبارات الدخان (Smoke Tests)
├── التحقق من صحة API
├── اتصال قاعدة البيانات
└── نقاط النهاية الحيوية تستجيب

مجموعة الاختبار: اختبارات التكامل (Integration Tests)
├── سير عمل تسجيل المستخدم
├── سير عمل معالجة الطلبات
└── سير عمل معالجة الدفع

إدارة مجموعات الاختبار في Apidog

Apidog يجعل تنظيم مجموعات اختبار API مرئيًا وبديهيًا. بدلاً من كتابة الكود، تقوم ببناء حالات الاختبار في واجهة مستخدم رسومية وتجميعها في مجموعات اختبار باستخدام السحب والإفلات. هذا يقلل من وقت إنشاء الاختبار بنسبة 60% مقارنة بالأساليب القائمة على الكود.

إليك كيفية تعامل Apidog مع تنظيم الاختبارات:

حالات الاختبار في Apidog:

يمكنك إنشاء حالات اختبار بعدة طرق:

في علامة التبويب حالات الاختبار (Test Cases) في صفحة تفاصيل نقطة النهاية، انقر فوق + إضافة حالة (+ Add Case) لإنشاء واحدة يدويًا.

عند إضافة حالة اختبار، يمكنك الاختيار بين:

تحتوي حالة الاختبار على المعلومات التالية:

مجموعات الاختبار في Apidog:

image.png
image.png

الفوائد:

يمكنك تصدير مجموعات اختبار Apidog إلى كود إذا لزم الأمر، مما يمنحك المرونة بين الاختبار المرئي والقائم على الكود.

متى تستخدم حالات الاختبار مقابل مجموعات الاختبار

معرفة متى يتم إنشاء حالة اختبار جديدة مقابل متى يتم تجميع الحالات في مجموعات أمر بالغ الأهمية للاختبارات القابلة للصيانة.

قم بإنشاء حالة اختبار جديدة عندما:

  1. تختبر متطلبًا جديدًا: يجب أن يكون لكل متطلب حالة اختبار واحدة على الأقل.
  2. تختبر سيناريو مختلفًا: تسجيل دخول صالح مقابل تسجيل دخول غير صالح = حالتا اختبار.
  3. تختبر حالات الحافة: إدخال فارغ، أقصى إدخال، أحرف خاصة.
  4. تختبر حالات الخطأ: أخطاء 400، أخطاء 500، سيناريوهات انتهاء المهلة.
  5. تختبر بيانات مختلفة: أدوار مستخدمين مختلفة، أذونات مختلفة.

قم بإنشاء مجموعة اختبار جديدة عندما:

  1. لديك 5+ حالات اختبار ذات صلة: قم بتجميعها للتنظيم.
  2. تختبر ميزة كاملة: جميع اختبارات المصادقة معًا.
  3. تنشئ فئة اختبار: اختبارات الدخان، اختبارات الانحدار، اختبارات الأداء.
  4. تنظم حسب الأولوية: اختبارات حرجة، أولوية عالية، أولوية منخفضة.
  5. تفصل حسب البيئة: اختبارات بيئة التطوير (Staging)، اختبارات بيئة الإنتاج.

أنماط يجب تجنبها

لا تفعل هذا:

// سيء: حالة اختبار واحدة عملاقة تختبر كل شيء
test('اختبار تدفق المستخدم بالكامل', () => {
  // تسجيل مستخدم
  // تسجيل دخول مستخدم
  // تحديث الملف الشخصي
  // إنشاء منشور
  // حذف منشور
  // تسجيل الخروج
  // حذف حساب
});

افعل هذا بدلاً من ذلك:

// جيد: حالات اختبار منفصلة في مجموعات منظمة
describe('مجموعة إدارة المستخدمين', () => {
  test('TC_001: تسجيل مستخدم جديد', () => {});
  test('TC_002: تسجيل الدخول ببيانات الاعتماد', () => {});
  test('TC_003: تحديث ملف تعريف المستخدم', () => {});
});

describe('مجموعة إدارة المحتوى', () => {
  test('TC_004: إنشاء منشور جديد', () => {});
  test('TC_005: حذف منشور', () => {});
});

لا تفعل هذا:

// سيء: مجموعات متداخلة أكثر من اللازم
describe('واجهة برمجة التطبيقات (API)', () => {
  describe('الإصدار 1', () => {
    describe('المستخدمون', () => {
      describe('المصادقة', () => {
        describe('تسجيل الدخول', () => {
          describe('بيانات اعتماد صالحة', () => {
            test('مع البريد الإلكتروني', () => {});
          });
        });
      });
    });
  });
});

افعل هذا بدلاً من ذلك:

// جيد: تداخل معقول (مستويين أو ثلاثة كحد أقصى)
describe('API V1: مصادقة المستخدم', () => {
  describe('تسجيل الدخول', () => {
    test('ببريد إلكتروني وكلمة مرور صالحين', () => {});
    test('بكلمة مرور غير صالحة', () => {});
  });

  describe('التسجيل', () => {
    test('ببيانات صالحة', () => {});
  });
});

أفضل الممارسات لتنظيم حالات الاختبار ومجموعات الاختبار

اتبع هذه الاستراتيجيات المجربة للحفاظ على اختباراتك منظمة وقابلة للصيانة.

1. استخدم اصطلاحات تسمية واضحة

حالات الاختبار:

// جيد: وصفي ومحدد
test('يجب أن يرجع 200 عندما يسجل المستخدم الدخول ببيانات اعتماد صالحة', () => {});
test('يجب أن يرجع 401 عندما تكون كلمة المرور غير صحيحة', () => {});
test('يجب أن يرجع 404 عندما لا يكون المستخدم موجودًا', () => {});

// سيء: مبهم وغير واضح
test('اختبار تسجيل الدخول', () => {});
test('اختبار 1', () => {});
test('التحقق من المستخدم', () => {});

مجموعات الاختبار:

// جيد: نطاق وغرض واضحان
describe('واجهة برمجة تطبيقات المصادقة - نقطة نهاية تسجيل الدخول', () => {});
describe('إدارة ملف تعريف المستخدم', () => {});
describe('اختبارات تكامل معالجة الدفع', () => {});

// سيء: عام جدًا
describe('اختبارات', () => {});
describe('واجهة برمجة تطبيقات', () => {});
describe('أشياء', () => {});

2. حافظ على استقلالية حالات الاختبار

يجب أن تعمل كل حالة اختبار بشكل مستقل دون الاعتماد على الاختبارات الأخرى:

// سيء: تعتمد الاختبارات على بعضها البعض
let userId;

test('إنشاء مستخدم', async () => {
  const response = await createUser();
  userId = response.id; // تخزين الحالة
});

test('تحديث المستخدم', async () => {
  await updateUser(userId); // يعتمد على الاختبار السابق
});

// جيد: كل اختبار مستقل
test('إنشاء مستخدم', async () => {
  const response = await createUser();
  expect(response.status).toBe(201);
  await cleanup(response.id); // تنظيف بعد الاختبار
});

test('تحديث المستخدم', async () => {
  const user = await createUser(); // إنشاء بيانات اختبار خاصة
  const response = await updateUser(user.id);
  expect(response.status).toBe(200);
  await cleanup(user.id);
});

3. تنظيم المجموعات حسب الميزة أو الوحدة

اعكس بنية واجهة برمجة التطبيقات الخاصة بك في تنظيم الاختبار الخاص بك:

src/
├── auth/
│   ├── login.js
│   └── register.js
├── users/
│   ├── profile.js
│   └── settings.js
└── posts/
    ├── create.js
    └── delete.js

tests/
├── auth/
│   ├── login.test.js (مجموعة اختبار)
│   └── register.test.js (مجموعة اختبار)
├── users/
│   ├── profile.test.js (مجموعة اختبار)
│   └── settings.test.js (مجموعة اختبار)
└── posts/
    ├── create.test.js (مجموعة اختبار)
    └── delete.test.js (مجموعة اختبار)

4. استخدام خطافات الإعداد والإنهاء (Setup and Teardown Hooks)

قلل التكرار باستخدام خطافات ما قبل/بعد:

describe('مجموعة اختبار واجهة برمجة تطبيقات المستخدم', () => {
  let authToken;
  let testUser;

  // يتم التشغيل مرة واحدة قبل جميع الاختبارات في هذه المجموعة
  beforeAll(async () => {
    authToken = await getAuthToken();
  });

  // يتم التشغيل قبل كل حالة اختبار
  beforeEach(async () => {
    testUser = await createTestUser();
  });

  // يتم التشغيل بعد كل حالة اختبار
  afterEach(async () => {
    await deleteTestUser(testUser.id);
  });

  // يتم التشغيل مرة واحدة بعد جميع الاختبارات في هذه المجموعة
  afterAll(async () => {
    await revokeAuthToken(authToken);
  });

  test('TC_001: الحصول على ملف تعريف المستخدم', async () => {
    // testUser و authToken متاحان
  });

  test('TC_002: تحديث ملف تعريف المستخدم', async () => {
    // testUser و authToken متاحان
  });
});

5. وسم الاختبارات لتنفيذ مرن

استخدم الوسوم أو الفئات لتشغيل مجموعات اختبار محددة:

describe('مجموعة المصادقة', () => {
  test('[smoke] فحص صحة API', () => {});
  test('[critical] تسجيل الدخول ببيانات اعتماد صالحة', () => {});
  test('[regression] تسجيل الدخول برمز منتهي الصلاحية', () => {});
  test('[edge-case] تسجيل الدخول بأحرف خاصة في كلمة المرور', () => {});
});

// تشغيل اختبارات الدخان فقط
// npm test -- --testNamePattern="smoke"

// تشغيل الاختبارات الحرجة
// npm test -- --testNamePattern="critical"

6. الحفاظ على تسلسل هرمي لمجموعات الاختبار

أنشئ تسلسلاً هرميًا واضحًا للمشاريع الكبيرة:

المستوى 1: نوع الاختبار (Smoke, Integration, E2E)
  └── المستوى 2: وحدة الميزة (Auth, Users, Orders)
      └── المستوى 3: وظيفة محددة (Login, Register)
          └── المستوى 4: حالات الاختبار (Valid, Invalid, Edge Cases)

مثال:

describe('[تكامل] إدارة المستخدمين', () => {
  describe('المصادقة', () => {
    describe('تسجيل الدخول', () => {
      test('ببيانات اعتماد صالحة', () => {});
      test('بكلمة مرور غير صالحة', () => {});
      test('ببريد إلكتروني غير موجود', () => {});
    });
  });
});

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

1. إنشاء حالات اختبار واسعة النطاق بشكل مفرط

المشكلة:

test('اختبار وظائف المستخدم', () => {
  // يختبر التسجيل، تسجيل الدخول، تحديث الملف الشخصي، والحذف
  // إذا فشل هذا، فما هو الجزء الذي تعطل؟
});

الحل:

test('يجب تسجيل مستخدم جديد', () => {});
test('يجب تسجيل دخول المستخدم المسجل', () => {});
test('يجب تحديث ملف تعريف المستخدم', () => {});
test('يجب حذف حساب المستخدم', () => {});

2. عدم تجميع حالات الاختبار ذات الصلة

المشكلة:

test('اختبار تسجيل الدخول 1', () => {});
test('اختبار الملف الشخصي 1', () => {});
test('اختبار تسجيل الدخول 2', () => {});
test('اختبار الطلب 1', () => {});
test('اختبار الملف الشخصي 2', () => {});

الحل:

describe('اختبارات تسجيل الدخول', () => {
  test('اختبار 1', () => {});
  test('اختبار 2', () => {});
});

describe('اختبارات الملف الشخصي', () => {
  test('اختبار 1', () => {});
  test('اختبار 2', () => {});
});

3. إنشاء عدد كبير جدًا من المجموعات المتداخلة

المشكلة:

describe('واجهة برمجة التطبيقات (API)', () => {
  describe('الإصدار 1', () => {
    describe('المستخدمون', () => {
      describe('الملف الشخصي', () => {
        describe('التحديث', () => {
          test('ببيانات صالحة', () => {});
        });
      });
    });
  });
});

الحل:

describe('API V1: ملف تعريف المستخدم', () => {
  test('يجب تحديث الملف الشخصي ببيانات صالحة', () => {});
});

4. تجاهل ترتيب تنفيذ الاختبار

المشكلة:

describe('تدفق المستخدم', () => {
  test('حذف مستخدم', () => {}); // يتم تشغيله أولاً
  test('إنشاء مستخدم', () => {}); // يتم تشغيله ثانيًا
  test('تحديث مستخدم', () => {}); // يتم تشغيله ثالثًا
});

الحل:

describe('تدفق المستخدم', () => {
  test('1. إنشاء مستخدم', () => {});
  test('2. تحديث مستخدم', () => {});
  test('3. حذف مستخدم', () => {});
});

// أو استخدم beforeEach لضمان الإعداد الصحيح

5. عدم استخدام أسماء وصفية

المشكلة:

describe('المجموعة 1', () => {
  test('اختبار 1', () => {});
  test('اختبار 2', () => {});
});

الحل:

describe('اختبارات واجهة برمجة تطبيقات المصادقة', () => {
  test('يجب إرجاع رمز JWT عند تسجيل الدخول بنجاح', () => {});
  test('يجب إرجاع 401 عند بيانات الاعتماد غير صالحة', () => {});
});

أمثلة واقعية

مثال 1: تنظيم اختبارات API للتجارة الإلكترونية

// مجموعة اختبار الدخان - يتم تشغيلها عند كل التزام (commit)
describe('[Smoke] نقاط نهاية API الحرجة', () => {
  test('TC_SMOKE_001: فحص صحة API يرجع 200', async () => {
    const response = await fetch('https://api.shop.com/health');
    expect(response.status).toBe(200);
  });

  test('TC_SMOKE_002: اتصال قاعدة البيانات نشط', async () => {
    const response = await fetch('https://api.shop.com/db-status');
    expect(response.json()).toHaveProperty('connected', true);
  });
});

// مجموعة اختبار المصادقة
describe('[تكامل] وحدة المصادقة', () => {
  describe('تسجيل المستخدم', () => {
    test('TC_AUTH_001: التسجيل ببريد إلكتروني وكلمة مرور صالحين', async () => {
      // تنفيذ الاختبار
    });

    test('TC_AUTH_002: رفض التسجيل ببريد إلكتروني مكرر', async () => {
      // تنفيذ الاختبار
    });

    test('TC_AUTH_003: رفض كلمات المرور الضعيفة', async () => {
      // تنفيذ الاختبار
    });
  });

  describe('تسجيل دخول المستخدم', () => {
    test('TC_AUTH_004: تسجيل الدخول ببيانات اعتماد صالحة', async () => {
      // تنفيذ الاختبار
    });

    test('TC_AUTH_005: رفض كلمة مرور غير صالحة', async () => {
      // تنفيذ الاختبار
    });
  });
});

// مجموعة اختبار إدارة المنتجات
describe('[تكامل] إدارة المنتجات', () => {
  test('TC_PROD_001: الحصول على قائمة المنتجات', async () => {
    // تنفيذ الاختبار
  });

  test('TC_PROD_002: الحصول على المنتج حسب المعرف', async () => {
    // تنفيذ الاختبار
  });

  test('TC_PROD_003: البحث عن المنتجات بالاسم', async () => {
    // تنفيذ الاختبار
  });

  test('TC_PROD_004: تصفية المنتجات حسب الفئة', async () => {
    // تنفيذ الاختبار
  });
});

// مجموعة اختبار معالجة الطلبات
describe('[تكامل] معالجة الطلبات', () => {
  test('TC_ORDER_001: إنشاء طلب بعناصر صالحة', async () => {
    // تنفيذ الاختبار
  });

  test('TC_ORDER_002: حساب إجمالي الطلب الصحيح', async () => {
    // تنفيذ الاختبار
  });

  test('TC_ORDER_003: تطبيق رمز الخصم', async () => {
    // تنفيذ الاختبار
  });

  test('TC_ORDER_004: معالجة الدفع', async () => {
    // تنفيذ الاختبار
  });
});

مثال 2: هيكل مجموعة اختبار Apidog

في Apidog، يمكنك تنظيم الاختبارات بصريًا:

📁 اختبارات API التجارة الإلكترونية
  📁 اختبارات الدخان (Smoke Tests) (مجموعة)
    ✓ فحص صحة API (حالة اختبار)
    ✓ حالة قاعدة البيانات (حالة اختبار)

  📁 المصادقة (Authentication) (مجموعة)
    📁 التسجيل (Registration) (مجموعة فرعية)
      ✓ تسجيل صالح (حالة اختبار)
      ✓ بريد إلكتروني مكرر (حالة اختبار)
      ✓ كلمة مرور ضعيفة (حالة اختبار)
    📁 تسجيل الدخول (Login) (مجموعة فرعية)
      ✓ تسجيل دخول صالح (حالة اختبار)
      ✓ كلمة مرور غير صالحة (حالة اختبار)

  📁 المنتجات (Products) (مجموعة)
    ✓ قائمة المنتجات (حالة اختبار)
    ✓ الحصول على تفاصيل المنتج (حالة اختبار)
    ✓ البحث عن المنتجات (حالة اختبار)

  📁 الطلبات (Orders) (مجموعة)
    ✓ إنشاء طلب (حالة اختبار)
    ✓ حساب الإجمالي (حالة اختبار)
    ✓ تطبيق الخصم (حالة اختبار)

تتضمن كل حالة اختبار في Apidog ما يلي:

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

الخلاصة

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

النقاط الرئيسية:

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

هل أنت مستعد لتنظيم اختبارات واجهة برمجة التطبيقات الخاصة بك؟ جرب إدارة مجموعات الاختبار المرئية في Apidog - أنشئ، نظم، وشغل حالات الاختبار دون كتابة كود. قلل وقت إعداد الاختبار بنسبة 60% واحصل على أول مجموعة اختبار تعمل في أقل من 5 دقائق.

button

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

ما هو الفرق الرئيسي بين حالة الاختبار ومجموعة الاختبار؟

حالة الاختبار هي اختبار واحد يتحقق من سلوك أو متطلب معين. مجموعة الاختبار هي مجموعة من حالات الاختبار المتعددة ذات الصلة المجمعة معًا للتنفيذ المنظم. فكر في حالات الاختبار كأسئلة فردية ومجموعات الاختبار كالاختبار الذي يحتوي على هذه الأسئلة.

هل يمكن أن تنتمي حالة الاختبار إلى مجموعات اختبار متعددة؟

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

كم عدد حالات الاختبار التي يجب أن تكون في مجموعة الاختبار؟

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

هل يجب أن أكتب حالات الاختبار أم مجموعات الاختبار أولاً؟

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

ما الفرق بين مجموعة الاختبار وسيناريو الاختبار؟

سيناريو الاختبار هو وصف عالي المستوى لما يجب اختباره (على سبيل المثال، "تدفق تسجيل دخول المستخدم"). مجموعة الاختبار هي المجموعة الفعلية من حالات الاختبار القابلة للتنفيذ. قد يصبح سيناريو الاختبار مجموعة اختبار تحتوي على حالات اختبار متعددة تتحقق من جوانب مختلفة من هذا السيناريو.

كيف أنظم مجموعات الاختبار لواجهات برمجة التطبيقات (APIs) الكبيرة؟

استخدم هيكلًا هرميًا: نظم حسب الميزة أو الوحدة في المستوى الأعلى، ثم حسب الوظيفة، ثم حسب نوع الاختبار. على سبيل المثال: "إدارة المستخدمين" (وحدة) → "المصادقة" (وظيفة) → "اختبارات تسجيل الدخول" (مجموعة اختبار) → حالات الاختبار الفردية. حافظ على التداخل بحد أقصى 2-3 مستويات.

هل يمكن أن تحتوي مجموعات الاختبار على مجموعات اختبار أخرى؟

نعم. يمكن تداخل مجموعات الاختبار لإنشاء تسلسلات هرمية. على سبيل المثال، قد تحتوي مجموعة "اختبارات API" على مجموعات فرعية "اختبارات المصادقة" و"اختبارات إدارة المستخدمين". ومع ذلك، تجنب التداخل المفرط (أكثر من 3 مستويات) لأنه يجعل الاختبارات أكثر صعوبة في التنقل والصيانة.

ما هي الأدوات التي تساعد في إدارة حالات الاختبار ومجموعات الاختبار؟

تشمل الأدوات الشائعة Jest و Mocha لـ JavaScript، Pytest لـ Python، JUnit لـ Java، و Postman لاختبار API. تقدم Apidog إدارة مجموعات الاختبار المرئية بدون ترميز، مما يسهل تنظيم وتنفيذ حالات اختبار API من خلال واجهة المستخدم الرسومية.

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

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