اختبار JavaScript: Unit، Integration، E2E — من الألف إلى الياء
تطوير تطبيق ويب حديث باستخدام JavaScript (خاصة على Node.js) لا يمكن أن يتم دون اختبار عالي الجودة. لا تكتشف الاختبارات الأخطاء قبل الوصول إلى الإنتاج فحسب، بل تعمل أيضًا كتوثيق حي، وتسمح بإعادة هيكلة الكود دون خوف من كسر شيء ما. في هذه المقالة، سنشرح المستويات الثلاثة الرئيسية لهرم الاختبار: unit (الاختبارات الوحدوية)، integration (اختبارات التكامل) و e2e (الاختبارات الشاملة). ستتعرف على الاختلافات بينها، والأدوات التي يجب استخدامها، وسترى أمثلة جاهزة على Node.js.
1. اختبارات Unit: اختبار الوحدات المنعزلة
اختبارات Unit هي أساس الهرم. تتحقق من عمل الدوال أو الفئات أو المكونات الفردية في عزلة تامة عن التبعيات الخارجية (قواعد البيانات، API، نظام الملفات). الهدف الرئيسي هو التأكد من أن منطق الوحدة يعمل بشكل صحيح مع أي بيانات إدخال.
بالنسبة لـ Node.js، الإطار الأكثر شيوعًا هو Jest (من Facebook). لا يتطلب تكوينًا معقدًا، ويحتوي على تأكيدات مدمجة، و mock، وتغطية الكود.
مثال: اختبار دالة ترتيب مصفوفة
// utils.jsfunction sortNumbers(arr) { if (!Array.isArray(arr)) { throw new Error('Input must be an array'); } return [...arr].sort((a, b) => a - b);}
module.exports = { sortNumbers };// utils.test.jsconst { sortNumbers } = require('./utils');
describe('sortNumbers', () => { test('should sort an array of numbers in ascending order', () => { expect(sortNumbers([3, 1, 2])).toEqual([1, 2, 3]); });
test('should handle an empty array', () => { expect(sortNumbers([])).toEqual([]); });
test('should throw error for non-array input', () => { expect(() => sortNumbers('string')).toThrow('Input must be an array'); });});أفضل الممارسات لاختبارات Unit:
- اختبار واحد — فحص واحد (assert واحد).
- استخدم
describeلتجميع الاختبارات حسب الدوال. - قم بعمل mock للتبعيات الخارجية (باستخدام
jest.mock()). - اكتب الاختبارات قبل كتابة الكود (TDD — Test-Driven Development).
2. اختبارات التكامل: التحقق من تفاعل المكونات
اختبارات التكامل تتحقق من كيفية عمل الوحدات المختلفة للنظام معًا. على سبيل المثال، كيف يتفاعل المتحكم (controller) الخاص بك مع قاعدة البيانات أو API خارجي. على عكس اختبارات Unit، هنا لا نقوم بعمل mock لكل شيء، بل نستخدم بيئات حقيقية (أو اختبارية).
لاختبار خوادم HTTP على Express، تعتبر مكتبة Supertest ممتازة مع Jest.
مثال: اختبار نقطة نهاية REST
// app.jsconst express = require('express');const app = express();
app.get('/api/hello', (req, res) => { res.json({ message: 'Hello, World!' });});
app.post('/api/data', (req, res) => { const { name } = req.body; if (!name) { return res.status(400).json({ error: 'Name is required' }); } res.status(201).json({ received: name });});
module.exports = app;// app.test.jsconst request = require('supertest');const app = require('./app');
describe('Integration tests for API', () => { test('GET /api/hello should return a greeting', async () => { const response = await request(app) .get('/api/hello') .expect(200);
expect(response.body).toEqual({ message: 'Hello, World!' }); });
test('POST /api/data with valid body should return 201', async () => { const response = await request(app) .post('/api/data') .send({ name: 'Alice' }) .expect(201);
expect(response.body).toEqual({ received: 'Alice' }); });
test('POST /api/data without name should return 400', async () => {