مرحبًا بك في تمرين جديد! بعد أن تعلمنا عن أهمية كتابة تأكيدات (Assertions) جيدة وكيفية استخدام الـ Matchers بفعالية، حان الوقت لتطبيق هذه المهارات عمليًا. في هذا التمرين، سنقوم بكتابة مجموعة من الاختبارات لدالة بسيطة تُرجع قائمة بكوبونات الخصم. هذا سيساعدنا على ترسيخ فهمنا لكيفية اختبار المصفوفات والكائنات.

الهدف من التمرين
الهدف هو التأكد من أنك تستطيع:
- اختيار الـ
Matcherالمناسب لكل حالة اختبار. - اختبار بنية البيانات المُرجعة (Array of Objects).
- التحقق من القيم والخصائص داخل الكائنات الموجودة في المصفوفة.
- كتابة اختبارات شاملة تغطي جوانب متعددة من الدالة.
وصف الدالة getCoupons
الدالة التي سنختبرها بسيطة جدًا. كل ما تفعله هو إرجاع مصفوفة ثابتة (hard-coded) من كائنات الكوبونات. كل كائن يمثل كوبونًا ويحتوي على خاصيتين:
code: سلسلة نصية (string) تمثل رمز الكوبون.discount: رقم (number) يمثل نسبة الخصم (على سبيل المثال،0.1لخصم 10%).
ملفات البداية
للبدء، سنحتاج إلى ملفين: ملف الدالة نفسها، وملف الاختبار الخاص بها.
1. ملف الدالة (coupons.js)
قم بإنشاء ملف باسم coupons.js وأضف الكود التالي بداخله. هذه هي الدالة التي سنكتب لها الاختبارات.
// src/coupons.js
export const getCoupons = () => {
return [
{ code: 'SAVE10', discount: 0.1 },
{ code: 'SALE20', discount: 0.2 },
{ code: 'NEWUSER', discount: 0.15 },
];
};2. ملف الاختبار (coupons.test.js)
الآن، قم بإنشاء ملف الاختبار coupons.test.js بجانب الملف السابق. هذا هو المكان الذي ستكتب فيه اختباراتك.
// tests/coupons.test.js
import { getCoupons } from '../src/coupons';
describe('getCoupons', () => {
// Your tests will go here
});المتطلبات (Requirements)
مهمتك هي كتابة مجموعة من الاختبارات داخل كتلة describe للتحقق من السلوك الصحيح لدالة getCoupons. عليك كتابة الاختبارات التالية:
- الاختبار الأول: يجب أن تتحقق من أن الدالة تُرجع مصفوفة (array).
- الاختبار الثاني: يجب أن تتحقق من أن المصفوفة المُرجعة ليست فارغة وأنها تحتوي على 3 كوبونات بالضبط.
- الاختبار الثالث: يجب أن تتحقق من أن المصفوفة تحتوي على كوبون خصم محدد. على سبيل المثال، تأكد من وجود الكوبون
{ code: 'SALE20', discount: 0.2 }. - الاختبار الرابع: يجب أن تتحقق من أن كل كوبون في المصفوفة له بنية صحيحة، أي أنه كائن يحتوي على خاصيتي
code(من نوع string) وdiscount(من نوع number). - الاختبار الخامس: يجب أن تتحقق من أن قيمة الخصم
discountلكل كوبون هي قيمة موجبة.
خذ وقتك في محاولة حل التمرين بنفسك قبل النظر إلى الحل المقترح. هذه هي أفضل طريقة للتعلم.
الحل المقترح
هل أنت مستعد لمقارنة حلك؟ إليك الحل الكامل مع شرح لكل اختبار.
// tests/coupons.test.js
import { getCoupons } from '../src/coupons';
describe('getCoupons', () => {
it('should return an array of coupons', () => {
const coupons = getCoupons();
// Test 1: Check if the result is an array.
// Using `toBeInstanceOf` is a robust way to check for type.
expect(coupons).toBeInstanceOf(Array);
});
it('should return an array with 3 coupons', () => {
const coupons = getCoupons();
// Test 2: Check for a specific array length.
// `toHaveLength` is the most idiomatic way to check the size of an array.
expect(coupons).toHaveLength(3);
});
it('should include a specific coupon', () => {
const coupons = getCoupons();
// Test 3: Check for the presence of a specific object.
// `toContainEqual` is used because it checks for deep equality (object values),
// whereas `toContain` checks for referential equality (same object instance).
expect(coupons).toContainEqual({ code: 'SALE20', discount: 0.2 });
});
it('should ensure every coupon has the correct structure and types', () => {
const coupons = getCoupons();
// Test 4: Verify the structure and types of each object in the array.
// We loop through each coupon and make assertions on its properties.
coupons.forEach(coupon => {
expect(coupon).toHaveProperty('code');
expect(typeof coupon.code).toBe('string');
expect(coupon).toHaveProperty('discount');
expect(typeof coupon.discount).toBe('number');
});
});
it('should ensure all discount values are positive', () => {
const coupons = getCoupons();
// Test 5: Verify a specific constraint on a property value.
// This ensures our data adheres to business logic (discounts can't be negative).
coupons.forEach(coupon => {
expect(coupon.discount).toBeGreaterThan(0);
});
});
});تحليل الحل
- الاختبار الأول: استخدمنا
toBeInstanceOf(Array)للتحقق من أن الناتج هو مصفوفة. هذه طريقة موثوقة للتحقق من النوع. - الاختبار الثاني: استخدمنا
toHaveLength(3)وهو الـMatcherالمخصص للتحقق من طول المصفوفات أو السلاسل النصية. إنه أكثر وضوحًا منexpect(coupons.length).toBe(3). - الاختبار الثالث: هنا يكمن الفارق الدقيق. عند التحقق من وجود كائن في مصفوفة، نستخدم
toContainEqual. لو استخدمناtoContainلفشل الاختبار، لأنtoContainيتحقق مما إذا كان نفس الكائن موجودًا في الذاكرة، بينماtoContainEqualيتحقق من وجود كائن له نفس القيم (deep equality). - الاختبار الرابع والخامس: قمنا بالمرور على كل عنصر في المصفوفة باستخدام
forEachللتحقق من البنية والقيم الداخلية لكل كائن. هذا يضمن لنا أن جميع البيانات في المصفوفة متسقة وصحيحة. لقد تحققنا من وجود الخصائص (toHaveProperty)، ونوعها (typeof), وقيمتها (toBeGreaterThan).
خلاصة
لقد قمت للتو بكتابة مجموعة اختبارات شاملة لدالة بسيطة. هذا التمرين يوضح كيف أن اختبار دالة واحدة قد يتطلب عدة حالات اختبار (test cases) للتأكد من كل جانب من جوانب سلوكها، بدءًا من نوع القيمة المُرجعة، مرورًا بحجمها ومحتواها، وانتهاءً ببنية وقيم العناصر داخلها. لقد تدربت على استخدام toBeInstanceOf, toHaveLength, toContainEqual, ودمج الحلقات مع التأكيدات للتحقق من كل عنصر في مصفوفة.

إرسال تعليق