مقدمة إلى Jest
Jest هو إطار عمل اختبار JavaScript رائع تم تطويره بواسطة Facebook، مصمم للعمل بسلاسة مع المشاريع التي تستخدم React وVue وAngular وNode.js والمزيد. يوفر تجربة اختبار بدون تكوين مع تغطية كود مدمجة وقدرات محاكاة وواجهة برمجة تطبيقات بديهية تجعل الاختبار ممتعاً بدلاً من مملاً.
على عكس أطر الاختبار القديمة التي تتطلب إعداداً واسع النطاق ومكتبات متعددة، يأتي Jest بكل ما تحتاجه جاهزاً: مشغل الاختبار ومكتبة التأكيد وأدوات المحاكاة وتقارير التغطية. إنه سريع ومعزول ويوفر رسائل خطأ ممتازة تساعدك على تحديد المشكلات بسرعة.
لماذا تختار Jest؟
أصبح Jest المعيار الفعلي لاختبار JavaScript لأنه يجمع بين البساطة والقوة. سواء كنت تختبر دالة مساعدة بسيطة أو تطبيق React معقد، يوفر Jest الأدوات التي تحتاجها دون تكوين معقد.
التثبيت والإعداد
تثبيت Jest
تثبيت Jest بسيط باستخدام npm أو yarn. لمشروع Node.js:
# باستخدام npm
npm install --save-dev jest
# باستخدام yarn
yarn add --dev jest
بالنسبة لمشاريع React التي تم إنشاؤها باستخدام Create React App، يأتي Jest مثبتاً ومكوناً مسبقاً. للمشاريع الأخرى:
npm install --save-dev jest babel-jest @babel/core @babel/preset-env @babel/preset-react
التكوين الأساسي
أضف سكريبت الاختبار إلى package.json:
{
"scripts": {
"test": "jest",
"test:watch": "jest --watch",
"test:coverage": "jest --coverage"
}
}
لمشاريع TypeScript، قم بتثبيت التبعيات الإضافية:
npm install --save-dev @types/jest ts-jest
أنشئ ملف jest.config.js للتكوين المخصص:
module.exports = {
testEnvironment: 'node',
coverageDirectory: 'coverage',
collectCoverageFrom: [
'src/**/*.js',
'!src/**/*.test.js'
],
testMatch: [
'**/__tests__/**/*.js',
'**/?(*.)+(spec|test).js'
]
};
خيارات التكوين:
- testEnvironment: استخدم 'node' للخلفية، 'jsdom' للواجهة
- coverageDirectory: مكان إخراج تقارير التغطية
- collectCoverageFrom: الملفات التي سيتم تضمينها في التغطية
- testMatch: الأنماط لتحديد ملفات الاختبار
كتابة أول اختبار
اختبار دالة بسيطة
لننشئ دالة بسيطة ونختبرها. أولاً، أنشئ sum.js:
function sum(a, b) {
return a + b;
}
module.exports = sum;
الآن أنشئ sum.test.js:
const sum = require('./sum');
test('adds 1 + 2 to equal 3', () => {
expect(sum(1, 2)).toBe(3);
});
test('adds -1 + 1 to equal 0', () => {
expect(sum(-1, 1)).toBe(0);
});
شغل الاختبارات باستخدام:
npm test
تسمية ملفات الاختبار:
يجد Jest تلقائياً ملفات الاختبار بهذه الأنماط: *.test.js أو *.spec.js أو الملفات في مجلدات __tests__. استخدم تسمية متسقة في مشروعك.
بنية الاختبار: describe وit وtest
دالة test()
دالة test() (الاسم المستعار it()) هي الوحدة الأساسية للبناء. تأخذ وصفاً ودالة رد نداء:
test('وصف ما تختبره', () => {
// كود الاختبار هنا
expect(actualValue).toBe(expectedValue);
});
كتلة describe()
describe() تجمع الاختبارات المرتبطة معاً، مما ينشئ مجموعة اختبار:
describe('العمليات الحسابية', () => {
test('الجمع يعمل بشكل صحيح', () => {
expect(2 + 2).toBe(4);
});
test('الطرح يعمل بشكل صحيح', () => {
expect(5 - 3).toBe(2);
});
test('الضرب يعمل بشكل صحيح', () => {
expect(3 * 4).toBe(12);
});
});
كتل describe متداخلة
يمكنك تداخل كتل describe لتنظيم أفضل:
describe('الآلة الحاسبة', () => {
describe('الجمع', () => {
test('جمع الأرقام الموجبة', () => {
expect(5 + 3).toBe(8);
});
test('جمع الأرقام السالبة', () => {
expect(-5 + -3).toBe(-8);
});
});
describe('الطرح', () => {
test('طرح الأرقام الموجبة', () => {
expect(5 - 3).toBe(2);
});
test('طرح الأرقام السالبة', () => {
expect(-5 - -3).toBe(-2);
});
});
});
المطابقات الشائعة
مطابقات المساواة
يوفر Jest مطابقات متنوعة لاحتياجات المقارنة المختلفة:
// المساواة الدقيقة (للأنواع البدائية)
test('toBe يطابق القيم الدقيقة', () => {
expect(2 + 2).toBe(4);
expect('hello').toBe('hello');
});
// المساواة العميقة (للكائنات والمصفوفات)
test('toEqual يطابق بنية الكائن', () => {
const data = { name: 'John', age: 30 };
expect(data).toEqual({ name: 'John', age: 30 });
});
// ليس مساوياً
test('مطابقات not', () => {
expect(2 + 2).not.toBe(5);
expect('hello').not.toBe('world');
});
toBe مقابل toEqual:
استخدم toBe() للقيم البدائية (أرقام، نصوص، قيم منطقية) وtoEqual() للكائنات والمصفوفات. استخدام toBe() مع الكائنات يقارن المراجع وليس القيم!
مطابقات الصحة
test('مطابقات الصحة', () => {
expect(null).toBeNull();
expect(undefined).toBeUndefined();
expect(true).toBeTruthy();
expect(false).toBeFalsy();
expect(0).toBeFalsy();
expect('').toBeFalsy();
expect('hello').toBeTruthy();
});
مطابقات الأرقام
test('مطابقات الأرقام', () => {
const value = 2 + 2;
expect(value).toBeGreaterThan(3);
expect(value).toBeGreaterThanOrEqual(4);
expect(value).toBeLessThan(5);
expect(value).toBeLessThanOrEqual(4);
// مساواة الفاصلة العائمة
expect(0.1 + 0.2).toBeCloseTo(0.3);
});
مطابقات النصوص
test('مطابقات النصوص', () => {
expect('team').not.toMatch(/I/);
expect('Christoph').toMatch(/stop/);
expect('Hello World').toContain('World');
});
مطابقات المصفوفات والعناصر القابلة للتكرار
test('مطابقات المصفوفات', () => {
const shoppingList = ['apples', 'bananas', 'oranges'];
expect(shoppingList).toContain('bananas');
expect(shoppingList).toHaveLength(3);
expect(new Set(shoppingList)).toContain('apples');
});
مشغل الاختبار
تشغيل الاختبارات
يوفر Jest عدة طرق لتشغيل اختباراتك:
# تشغيل جميع الاختبارات
npm test
# تشغيل الاختبارات في وضع المراقبة (يعيد التشغيل عند تغيير الملفات)
npm test -- --watch
# تشغيل الاختبارات مع التغطية
npm test -- --coverage
# تشغيل ملف اختبار محدد
npm test sum.test.js
# تشغيل الاختبارات المطابقة لنمط
npm test -- --testNamePattern='addition'
وضع المراقبة
وضع المراقبة مفيد للغاية أثناء التطوير. يوفر خيارات تفاعلية:
Watch Usage
› Press f to run only failed tests.
› Press o to only run tests related to changed files.
› Press p to filter by a filename regex pattern.
› Press t to filter by a test name regex pattern.
› Press q to quit watch mode.
› Press Enter to trigger a test run.
أفضل ممارسة لوضع المراقبة:
أبق وضع المراقبة قيد التشغيل أثناء التطوير. يوفر ملاحظات فورية ويساعد في اكتشاف الانحدارات على الفور. استخدم خيار 'o' لتشغيل الاختبارات المتعلقة بالملفات المتغيرة فقط للحصول على ملاحظات أسرع.
تصفية الاختبارات
يسمح Jest بتخطي أو تشغيل اختبارات محددة فقط:
// تخطي اختبار
test.skip('سيتم تخطي هذا الاختبار', () => {
expect(true).toBe(false);
});
// تشغيل هذا الاختبار فقط
test.only('هذا الاختبار فقط سيتم تشغيله', () => {
expect(true).toBe(true);
});
// تخطي مجموعة كاملة
describe.skip('مجموعة للتخطي', () => {
test('لن يتم تشغيله', () => {
expect(true).toBe(true);
});
});
// تشغيل هذه المجموعة فقط
describe.only('هذه المجموعة فقط', () => {
test('سيتم تشغيله', () => {
expect(true).toBe(true);
});
});
لا تقم برفع .only():
لا تقم أبداً برفع كود يحتوي على معدلات .only(). فهي تمنع تشغيل الاختبارات الأخرى في خطوط CI/CD. استخدمها فقط أثناء التطوير المحلي.
مخرجات الاختبار وإعداد التقارير
فهم نتائج الاختبار
يوفر Jest مخرجات واضحة ومفيدة:
PASS src/sum.test.js
✓ adds 1 + 2 to equal 3 (2 ms)
✓ adds -1 + 1 to equal 0 (1 ms)
Test Suites: 1 passed, 1 total
Tests: 2 passed, 2 total
Snapshots: 0 total
Time: 1.234 s
رسائل الفشل
عندما تفشل الاختبارات، يعرض Jest معلومات تفصيلية:
FAIL src/sum.test.js
✕ adds 1 + 2 to equal 3 (5 ms)
● adds 1 + 2 to equal 3
expect(received).toBe(expected) // Object.is equality
Expected: 3
Received: 4
2 |
3 | test('adds 1 + 2 to equal 3', () => {
> 4 | expect(sum(1, 2)).toBe(3);
| ^
5 | });
تقارير التغطية
يمكن لـ Jest إنشاء تقارير تغطية كود شاملة:
npm test -- --coverage
ينشئ هذا تقرير تغطية يعرض:
------------|---------|----------|---------|---------|
File | % Stmts | % Branch | % Funcs | % Lines |
------------|---------|----------|---------|---------|
All files | 100 | 100 | 100 | 100 |
sum.js | 100 | 100 | 100 | 100 |
------------|---------|----------|---------|---------|
مقاييس التغطية:
- Statements: نسبة عبارات الكود المنفذة
- Branches: نسبة فروع if/else المختبرة
- Functions: نسبة الدوال المستدعاة
- Lines: نسبة الأسطر المنفذة
تمرين تطبيقي:
- أنشئ وحدة
calculator.js مع دوال الجمع والطرح والضرب والقسمة
- اكتب اختبارات شاملة في
calculator.test.js باستخدام كتل describe لتنظيم الاختبارات حسب العملية
- اختبر الحالات الحدية مثل القسمة على صفر والأرقام السالبة والحسابات العشرية
- شغل الاختبارات مع التغطية واستهدف تغطية 100%
- استخدم وضع المراقبة أثناء التطوير وجرب خيارات التصفية
أفضل الممارسات
تنظيم الاختبارات
- اجمع الاختبارات المرتبطة بكتل
describe
- استخدم أسماء اختبار وصفية تشرح ما يتم اختباره
- اتبع نمط الترتيب-التنفيذ-التأكيد (AAA)
- حافظ على تركيز الاختبارات - تأكيد واحد لكل اختبار عندما يكون ذلك ممكناً
تسمية الاختبارات
// جيد: يصف السلوك بوضوح
test('يعيد اسم المستخدم عندما يكون المستخدم موجوداً', () => {
// ...
});
// سيء: وصف غامض
test('اختبار دالة المستخدم', () => {
// ...
});
بنية الملف
نظم ملفات الاختبار لتعكس بنية المصدر الخاص بك:
src/
utils/
calculator.js
__tests__/
calculator.test.js
components/
Button.jsx
__tests__/
Button.test.jsx
نصيحة احترافية:
ضع ملفات الاختبار بالقرب من الكود الذي تختبره. هذا يسهل العثور على الاختبارات المرتبطة ويحافظ على تنظيم الاختبار متوافقاً مع بنية الكود الخاص بك.
الخلاصة
في هذا الدرس، قمنا بتغطية أساسيات Jest، إطار الاختبار الأكثر شعبية لـ JavaScript. لقد تعلمت كيفية تثبيت وتكوين Jest، وكتابة الاختبارات باستخدام دالتي test() وdescribe()، واستخدام المطابقات الشائعة للتأكيدات، والاستفادة من مشغل الاختبار القوي لسير عمل تطوير فعال.
نهج Jest بدون تكوين، جنباً إلى جنب مع ميزات مثل وضع المراقبة وتقارير التغطية ورسائل الخطأ الواضحة، يجعله خياراً ممتازاً لاختبار تطبيقات JavaScript من أي حجم. مع استمرارك في التعلم، ستكتشف ميزات أكثر تقدماً مثل المحاكاة واختبار اللقطات والاختبار غير المتزامن التي تجعل Jest أكثر قوة.