اختبار JavaScript: من اختبارات الوحدات إلى الاختبارات الشاملة
\n\nالاختبار عالي الجودة هو جزء لا يتجزأ من التطوير الاحترافي باستخدام JavaScript. في هذه المقالة، سنناقش المستويات الثلاثة الرئيسية للاختبار: اختبارات الوحدات (unit)، واختبارات التكامل (integration)، واختبارات النهاية إلى النهاية (e2e). ستتعرف على الأدوات التي يجب استخدامها، وكيفية كتابة الاختبارات على Node.js، وكيفية بناء استراتيجية اختبار فعالة.
\n\n1. اختبار الوحدات (Unit Testing): أساس هرم الاختبار
\n\nتتحقق اختبارات الوحدات من الوحدات المعزولة - الدوال أو الفئات أو الطرق الفردية. القاعدة الأساسية: يجب ألا يعتمد الكود الذي يتم اختباره على الموارد الخارجية (قواعد البيانات، واجهات API، نظام الملفات).
\n\nأدوات اختبار الوحدات
\n- \n
- Jest - الإطار الأكثر شيوعًا من Facebook. يتضمن بشكل افتراضي mock، snapshots، وتغطية الكود. \n
- Mocha + Chai - مجموعة مرنة لمن يحبون تخصيص كل شيء يدويًا. \n
- Vitest - بديل حديث لـ Jest، محسّن لمشاريع Vite. \n
// مثال على اختبار وحدة باستخدام Jest\nconst { calculateDiscount } = require('./pricing');\n\ndescribe('calculateDiscount', () => {\n test('يعيد خصم 10% للمبلغ > 1000', () => {\n const result = calculateDiscount(1500);\n expect(result).toBe(1350);\n });\n\n test('لا يطبق خصم للمبلغ <= 1000', () => {\n const result = calculateDiscount(500);\n expect(result).toBe(500);\n });\n\n test('يعالج القيمة الحدية 1000', () => {\n const result = calculateDiscount(1000);\n expect(result).toBe(1000);\n });\n});\n\nأفضل ممارسات اختبار الوحدات
\n- \n
- اختبر سلوكًا واحدًا في كل مرة (assertion واحد لكل اختبار). \n
- استخدم أسماء اختبار وصفية (given/when/then). \n
- تجنب اختبار الطرق الخاصة - اختبر الواجهة العامة. \n
- حافظ على تغطية الكود عند مستوى 70-80%. \n
2. اختبار التكامل (Integration Testing): التحقق من تفاعل المكونات
\n\nتتحقق اختبارات التكامل من كيفية عمل الوحدات المختلفة معًا. في سياق Node.js، يعني هذا عادةً الاختبار مع قاعدة بيانات حقيقية، أو نظام ملفات، أو واجهات API خارجية.
\n\nسيناريوهات اختبار التكامل النموذجية
\n- \n
- تفاعل المتحكم (controller) مع طبقة الخدمات وقاعدة البيانات. \n
- التحقق من middleware ومسارات Express/Koa. \n
- اختبار المستودعات (repositories) مع قاعدة بيانات اختبارية (SQLite في الذاكرة أو PostgreSQL في Docker). \n
// مثال على اختبار تكامل باستخدام Supertest و Jest\nconst request = require('supertest');\nconst app = require('../app');\nconst { createTestUser, cleanDatabase } = require('./helpers');\n\nbeforeEach(async () => {\n await cleanDatabase();\n});\n\ndescribe('POST /api/users', () => {\n test('ينشئ مستخدمًا ويعيد 201', async () => {\n const response = await request(app)\n .post('/api/users')\n .send({ name: 'إيفان', email: 'ivan@test.com' });\n\n expect(response.status).toBe(201);\n expect(response.body).toHaveProperty('id');\n expect(response.body.name).toBe('إيفان');\n });\n\n test('يعيد 400 عند تكرار البريد الإلكتروني', async () => {\n await createTestUser({ email: 'ivan@test.com' });\n\n const response = await request(app)\n .post('/api/users')\n .send({ name: 'بيتر', email: 'ivan@test.com' });\n\n expect(response.status).toBe(400);\n expect(response.body.error).toBe('البريد الإلكتروني مستخدم بالفعل');\n });\n});\n\nإعداد البنية التحتية للاختبار
\n- \n
- Docker Compose - لتشغيل خدمات الاختبار (قواعد البيانات، Redis). \n
- Testcontainers - إدارة برمجية للحاويات من داخل الاختبارات. \n
- قواعد البيانات في الذاكرة (مثل mongodb-memory-server) - لاختبارات سريعة بدون تبعيات خارجية. \n