استخدام الـ Matchers: أدوات التحقق في اختباراتك

الكاتب: قالب اقرأتاريخ النشر: آخر تحديث: وقت القراءة:
للقراءة
عدد الكلمات:
كلمة
عدد التعليقات: 0 تعليق
نبذة عن المقال: تعلم كيفية استخدام Matchers في Vitest لكتابة تأكيدات دقيقة وقوية في اختبارات الوحدات. استكشف أشهر الـ Matchers مثل toBe وtoEqual وtoMatch والمزيد.

أهلاً بك مجدداً! 

في الدرس السابق، كتبنا أول اختبار لنا. لاحظنا أننا استخدمنا دالة expect متبوعة بـ .toBe(). هذا الجزء الثاني، .toBe()، هو ما نسميه Matcher. في هذا الدرس، سنتعمق في عالم الـ Matchers، فهي بمثابة قلب وروح كل تأكيد (Assertion) نكتبه.

تخيل أنك محقق في مسرح جريمة. لديك دليل (القيمة الفعلية التي تنتجها دالتك)، وتريد التحقق من صحة فرضية معينة (القيمة المتوقعة). الـ Matchers هي الأدوات المتخصصة التي تستخدمها للمقارنة، مثل العدسة المكبرة، أو أدوات فحص البصمات، أو جهاز تحليل المواد. كل أداة مصممة لغرض معين، واختيار الأداة الصحيحة يجعل استنتاجك دقيقاً وموثوقاً.

استخدام الـ Matchers: أدوات التحقق في اختباراتك

ما هي الـ Matchers؟

ببساطة، الـ Matchers هي دوال (methods) توفرها مكتبة الاختبار (مثل Vitest) وتُستخدم للتحقق من قيم مختلفة بطرق مختلفة. تأتي دائمًا بعد expect(value) لتُكمل جملة التأكيد وتوضح كيف يجب أن تكون القيمة.

الصيغة العامة تبدو هكذا:

JavaScript
// General syntax of an assertion
expect(actualValue).matcher(expectedValue);

بدون الـ Matchers، ستكون دالة expect مجرد بداية جملة بدون خبر. الـ Matchers هي التي تعطيها المعنى والقوة.

أشهر أنواع الـ Matchers في Vitest

توفر Vitest (بالتوافق مع Jest) مجموعة غنية من الـ Matchers لتغطية معظم سيناريوهات الاختبار. دعنا نستكشف الأكثر شيوعًا واستخدامًا.

1. التحقق من المساواة (Equality)

هذا هو النوع الأكثر أساسية من التحقق.

  • toBe(): يستخدم للتحقق من المساواة الصارمة (Strict Equality)، أي ما يعادل === في JavaScript. هذا يعني أنه يتحقق من القيمة والنوع معًا. إنه مثالي للأنواع الأولية (Primitives) مثل الأرقام والنصوص والقيم المنطقية.

  • JavaScript
    // a function that returns a greeting message
    function getGreeting(name) {
      return `Hello, ${name}`;
    }
    
    test('getGreeting should return the correct message', () => {
      expect(getGreeting('Alice')).toBe('Hello, Alice'); // works for strings
      expect(2 + 2).toBe(4); // works for numbers
    });
  • toEqual(): يستخدم للتحقق من "القيمة" لكائن أو مصفوفة. على عكس toBe، فإنه لا يتحقق من تطابق مرجع الكائن في الذاكرة، بل يقوم بالمرور على كل خاصية (property) داخل الكائن أو كل عنصر في المصفوفة ويقارن قيمها بشكل متكرر (recursively).

  • JavaScript
    // a function that creates a user object
    function createUser(name, age) {
      return { name, age };
    }
    
    test('createUser should return a correct user object', () => {
      const user = createUser('Bob', 30);
      // Using .toBe will FAIL because they are two different objects in memory.
      // expect(user).toBe({ name: 'Bob', age: 30 }); // This would fail!
    
      // Using .toEqual will PASS because it checks the properties inside the object.
      expect(user).toEqual({ name: 'Bob', age: 30 });
    });

ملاحظة هامة

القاعدة بسيطة. استخدم toBe للأنواع الأولية (string, number, boolean, null, undefined). استخدم toEqual لكل شيء آخر تقريبًا، خاصة الكائنات (Objects) والمصفوفات (Arrays).

2. التحقق من الصوابية (Truthiness)

في JavaScript، هناك قيم تعتبر false (مثل 0, '', null, undefined, NaN) وقيم أخرى تعتبر true. أحيانًا لا نهتم بالقيمة الدقيقة، بل نهتم فقط بما إذا كانت "صحيحة" أم "خاطئة" في سياق منطقي.

  • toBeNull(): يتحقق من أن القيمة هي null بالضبط.
  • toBeUndefined(): يتحقق من أن القيمة هي undefined.
  • toBeDefined(): عكس toBeUndefined، يتحقق من أن القيمة ليست undefined.
  • toBeTruthy(): يتحقق من أن القيمة تُعتبر true في سياق if statement.
  • toBeFalsy(): يتحقق من أن القيمة تُعتبر false في سياق if statement.
JavaScript
    test('truthiness matchers', () => {
      const emptyString = '';
      const zero = 0;
      const user = null;
      let admin; // undefined by default

      expect(user).toBeNull();
      expect(admin).toBeUndefined();
      expect(emptyString).toBeDefined();

      expect(emptyString).toBeFalsy();
      expect(zero).toBeFalsy();
      expect(user).toBeFalsy();

      expect('hello').toBeTruthy();
      expect(123).toBeTruthy();
    });

3. التحقق من الأرقام (Numbers)

عند التعامل مع الأرقام، قد تحتاج إلى مقارنات أكثر من مجرد المساواة.

  • toBeGreaterThan(): أكبر من (>).
  • toBeGreaterThanOrEqual(): أكبر من أو يساوي (>=).
  • toBeLessThan(): أصغر من (<).
  • toBeLessThanOrEqual(): أصغر من أو يساوي (<=).
  • toBeCloseTo(): يُستخدم خصيصًا للأعداد العشرية (floating-point numbers) لتجنب أخطاء التقريب الدقيقة.
JavaScript
    function calculateDiscount(price, percentage) {
        if (percentage < 0 || percentage > 100) {
            throw new Error('Invalid percentage');
        }
        return price * (percentage / 100);
    }

    test('numeric matchers for discount calculation', () => {
      const discount = calculateDiscount(150, 10); // 15
      expect(discount).toBeGreaterThan(10);
      expect(discount).toBeLessThanOrEqual(15);
    });

    test('handling floating point numbers', () => {
        const result = 0.1 + 0.2;
        // expect(result).toBe(0.3); // This will fail because of floating point inaccuracies (result is 0.30000000000000004)
        expect(result).toBeCloseTo(0.3); // This will pass!
    });

4. التحقق من النصوص (Strings)

  • toMatch(): يتحقق مما إذا كان النص يتطابق مع تعبير نمطي (Regular Expression).
JavaScript
    function formatErrorCode(code) {
      return `ERR-${code}-SERVER`;
    }

    test('formatErrorCode should match the specific format', () => {
      const errorCode = formatErrorCode(404);
      expect(errorCode).toMatch(/ERR-\d+-SERVER/);
      expect(errorCode).toMatch('404'); // It can also check for a substring
    });

5. التحقق من المصفوفات والكائنات القابلة للتكرار (Arrays & Iterables)

  • toContain(): يتحقق مما إذا كانت المصفوفة تحتوي على عنصر معين.
  • toHaveLength(): يتحقق من طول المصفوفة.
JavaScript
    function getSupportedFeatures() {
      return ['login', 'logout', 'profile', 'dashboard'];
    }

    test('supported features array', () => {
      const features = getSupportedFeatures();
      expect(features).toHaveLength(4);
      expect(features).toContain('profile');
    });

6. التحقق من الاستثناءات (Exceptions)

أحيانًا، يكون السلوك الصحيح للدالة هو إلقاء خطأ (throw an error). يمكنك اختبار هذا السلوك.

  • toThrow(): يتحقق من أن دالة ما تُلقي خطأ عند استدعائها.

نصيحة احترافية

يجب أن تضع الاستدعاء الذي تتوقع أن يُلقي خطأ داخل دالة () =>، وإلا فإن الخطأ سيوقف تنفيذ الاختبار ولن يتمكن الـ Matcher من التقاطه.

JavaScript
    function validateUsername(username) {
      if (username.length < 3) {
        throw new Error('Username must be at least 3 characters long.');
      }
      return true;
    }

    test('validateUsername should throw an error for short usernames', () => {
      // The function that throws an exception needs to be invoked within a wrapping function
      // otherwise the assertion will fail and the test will stop.
      expect(() => validateUsername('ab')).toThrow();
      expect(() => validateUsername('ab')).toThrow('Username must be at least 3 characters long.');
    });

قوة النفي: المعدِّل .not

ماذا لو أردت التأكد من أن شيئًا ليس صحيحًا؟ يمكنك استخدام المعدِّل (modifier) .not قبل أي Matcher لعكس معناه.

JavaScript
    test('using .not modifier', () => {
        const a = 5;
        expect(a).not.toBe(10);

        const features = ['login', 'logout'];
        expect(features).not.toContain('admin');
    });

.not هو أداة قوية للغاية تضاعف فائدة كل Matcher لديك.

الخلاصة

لقد قمنا بجولة سريعة ومكثفة على أهم الـ Matchers التي ستحتاجها يوميًا. الـ Matchers هي أساس كتابة التأكيدات الواضحة والدقيقة التي تعبر عن نيتك بوضوح.

تذكر النقاط الرئيسية:

  • الـ Matchers تكمل expect للتحقق من القيم.
  • استخدم toBe للأنواع الأولية و toEqual للكائنات والمصفوفات.
  • اختر الـ Matcher الأكثر تعبيرًا عن الحالة التي تختبرها (مثلاً، استخدم toBeNull() بدلاً من toBe(null) لأنها أوضح).
  • استخدم .not لعكس منطق أي Matcher.

في الدرس التالي، سنتحدث عن كيفية كتابة تأكيدات جيدة، مما يجمع بين ما تعلمناه عن بنية الاختبار والـ Matchers.

قد تُعجبك هذه المشاركات

إرسال تعليق

ليست هناك تعليقات

7627059358572141466

العلامات المرجعية

قائمة العلامات المرجعية فارغة ... قم بإضافة مقالاتك الآن

    البحث