حدِّد ما تحتاج إلى اختباره وما يمكنك استبعاده.
تناولت المقالة السابقة أساسيات حالات الاختبار وما يجب أن تحتوي عليه. تتناول هذه المقالة بالتفصيل إنشاء حالات الاختبار من منظور فني، وتوضّح ما يجب تضمينه في كل اختبار وما يجب تجنّبه. في الأساس، ستتعرّف على الإجابة عن الأسئلة القديمة حول "ما الذي يجب اختباره" أو "ما الذي لا يجب اختباره".
الإرشادات العامة والأنماط
تجدر الإشارة إلى أنّ هناك أنماطًا ونقاطًا معيّنة مهمة، بغض النظر عمّا إذا كنت تُجري اختبارات الوحدة أو الدمج أو الاختبار من البداية إلى النهاية. يمكن تطبيق هذه المبادئ ويجب تطبيقها على كلا النوعَين من الاختبارات، لذا فهي نقطة انطلاق جيدة.
اعتماد البساطة
عند كتابة الاختبارات، من أهم الأمور التي يجب تذكرها هي الحفاظ على البساطة. من المهم مراعاة قدرة الدماغ. يشغل رمز الإنتاج الرئيسي مساحة كبيرة، ما يترك مساحة قليلة لتعقيد إضافي. وينطبق ذلك بشكل خاص على الاختبار.
إذا كان هناك مساحة أقل متاحة، قد تشعر بالاسترخاء أكثر في جهود الاختبار. لهذا السبب، من المهم إعطاء الأولوية للبساطة في الاختبار. في الواقع، تُبرز أفضل الممارسات لاختبار JavaScript التي وضعها "يونى جولدبيرغ" أهمية القاعدة الذهبية، وهي أنّ الاختبار يجب أن يُشعرك بأنّه مساعد وليس صيغة رياضية معقّدة. بعبارة أخرى، يجب أن تتمكّن من فهم الغرض من الاختبار من النظرة الأولى.
يجب أن تسعى إلى البساطة في جميع أنواع الاختبارات، بغض النظر عن تعقيدها. في الواقع، كلما كان الاختبار معقّدًا، كان من الضروري تبسيط محتواه. وإحدى الطرق لتحقيق ذلك هي من خلال تصميم اختبارات بسيطة، حيث يتم إبقاء الاختبارات بسيطة قدر الإمكان، واختبار ما هو ضروري فقط. وهذا يعني أنّ كل اختبار يجب أن يحتوي على حالة اختبار واحدة فقط، ويجب أن تركّز حالة الاختبار على اختبار وظيفة أو ميزة معيّنة واحدة.
ننصحك بالتفكير من هذه الناحية: من المفترض أن يكون من السهل تحديد الخطأ عند قراءة اختبار تعذّر إكماله. لهذا السبب، من المهم أن تكون الاختبارات بسيطة وسهلة الفهم. يتيح لك ذلك تحديد المشاكل وحلّها بسرعة عند حدوثها.
اختبار المحتوى الذي يستحقّ النشر
يشجع تصميم الاختبار البسيط أيضًا على التركيز ويساعد في ضمان أن تكون اختباراتك ذات مغزى. تذكَّر أنّه لا يجب إنشاء الاختبارات فقط من أجل تغطية المحتوى، بل يجب أن يكون لها غرضًا في كلّ الأوقات.
لا تختبر تفاصيل التنفيذ.
من المشاكل الشائعة في الاختبار أنّه غالبًا ما يتم تصميم الاختبارات لاختبار تفاصيل التنفيذ، مثل استخدام المحدّدات في المكوّنات أو الاختبارات الشاملة. تشير تفاصيل التنفيذ إلى العناصر التي لن يستخدمها مستخدمو الرمز البرمجي عادةً أو يطّلعوا عليها أو حتى يعرفوا عنها. ويمكن أن يؤدي ذلك إلى حدوث مشكلتَين رئيسيتين في الاختبارات: النتائج السلبية الخاطئة والنتائج الموجبة الخاطئة.
تحدث النتائج السلبية الخاطئة عند تعذُّر إجراء اختبار، حتى لو كان الرمز الذي تم اختباره صحيحًا. ويمكن أن يحدث ذلك عند تغيير تفاصيل التنفيذ بسبب إعادة هندسة رمز التطبيق. من ناحية أخرى، تحدث النتائج الإيجابية الخاطئة عند اجتياز الاختبار، حتى لو كان الرمز البرمجي الذي يتم اختباره غير صحيح.
أحد الحلول لهذه المشكلة هو مراعاة الأنواع المختلفة من المستخدمين لديك. يمكن أن يختلف أسلوب المستخدمين النهائيين والمطوّرين، وقد يتفاعلون مع الرمز البرمجي بشكل مختلف. عند التخطيط للاختبارات، من الضروري مراعاة ما سيرى المستخدمون أو يتفاعلون معه، وجعل الاختبارات تعتمد على هذه العناصر بدلاً من تفاصيل التنفيذ.
على سبيل المثال، يمكن أن يؤدي اختيار أدوات الاختيار الأقل عرضة للتغيير إلى جعل الاختبارات أكثر موثوقية: سمات البيانات بدلاً من أدوات اختيار CSS. لمزيد من التفاصيل، يُرجى الرجوع إلى Kent C. مقالة "دودز" حول هذا الموضوع، أو يمكنك المتابعة لاحقًا للحصول على مقالة حول هذا الموضوع.
السخرية: لا تفقد السيطرة
التزوير هو مفهوم واسع النطاق يُستخدَم في اختبار الوحدات وفي اختبار الدمج أحيانًا. ويشمل ذلك إنشاء بيانات أو مكوّنات مزيّفة لمحاكاة التبعيات التي تتحكّم بشكل كامل في التطبيق. يتيح ذلك إجراء اختبار معزول.
يمكن أن يؤدي استخدام النماذج الاختبارية في اختباراتك إلى تحسين قابلية التوقّع وفصل المخاوف والأداء. وإذا كنت بحاجة إلى إجراء اختبار يتطلّب تدخلًا بشريًا (مثل إثبات صحة جواز السفر)، عليك إخفاءه باستخدام نموذج تجريبي. لكل هذه الأسباب، فإنّ النماذج المرجعية هي أداة قيّمة يجب أخذها في الاعتبار.
وفي الوقت نفسه، قد تؤثر المحاكاة في دقة الاختبار لأنّها محاكاة، وليست تجارب المستخدمين الفعلية. لذا، عليك الانتباه عند استخدام النماذج الاختبارية والعناصر النموذجية.
هل يجب استخدام النماذج في الاختبارات الشاملة؟
بشكل عام، لا. ومع ذلك، يمكن أن يكون التوقّع مفعّلاً لإنقاذ حياتك في بعض الأحيان، لذا لن نستبعده تمامًا.
تخيل هذا السيناريو: أنت بصدد كتابة اختبار لميزة تتضمّن خدمة مقدّم دفع تابع لجهة خارجية. أنت في بيئة اختبار تم توفيرها من قِبل الجهة، ما يعني أنّه لا يتم إجراء أي معاملات حقيقية. يتعذّر على وضع الحماية العمل بشكل صحيح، ما يؤدي إلى تعذّر اجتياز اختباراتك. على موفّر خدمة الدفع حلّ هذه المشكلة. ما عليك سوى الانتظار إلى أن يحلّ مقدّم الخدمة المشكلة.
في هذه الحالة، قد يكون من الأفضل تقليل الاعتماد على الخدمات التي لا يمكنك التحكّم فيها. يُنصح باستخدام المحاكاة بعناية في اختبارات الدمج أو الاختبارات الشاملة لأنّها تؤدي إلى خفض مستوى الثقة في اختباراتك.
تفاصيل الاختبار: الإجراءات المسموح بها وغير المسموح بها
إذًا، ما الذي يحتوي عليه الاختبار؟ وهل هناك اختلافات بين أنواع الاختبارات؟ لنلقِ نظرة عن كثب على بعض الجوانب المحدّدة المخصّصة لأنواع الاختبار الرئيسية.
ما هي العناصر التي يجب أن تتضمّنها اختبارات الوحدة الجيدة؟
يجب أن يستوفي اختبار الوحدة المثالي والفعّال الشروط التالية:
- التركيز على جوانب معيّنة
- العمل بشكل مستقل
- أن تشمل سيناريوهات صغيرة النطاق
- استخدِم أسماءً وصفية.
- اتّبِع نمط AAA إذا كان ذلك منطبقًا.
- ضمان تغطية اختبارية شاملة
ما تفعله ✅ | ما يجب تجنّبه ❌ |
---|---|
يجب أن تكون الاختبارات صغيرة قدر الإمكان. اختبِر عنصرًا واحدًا لكل حالة اختبار. | كتابة اختبارات على وحدات كبيرة |
يجب دائمًا عزل الاختبارات ومحاكاة العناصر التي تحتاج إليها خارج وحدتك. | أن تتضمّن مكونات أو خدمات أخرى |
يجب أن تكون الاختبارات مستقلة. | الاعتماد على الاختبارات السابقة أو مشاركة بيانات الاختبار |
أن تتناول سيناريوهات ومسارات مختلفة | يجب التركيز على مسار الإجراء الصحيح أو الاختبارات السلبية كحد أقصى. |
استخدِم عناوين اختبارات وصفية حتى تتمكّن من معرفة موضوع الاختبار على الفور. | الاختبار حسب اسم الدالة فقط، وليس حسب الوصف الكافي: testBuildFoo() أو testGetId() |
احرص على تغطية الرمز البرمجي بشكل جيد أو مجموعة أوسع من حالات الاختبار، خاصةً في هذه المرحلة. | يمكنك إجراء الاختبار من كل فئة وصولاً إلى مستوى قاعدة البيانات (I/O). |
ما الذي يندرج ضمن اختبار الدمج الجيد؟
يشترك اختبار الدمج المثالي أيضًا في بعض المعايير مع اختبارات الوحدة. ومع ذلك، هناك نقطتان إضافيتان يجب مراعاتهما. يجب أن يستوفي اختبار الدمج الجيد الشروط التالية:
- محاكاة التفاعلات بين المكوّنات
- أن تتناول سيناريوهات واقعية، وتستخدم نماذج محاكاة أو نماذج تجريبية
- راجِع الأداء.
ما تفعله ✅ | ما يجب تجنّبه ❌ |
---|---|
اختبار نقاط الدمج: تأكَّد من أنّ كل وحدة تعمل معًا بسلاسة عند دمجها مع بعضها. | اختبِر كل وحدة بشكل منفصل، فهذا هو الغرض من اختبارات الوحدة. |
اختبار سيناريوهات واقعية: استخدِم بيانات اختبار مستمَدة من بيانات واقعية. | استخدام بيانات اختبار مكرّرة يتم إنشاؤها تلقائيًا أو بيانات أخرى لا تعكس حالات الاستخدام في العالم الواقعي |
استخدِم النماذج الاختبارية والعناصر النموذجية للتبعيات الخارجية من أجل الحفاظ على التحكّم في الاختبار الكامل. | إنشاء تبعيات على خدمات تابعة لجهات خارجية، مثل طلبات الشبكة إلى الخدمات الخارجية |
استخدِم سلسلة إجراءات لتنظيف البيانات قبل كل اختبار وبعده. | لا تنسَ استخدام إجراءات التنظيف داخل اختباراتك، وإلا قد يؤدي ذلك إلى حالات تعذُّر إكمال الاختبار أو موجبات خاطئة، بسبب عدم عزل الاختبار بشكلٍ سليم. |
ما هي العناصر التي يجب أن تتضمّنها اختبارات الأداء الشاملة الجيدة؟
يجب أن يستوفي الاختبار الشامل والشامل ما يلي:
- تكرار تفاعلات المستخدمين
- أن تتضمّن سيناريوهات حيوية
- تغطي مجالات متعددة.
- إدارة العمليات غير المتزامنة
- التحقّق من النتائج
- مراعاة الأداء
ما تفعله ✅ | ما يجب تجنّبه ❌ |
---|---|
استخدام الاختصارات المستندة إلى واجهة برمجة التطبيقات مزيد من المعلومات | استخدِم تفاعلات واجهة المستخدم لكل خطوة، بما في ذلك عنصر الربط beforeEach . |
استخدِم سلسلة إجراءات لتنظيف البيانات قبل كل اختبار. يجب الانتباه أكثر إلى عزل الاختبار مقارنةً باختبارات الوحدة والدمج، لأنّ هناك خطرًا أكبر من حدوث تأثيرات جانبية. | لا تنسَ تنظيف المساحة بعد كل اختبار. إذا لم يتم تنظيف الحالة أو البيانات أو التأثيرات الجانبية المتبقية، ستؤثّر في الاختبارات الأخرى التي يتم تنفيذها لاحقًا. |
يجب اعتبار الاختبارات الشاملة كاختبارات للنظام. وهذا يعني أنّك بحاجة إلى اختبار حِزمة التطبيق بالكامل. | اختبِر كل وحدة بشكل منفصل، فهذا هو الغرض من اختبارات الوحدة. |
استخدِم قدرًا قليلاً من المحاكاة أو لا تستخدِم أي محاكاة داخل الاختبار. ننصحك بالتفكير جيدًا في ما إذا كنت تريد محاكاة التبعيات الخارجية. | الاعتماد بشكل كبير على النماذج التجريبية |
يجب مراعاة الأداء وعبء العمل، على سبيل المثال، من خلال عدم اختبار السيناريوهات الكبيرة بشكل مفرط في الاختبار نفسه. | تغطية سير العمل الكبير بدون استخدام اختصارات |