بيئات الاختبار في React
بيئات الاختبار
تركز هذه الصفحة على توضيح العوامل التي تؤثر على بيئة الاختبار بالإضافة إلى توفير بعض التوصيات التي يمكنها مساعدتك في التعامل مع العديد من الاحتمالات المختلفة.
أدوات الاختبار
تُتيح لك أدوات اختبار مثل Jest و mocha و ava تصميم مجموعات اختبار باستخدام لغة جافاسكربت وتشغيلها كجزء من بيئة التطوير التي تستخدمها كما يمكنك وضعهامثل أجزاء من تكامل متواصل عبر استخدام إحدى برامج إدارة الإصدارات مثل Git.
- تتوافق مكتبة Jest جيدًا مع مشاريع ريآكت إذ تدعم مزايا قوية، مثل: المؤقِّتات، ومُحاكاة المكوِّنات، ودعم مكتبة jsdom. إذا استخدمت الأداة create-react-app لبناء تطبيق ريآكت، فستلاحظ أنّ مكتبة jsdom تأتي مُثبّتة مسبقًا بإعدادات مناسبة لبدء الاستخدام مباشرةً.
- تُعَدّ مكتبة mocha وما يُشابهها مناسبةً للعمل على بيئة متصفِّح حقيقي ويمكنها المساعدة في إعداد اختبارات تستهدف تلك النقطة.
- يُستخدم أسلوب الاختبار الكامل (اختبار عمل كامل التطبيق من البداية إلى النهاية أو ما يُعرف باختبار End-to-end tests) لاختبار سير عمل التطبيق لفترات طويلة وعلى مدار سيناريوهات مختلفة وعادةً ما يتطلّب هذا النوع تحضيرات مختلفة لإجراء الاختبار.
محاكاة المعالجة
عادةً ما تُجرى الاختبارات في بيئة تطوير لا تمتلك وصولًا إلى مُحاكي حقيقي مثل متصفح الإنترنت. يُوصى في تلك الحالة بإنشاء مُحاكي للمتصفِّح عبر الاستعانة بمكتبة jsdom كونها تُقدِّم تكاملًا بسيطًا يعمل داخل ريآكت ولا يتطلّب الكثير من قوة المعالجة لتشغيله.
تعمل مكتبة jsdom مثل متصفِّح عادي في معظم الحالات لكنها لا توفِّر مزايا بصرية، مثل: تنسيق الصفحات، والتنقل عبر الروابط. مع ذلك فهي تفي بالغرض لمعظم الاختبارات المبنية لتعمل على الويب، كما أنها تعمل بسرعة أكبر موازنةً مع تشغيل متصفِّح حقيقي في كلّ اختبار. أضف إلى ذلك أنّ هذه المكتبة تعمل في نفس خط المعالجة الذي يستخدمه الاختبار، أي ستتمكن من كتابة تعليمات برمجية لتفقُّد وتقييم المخرجات الناتجة على نموذج كائن المستند (DOM) قيد المُحاكاة.
وكما هو الحال في المتصفِّحات الحقيقة، تُتيح لك مكتبة jsdom مُحاكاة تفاعلات المستخدم، أي يمكنك تقليد أحداث مرتبطة بعناصر الصفحة لرؤية وتقييم عملها وآثارها الجانبية.
يمكن تصميم جزء كبير من اختبارات الواجهات (UI tests) عبر استخدام ذلك الأسلوب، أي استخدام Jest مثل أداة اختبار ومحاكاته باستخدام مكتبة jsdom مع تحديد تفاعلات المستخدم مثل سلسلة من الأحداث عبر استخدام دالّة act()
. في الحقيقة كُتِبت الكثير من الاختبارات التي صمّمتها ريآكت باستخدام تلك الخطوات.
أمّا إذا كنت تصمِّم مكتبةً تستهدف اختبار سلوك المتصفِّح وتتطلّب وجود مزايا متصفِّح حقيقي مثل تنسيق الصفحات أو توفير مُدخَلات حقيقية، فربما يجدر بك استخدام إطار عمل مثل mocha.
إذا كنت تستخدم بيئة اختبار لا يمكنها مُحاكاة نموذج كائن المستند (DOM) كما هو الحال في اختبار مكوِّنات ريآكت المُدمَجة في Node.js، فيمكنك الاستعانة بمُحاكيات الأحداث (event simulation helpers) لمحاكاة التفاعلات مع العناصر. أو يمكنك استخدام محاكي fireEvent
من مكتبة اختبار ريآكت.
وبالطبع هناك إطارات عمل أخرى مثل Cypress، وpuppeteer، وwebdriver تُعَدّ أكثر مُلاءمةً في حالة رغبت في إجراء اختبارات كاملة (end-to-end tests).
محاكاة الدوال
قد ترغب أحيانًا عند مُحاكاة الاختبار في تقليد الأجزاء التي لا يمكنك تقييمها في بيئة الاختبار، مثل اختبار خاصية navigator.onLine
للتحقق من كون المتصفِّح متصل بالإنترنت. يمكن للاختبارات أيضًا مراقبة عمل بعض الدوال وتفحص كيف تتفاعل أجزاء الاختبار الأخرى معها، مما يسهل من عملية محاكاتها باستخدام طرق اختبار ملائمة.
تمتلك هذه النقطة أهميةً خاصةً بالنسبة إلى ميزة جلب البيانات (data fetching)، إذ يُفضَّل استخدام بيانات مُزيَّفة أثناء الاختبار لتفادي البطء والتعقيد، المرتبط بعملية جلب البيانات من واجهة برمجة تطبيقات (API) حقيقية، كما يُساعد هذا أيضًا على جعل نتائج الاختبار متوقَّعة. تدعم مكتبات، مثل: Jest، وsinon، ميزة مُحاكاة الدوال، لكن عندما يتعلق الأمر بالاختبارات الكاملة فعادةً ما تكن عملية مُحاكاة شبكة الاتصال أصعب، ومع ذلك فقد تجد نفسك مُضطرًا إلى اختبار تلك الدوال باستخدام بيانات واجهة برمجة تطبيقات حقيقة (real API endpoints).
محاكاة الوحدات
تمتلك بعض المكوِّنات مُتطلّبات تتضمن وحدات لا تؤدّي جيدًا داخل بيئات الاختبار، أو لا تمتلك أهميةً تجاه تلك الاختبارات، لذلك يُنصح باستبدال عملية مُحاكاتها عبر استخدام بدائل مناسبة كما في هذا المثال.
بالنسبة إلى نظام Node.js، فإنّ أدوات اختبار مثل Jest ، تدعم مُحاكاة الوحدات كما يمكنك استخدام مكتبات مثل mock-require لإجراء نفس العملية.
محاكاة المؤقتات
قد تستخدم بعض المكوِّنات دوال مبنية على الوقت، مثل: دالّة setTimeout
، أو setInterval
، أو Date.now
. وفي تلك الحالة يُفضَّل استبدال مُحاكاة تلك الدوال عبر استخدام بدائل تُتيح تغيير الوقت يدويًا، إذ يساعد هذا في تسريع الاختبار. بالطبع فإن الاختبارات التي تعتمد على المؤقِّتات ستُجرى بالترتيب المُحدّد لكن بنحو أسرع. ولحسن الحظ فمعظم إطارات العمل، مثل: Jest ، وsinon، وlolex، تُتيح لك مُحاكاة المؤقِّتات ضمن بيئة الاختبار.
من ناحية أخرى هناك بعض الأوقات التي لا ترغب فيها بمحاكاة المؤقِّتات، مثلًا إذا كنت ترغب في اختبار بعض الرسوميات أو التفاعل مع واجهة برمجة حساسة للوقت. لذلك فالمكتبات التي تتضمّن محاكي للمؤقِّتات، ستُتيح لك تشغيلها أو تعطيلها لكلّ اختبار أو مجموعة اختبارات على حِدة، مما يسمح لك بانتقاء الاختبارات الملائمة لاستخدام هذه الميزة وكيف تُجرى تلك الاختبارات.
الاختبارات الكاملة (End-to-end tests)
تُعَدّ الاختبارات الكاملة أكثر فائدةً عند اختبار سير العمل الأطول نسبيًا، خاصةً عند اختبار مزايا مهمة لمشروعك، مثل: عملية تسجيل الاشتراك، أو عمليات الدفع. في تلك الحالات قد ترغب في اختبار كيف يعالج المتصفِّح الحقيقي كامل تطبيقك وكيف يجلب البيانات من واجهة برمجة حقيقية (API)، وكيف يستخدم بيانات الجلسات (sessions)، وملفّات تعريف الارتباط (cookies)، وكيف يتنقَّل بين الروابط المختلفة. كما قد تحتاج إلى تقييم حالة نموذج كائن المستند (DOM)، وعملية تحديث البيانات أيضًا (أي تفقُّد إذا ما كانت التحديثات تُحفظ في قاعدة البيانات صحيحةً).
ستحتاج في تلك الأوقات إلى استخدام إطار عمل مثل Cypress، أو مكتبة مثل puppeteer، لكي تتمكَّن من التنقذُل بين مسارات متعدِّدة في الاختبار والتأكُّد من عدم ظهور آثار جانبية غير مرغوبة على المتصفِّح والخادم أيضًا.
ترجمة -وبتصرف- للمقال Testing Environments، من توثيق ريآكت