
إذا كنت تقوم بتطوير واجهات باستخدام React أو أطر عمل أخرى الواجهة الأماميةعاجلاً أم آجلاً، ستدرك أن الاعتماد فقط على عبارة "يعمل على جهازي" هو لعب بالنار. تغيير بسيط في أحد المكونات، أو إعادة هيكلة سريعة، أو تحديث أحد التبعيات، قد يُعطّل أجزاءً من التطبيق دون أن تلاحظ ذلك... إلا إذا كنت قد نظام اختبار وحدات جيد تم إعداده باستخدام Jest.
تتضمن بيئة جافا سكريبت الحديثة اختبارات مؤتمتة في صميمها. أدوات مثل دعابة هم يصنعون اكتب اختبارات للمكونيُفترض أن يكون استخدام الدوال والخطافات سهلاً في عملك اليومي، حتى لو لم تكن من هواة الاختبار. يكمن السر في امتلاك بيئة عمل مريحة، وفهم كيفية كتابة الاختبارات، ومعرفة كيفية تفسير النتائج وتغطية الاختبار لتحديد أجزاء الكود التي لم يتم اختبارها.
لماذا يتم إجراء اختبارات الوحدة في مشاريع الواجهة الأمامية؟
اختبارات الوحدة هي اختبارات صغيرة للتحقق من صحة أجزاء محددة من التعليمات البرمجية الخاصة بك (الدوال، والمكونات، والخطافات، والأدوات المساعدة...). في تطوير واجهات المستخدم، تُعدّ هذه الأدوات مفيدة للغاية لأن الواجهة تتغير باستمرار، وهناك منطق الحالة، وأحداث المستخدم، والمكالمات غير المتزامنة، وما إلى ذلك. وبدون شبكة أمان، يصبح كل تغيير بمثابة مقامرة.
من أبرز فوائد اختبار الوحدات ما يلي: الكشف المبكر عن الأخطاءبدلاً من اكتشاف الأخطاء عندما يكون المستخدم قد بدأ بالفعل في الإنتاج، يمكنك اكتشافها بمجرد حفظ التغييرات وتشغيل مجموعة الاختبارات، مما يساعدك على فهمها بشكل أفضل. دورة حياة الخللهذا يوفر على الفريق الوقت والمال والكثير من المتاعب.
ومن النقاط المهمة الأخرى أن تُصبح الاختبارات في نهاية المطاف بمثابة وثائق حية.إنّ الاطلاع على كيفية كتابة اختبار لمكوّن أو دالة ما يُوضّح كيفية استخدامه، وما هي المدخلات التي يقبلها، وما هي النتائج التي يجب أن يُعيدها. في المشاريع الكبيرة، يُعدّ هذا الأمر بالغ الأهمية لأعضاء الفريق الجدد.
في سياق جافا سكريبت ورياكت، تساعد كتابة الاختبارات أيضًا في تحسين تقسيم الكود إلى وحدات.لكي تتمكن من اختبار جزء بشكل منفصل، فأنت بحاجة إلى أن يكون معزولاً بشكل جيد، مع تبعيات واضحة ومسؤوليات محددة، وهو ما يترجم إلى واجهة أمامية أكثر قابلية للصيانة على المدى المتوسط والطويل.
ما هو Jest ولماذا يُستخدم بكثرة في تطوير واجهات المستخدم؟
Jest هو إطار عمل لاختبار جافا سكريبت تم تطويره في الأصل بواسطة فيسبوك، مصممة للعمل بشكل رائع مع React، ولكنها صالحة تمامًا لأي مشروع JavaScript أو TypeScript من جانب العميل أو الخادم.
ومن أهم أصولها هي فلسفة "التكوين الصفري"في العديد من المشاريع، يكفي تثبيته وإضافة سكربت إلى ملف package.json لبدء تشغيل الاختبارات دون الحاجة إلى التعامل مع ملفات التكوين المعقدة. وهذا ما يجعله جذابًا بشكل خاص في بيئات الواجهة الأمامية حيث تُستخدم العديد من الأدوات بالفعل.
يتم دمج Jest كمعيار قياسي الميزات الرئيسية لمشاريع الواجهة الأمامية: تنفيذ سريع للاختبارات، ووضع مراقبة يعيد تشغيل الاختبارات عند اكتشاف التغييرات، ودعم ملائم للغاية للتعليمات البرمجية غير المتزامنة، والمحاكاة والتجسس لمحاكاة التبعيات، وإنشاء تقارير تغطية التعليمات البرمجية دون الاعتماد على أدوات خارجية إضافية.
بالنسبة لمشاريع الواجهة الأمامية التي تستخدم React، يتم دمج Jest دائمًا تقريبًا مع مكتبة اختبار رد الفعلتُسهّل هذه المكتبة اختبار المكونات من خلال سلوكها وعرضها، بدلاً من الاعتماد المفرط على التنفيذ الداخلي. وباستخدام الأداتين معًا، يمكنك تغطية جميع احتياجاتك المعتادة لاختبار واجهات المستخدم تقريبًا.
تثبيت مكتبة اختبار Jest و React في مشروع الواجهة الأمامية
الخطوة الأولى للبدء باستخدام Jest هي إضافته كاعتمادية تطوير. في مشروعك. إذا كنت تستخدم npm، فسيكون الأمر النموذجي كالتالي:
npm install --save-dev jest
إذا كنت تفضل العمل بالخيوطيمكنك تثبيته باستخدام:
yarn add --dev jest
في المشاريع القائمة على React، من الشائع جدًا أيضًا تثبيت مكتبة اختبار React، والتي تتكون من عدة حزم: الحزمة الأساسية @testing-library/react للمكونات، و @testing-library/jest-dom للمطابقات الإضافية على DOM، وغالبًا @testing-library/user-event لمحاكاة تفاعلات المستخدم المعقدة.
قد يبدو إعداد React النموذجي كالتالي:
npm install --save-dev @testing-library/react @testing-library/jest-dom @testing-library/user-event
مع وجود هذه التبعيات، تصبح بيئتك جاهزة لكتابة اختبارات الوحدة التي تركز على المكونات.، الأحداث والنتائج مرئية للمستخدم، مع الاعتماد دائمًا على Jest كمحرك تنفيذ الاختبار الرئيسي.
تكوين Jest الأساسي في ملف package.json
بمجرد تثبيت Jest، ستحتاج إلى إخبار المشروع بكيفية تشغيل الاختبارات.تتمثل الممارسة المعتادة في إضافة نص برمجي إلى ملف package.json للحصول على أمر بسيط من الطرفية.
يمكن أن يكون أحد الأمثلة البسيطة على التكوين هو:
{ «البرامج النصية»: { «اختبار»: «المزاح» } }
باستخدام هذا البرنامج النصي، يمكنك تشغيل جميع اختبارات المشروع ببساطة عن طريق بدء التشغيل:
اختبار npm
أو، إذا كنت تستخدم خيوطًا، مع:
اختبار الخيوط
يكتشف Jest تلقائيًا ملفات الاختبار بناءً على اسمهابشكل افتراضي، سيبحث عن الملفات التي تحتوي على لاحقة .test.js أو .spec.js في شجرة المجلدات الخاصة بك، لذلك لا تحتاج عادةً إلى تحديد المسارات يدويًا طالما أنك تحترم هذه الاصطلاحات.
اصطلاح الملفات: امتداد .test.js وبنية الاختبار
لتمكين Jest من التعرف على اختباراتك دون الحاجة إلى إعدادات إضافية، يوصى بشدة باستخدام امتداد .test.js (أو .test.ts إذا كنت تعمل باستخدام TypeScript). على سبيل المثال، إذا كان لديك مكون Button.jsx، فسيكون الاسم الشائع لاختباره هو Button.test.js في نفس الدليل أو في مجلد اختبارات منفصل.
هذا الاتفاق ميزتان واضحتان:
- من ناحية أخرى، يقوم Jest بتحديد موقع الملفات المراد تنفيذها تلقائيًا.
- من ناحية أخرى، يعرف أي شخص جديد في المشروع على الفور أي الملفات تحتوي على كود الإنتاج وأيها تحتوي على الاختبارات.
يتم تحديد الاختبارات بواسطة دالة الاختبار أو اسمها المستعارحيث يمثل الوسيط الأول وصفًا نصيًا لما يتم التحقق منه، بينما يمثل الوسيط الثاني دالة تُنفذ منطق الاختبار. ويتم استخدام التأكيدات داخل هذه الدالة من خلال `expect` ومطابقاتها المختلفة.
في مكونات React، يكون الهيكل مشابهًابدلاً من اختبار دالة نقية، تقوم بعرض المكون باستخدام مكتبة اختبار React، والبحث عن العناصر على الشاشة (عن طريق النص، أو الدور، أو التسميات، وما إلى ذلك) والتحقق من عرضها أو تفاعلها كما تتوقع عند محاكاة تفاعلات المستخدم.
اكتب أول اختبار وحدة لك باستخدام Jest
لنجعل كل هذا واقعياً، تخيل دالة بسيطة تجمع قيمتينفي ملف باسم sum.js، عرّف الدالة sum(a, b) { return a + b; } وقم بتصديرها. ثم، في ملف sum.test.js، استورد تلك الدالة وعرّف اختبارًا مع وصف واضح لما يجب أن يحدث.
يقتصر جسم الاختبار على تنفيذ الوظيفة والتحقق من صحة النتيجة.تقوم باستدعاء الدالة sum(1, 2) وتستخدم expect للإشارة إلى أن القيمة يجب أن تكون 3 بالضبط. إذا توقفت الدالة عن إرجاع تلك النتيجة (بسبب خطأ أو تعديل غير متوقع)، فسيقوم Jest بوضع علامة على الاختبار بأنه فاشل.
هذا النوع من الاختبارات، مهما بدا بسيطاً، هو أساس اختبار الوحدة.تحتوي كل وظيفة أو وحدة منطقية على اختبار واحد أو أكثر يصف ما يجب أن تفعله في سيناريوهات مختلفة، بحيث يكون أي انحراف عن السلوك المتوقع واضحًا على الفور بمجرد تشغيل مجموعة الاختبارات.
أما في مكونات الواجهة الأمامية، فإن النهج يكون بنفس القدر من البساطة.تقوم بعرض المكون، والتحقق مما يتم عرضه، ومحاكاة الأحداث مثل النقرات أو الكتابة إلى المدخلات، والتحقق من أن الحالة الناتجة وDOM تتطابق مع ما يحدد التصميم الوظيفي للتطبيق.
مع نمو المشروع، سوف إضافة المزيد من الاختبارات لتغطية الحالات الحديةإدخالات غير نمطية، وأخطاء، وحالات أقل وضوحًا، مما يعزز موثوقية التطبيق ويمنع حدوث تراجعات عند إدخال وظائف جديدة.
أدوات مطابقة Jest: طرق مختلفة للتحقق من النتائج
جوهر الادعاءات في مسرحية "Jest" هو دالة التوقعيتم ربط هذه العملية بمطابقات مختلفة لتحديد متطلبات القيمة المستلمة. وبحسب نوع الاختبار، ستختار استخدام إحدى هذه المطابقات. فيما يلي أكثر المطابقات عملية:
- يكون. يتحقق هذا من التطابق التام، والذي يعني في جافا سكريبت تطابق القيمة والنوع، وهو أمر مفيد للغاية للأرقام والسلاسل النصية والقيم المنطقية التي تتطلب تطابقًا تامًا. فإذا كنت تتوقع القيمة 3، فلا تريد أن تصلك القيمة "3".
- لتساويمفيد عند التعامل مع الكائنات أو المصفوفات. يقارن هذا المطابق بنية ومحتوى الكائنات، مما يتيح لك التحقق من أن الدالة تُرجع كائنًا بالخصائص والقيم الصحيحة، حتى لو لم يكن المرجع الداخلي هو نفسه.
- لا. إذا احتجتَ في أي وقتٍ إلى التأكد من عدم حدوث شيءٍ ما، يمكنك استخدام أداة النفي `not`. على سبيل المثال، يُوضّح `expect(value).not.toBe(0)` أن الرقم لا يجب أن يكون صفرًا، أو يُشير `expect(array).not.toEqual([])` إلى أنك لا تتوقع مصفوفةً فارغة.
بالإضافة إلى هذه الأساسيات، يقدم Jest العديد من الميزات. وسطاء زواج آخرون: للتحقق من أن الدالة تُطلق خطأً، أو أن المصفوفة تحتوي على عنصر معين، أو أن السلسلة النصية تطابق تعبيرًا عاديًا، أو، باستخدام jest-dom في حالة React، أن عنصر DOM مرئي، أو معطل، أو يحتوي على نص معين، وما إلى ذلك.
الاختبار غير المتزامن في Jest: الوعود، و async/await، و callbacks
الواجهة الأمامية الحديثة مليئة بـ العمليات غير المتزامنةطلبات HTTP، والمؤقتات، وتفاعلات المستخدم التي تؤدي إلى تحديثات الحالة، وما إلى ذلك. لهذا السبب يدمج Jest عدة طرق للعمل بشكل مريح مع الاختبارات غير المتزامنة.
إن أنقى الطرق وأكثرها شيوعاً لاختبار المنطق غير المتزامن هي استخدم async/awaitتقوم بتعريف دالة الاختبار الخاصة بك على أنها غير متزامنة، وتنتظر حتى يتم حل الوعد الذي تتحقق منه، ثم تقوم بإجراء التأكيدات المعتادة باستخدام expect على النتيجة المستلمة.
على سبيل المثال، يمكنك أن يكون لديك دالة fetchData التي تُرجع وعدًا وتكتب اختبارًا غير متزامن يستدعي fetchData، وينتظر حتى يتم حله، ويتحقق من أن البيانات المُعادة تتطابق مع ما تتوقعه، سواء كان نصًا معينًا أو كائنًا ذا بنية معينة.
يدعم Jest أيضًا الوعود بشكل مباشر دون الحاجة إلى async/awaitيُعيد هذا الإجراء الوعد نفسه من الاختبار لكي يعرف الإطار متى انتهت العملية. بالإضافة إلى ذلك، في حالات قديمة أو محددة للغاية، يسمح باستخدام دوال رد الاتصال مع مُعامل `done` للإشارة إلى نهاية الاختبار.
في مجال مكتبة اختبار React، غالباً ما تجمع الاختبارات غير المتزامنة بين عمليات الانتظار و findBy أو waitFor، والتي تسمح بالانتظار حتى يتم تحديث DOM بعد طلب أو تغيير في الحالة قبل إجراء التأكيدات ذات الصلة.
المحاكاة في Jest: محاكاة الوحدات والوظائف والتبعيات
أحد المبادئ الأساسية لاختبار الوحدات هو اعزل الوحدة قيد الاختبارهذا يعني أنه إذا كانت وظيفة أو مكون يعتمد على خدمات خارجية (واجهات برمجة التطبيقات، ومكتبات الطرف الثالث، والوحدات النمطية الثقيلة، وما إلى ذلك)، فستحتاج إلى محاكاة تلك السلوكيات بدلاً من تشغيلها فعليًا أثناء الاختبار.
يُسهّل برنامج Jest هذا العزل من خلال المحاكاة.باستخدام jest.fn، يمكنك إنشاء دوال وهمية تسجل عدد مرات استدعائها، والوسائط التي تستخدمها، والقيمة التي يجب أن تُرجعها. يُعد هذا مفيدًا جدًا لاختبار التفاعلات الداخلية دون الحاجة إلى تعديل الشيفرة البرمجية الفعلية لتلك الخدمات.
عندما تحتاج إلى الذهاب خطوة أخرى، تتيح لك مكتبة jest.mock استبدال الوحدات النمطية بالكامليمكنك تحديد أنه عند استيراد ملف معين، يجب على Jest استخدام تطبيق وهمي يقوم بإرجاع قيم متحكم بها، وتجنب، على سبيل المثال، إرسال طلبات HTTP حقيقية في كل مرة يتم فيها تشغيل مجموعة الاختبار.
في مكونات React، تُستخدم الكائنات الوهمية بشكل متكرر لمحاكاة الخطافات المخصصة.، خدمات البيانات أو الوحدات التي تدير التخزين المحلي والتحليلات وما إلى ذلك، مع الحفاظ على تركيز الاختبار على سلوك المكون وليس على سلوك تبعياته الخارجية.
عند الاستخدام الصحيح، يؤدي استخدام المحاكاة إلى تسريع تنفيذ الاختبارات بشكل كبير. ويتيح لك إعادة إنتاج سيناريوهات الأخطاء بسهولة، أو استجابات الخادم الغريبة، أو الحالات غير النمطية التي يصعب تحقيقها من خلال التفاعل مع الخدمات الحقيقية.
يصف تنظيم وتجميع الاختبارات باستخدام الكتل
مع نمو مجموعة الاختبارات الخاصة بك، ستحتاج الحفاظ على الحد الأدنى من النظام ولتجنب الضياع بين مئات الاختبارات المنتشرة عبر ملفات متعددة، يوفر Jest الكتل كطريقة طبيعية لتجميع الاختبارات ذات الصلة.
باستخدام خاصية الوصف يمكنك تضمين عدة اختبارات ضمن نفس السياقعلى سبيل المثال، "العمليات الحسابية" أو "سلوك مكون الرأس". ضمن الكتلة، يصف كل اختبار حالة محددة، لكن المجموعة تبدو وكأنها قصة متماسكة حول ذلك الجزء من الكود.
تساعد هذه المنظمة في كل من القراءة وتصحيح الأخطاء.عندما يحدث خطأ ما، يصبح من الأسهل تحديد مجموعة الاختبار وفهم أي جزء من النظام يتأثر، دون الحاجة إلى فحص المشروع بأكمله.
وبالإضافة إلى ذلك، يتكامل الوصف بشكل ممتاز مع خطافات دورة حياة Jest، مثل beforeEach أو afterEach، مما يسمح لك بإعداد البيانات أو مسح الحالات المشتركة لجميع الاختبارات داخل نفس الكتلة، وتجنب تكرار منطق التهيئة في كل اختبار على حدة.
في مشاريع الواجهة الأمامية المعقدة، من الشائع وجود وصف لكل مكون.، مقسمة إذا لزم الأمر إلى أوصاف داخلية لأوضاع مختلفة أو خصائص أو تدفقات تفاعل، مما يحول ملف الاختبار إلى خريطة واضحة إلى حد ما لكل ما هو متوقع من هذا المكون.
استخدام منهجية اختبار وتنفيذ npm في سير العمل
بعد اكتمال التكوين الأساسي، يصبح أمر npm test حليفك اليومييجب أن يكون تشغيله قبل تحميل التغييرات إجراءً تلقائياً تقريباً، مثل حفظ الملف أو تشغيل أداة التدقيق اللغوي.
تتبنى العديد من الفرق قاعدة غير مكتوبة مفادها عدم الالتزام إذا فشلت الاختبارات.تمنع هذه الممارسة الفرع الرئيسي للمشروع من التعطل وتحافظ على الحد الأدنى المضمون من الجودة في كل عملية دمج أو طلب سحب يتم دمجه في المستودع.
يقدم جيست أيضًا وضع تفاعلي مفيد للغاية قيد التطويرمن خلال تشغيل npm test في وضع المراقبة، يقوم الإطار بإعادة تشغيل الاختبارات المتعلقة فقط بالملفات التي تقوم بتعديلها، مما يؤدي إلى تسريع دورة الاختبار والإصلاح بشكل كبير أثناء تطوير ميزات جديدة أو إصلاح الأخطاء.
دمج Jest في نظام التكامل المستمر (CI) كـ إجراءات جيثب أكمل الدائرةفي كل مرة يقوم فيها شخص ما بتحميل التعليمات البرمجية إلى المستودع البعيد، يقوم خادم التكامل المستمر بتشغيل اختبار npm ويحظر التكامل إذا فشلت المجموعة، مما يمنع الأخطاء من التسلل إلى البيئات المشتركة.
تغطية الكود: قياس مدى اختبار الكود فعليًا
لا يكفي إجراء بعض الاختبارات الكتابية. ومن المثير للاهتمام أيضاً معرفة مدى تغطيتهم للرمز.ولهذا الغرض، يدمج Jest تقارير التغطية التي تشير إلى الأسطر والوظائف والفروع التي تم تنفيذها أثناء الاختبار.
إن إنشاء هذه التقارير بسيط مثل إضافة علامة --coverage إلى أمر الاختبار.على سبيل المثال، يمكنك تكوين البرنامج النصي package.json على النحو التالي: "test": "jest --coverage" أو تشغيل npm test --coverage عندما تريد تقريرًا مفصلاً.
وتشمل النتيجة نسب التغطية لكل ملف وعلى المستوى العالميسترى أي الملفات تتمتع بتغطية جيدة وأيها بالكاد يتم لمسها أثناء الاختبار، مما يساعدك على تحديد أين يستحق الأمر بذل جهد إضافي في كتابة المزيد من الاختبارات.
وبطبيعة الحال، يجدر بنا أن نتذكر أن لا تضمن التغطية بنسبة 100% خلو المنتج من الأخطاء.من الممكن تشغيل جميع أسطر التعليمات البرمجية باختبارات غير متطلبة، لذا فإن جودة التأكيدات لا تقل أهمية عن الرقم نفسه، بل قد تكون أكثر أهمية منه.
استخدم التغطية كمؤشر تقريبي، بالإضافة إلى مراجعات التعليمات البرمجية والمنطق السليم.إنها طريقة جيدة للحفاظ على التوازن بين جهد الاختبار والفوائد الحقيقية لاستقرار المشروع.
مع رؤية كل شيء ، استخدام Jest وأدوات مثل مكتبة اختبار React في مشاريع الواجهة الأمامية يصبح ذلك قراراً منطقياً إلى حد مايتيح لك ذلك التحقق من أن كل مكون ووظيفة يقوم بما ينبغي عليه، وتشغيل الاختبارات بسهولة باستخدام npm test، ومراقبة التغطية باستخدام –coverage، والحفاظ على قاعدة بيانات قوية حيث يكون من الآمن تطوير المنتج دون خوف من كسر ما كان يعمل بالفعل.



