يختبر معظم المبتدئين برنامجهم بتشغيله يدويًا والنظر إلى النتيجة، وهذا ينجح في المشروع الصغير ثم ينهار حين يكبر، فكل تعديل قد يكسر شيئًا بعيدًا لا تنتبه له. والاختبارات الآلية كود يتحقق من سلوك كودك تلقائيًا في ثوانٍ. نشرح هنا الأنواع والبدء العملي.

لماذا تكتب اختبارات؟
قد تبدو الاختبارات وقتًا ضائعًا في البداية، لكن فوائدها تظهر سريعًا:
ثقة عند التعديل: تغير الكود فتتأكد خلال ثوانٍ أنك لم تكسر ما كان يعمل. وبدونها يصبح كل تعديل مخاطرة فيتجنبه الفريق.
اكتشاف الأخطاء مبكرًا: الخطأ الذي يظهر في اختبار محلي أرخص بكثير من الذي يظهر عند عميل.
توثيق حي: الاختبار يبين كيف يفترض أن يعمل الكود، وهو لا يتقادم لأن فشله ينبه.
تصميم أفضل: الكود الصعب اختباره غالبًا شديد الترابط، فيدفعك الاختبار إلى تقسيمه.
شبكة أمان لإعادة الهيكلة: تحسن الكود بشجاعة لأن لديك ما يكشف الكسر.
تسريع العمل على المدى المتوسط: تكلفة الكتابة تقابلها ساعات تنقيح موفرة، وإن كانت النسبة تختلف بين المشاريع ولا نملك رقمًا عاميًا موثقًا.
متطلب في الشركات: كثير من الفرق تشترط اختبارات قبل الدمج، فهي مهارة مطلوبة في الوظائف.
ما أنواع الاختبارات؟
يتدرج الاختبار من الصغير السريع إلى الكبير الشامل، ولكل مستوى دور:
اختبارات الوحدة (Unit): تختبر دالة أو وحدة صغيرة بمعزل عن غيرها. سريعة ودقيقة، وتشكل الأغلبية في معظم المشاريع.
اختبارات التكامل (Integration): تختبر عمل أجزاء معًا، كدالة مع قاعدة بيانات حقيقية أو مسار في الواجهة البرمجية. أبطأ لكنها تكشف مشكلات الوصل بين الأجزاء.
اختبارات الطرف للطرف (End-to-End): تحاكي مستخدمًا حقيقيًا يتنقل في التطبيق عبر المتصفح، بأدوات مثل Playwright أو Cypress. أقرب للواقع وأبطأ وأكثر هشاشة، فاستعملها للمسارات الحرجة فقط.
اختبارات القبول: تتحقق من أن النظام يحقق متطلبات العمل، وتكتب أحيانًا بلغة قريبة من وصف الأعمال.
اختبارات الأداء والحمل: تقيس الاستجابة تحت ضغط، وتكشف الاختناقات قبل الإنتاج.
اختبارات الأمان: فحوص آلية للثغرات المعروفة، لا تغني عن مراجعة بشرية.
الاختبار اليدوي والاستكشافي: لا يزال مهمًا لاكتشاف ما لم تتوقع، ولتقييم التجربة.
هرم الاختبار: فكرة شائعة تقول أكثر من الصغيرة السريعة وأقل من الكبيرة البطيئة. هي إرشاد لا قاعدة جامدة.
كيف تكتب أول اختبار؟
الأدوات تختلف بين اللغات لكن الفكرة واحدة: ثلاث خطوات واضحة.
اختر أداة اختبار: pytest في بايثون، وJest أو Vitest في جافاسكربت، وJUnit في جافا، وغيرها. وتأتي أغلب الأطر مع أدوات جاهزة.
صيغة الترتيب-التنفيذ-التحقق (Arrange-Act-Assert): جهز المدخلات، ونفذ الدالة، ثم تحقق من النتيجة المتوقعة. وهذا يجعل كل اختبار مقروءًا.
مثال: دالة تحسب الخصم: ترسل سعر 100 ونسبة 10%، وتتوقع 90. ثم تضيف حالات: نسبة صفر، ونسبة 100، ونسبة سالبة ترفض.
اسم الاختبار يوضح السيناريو: مثل «يرفض الخصم السالب»، فإذا فشل عرفت المشكلة من الاسم.
اختبار واحد لفكرة واحدة: حين يفشل اختبار طويل يتحقق من عشرة أشياء لا تعرف أيها السبب.
شغّل الاختبار ورَ فشله أولًا: اختبار لم تره يفشل قد لا يختبر شيئًا. وهذه فكرة التطوير بالاختبار (TDD) المبسطة.
شغّلها كثيرًا: بأمر واحد أو تلقائيًا عند حفظ الملفات، فتتحول إلى عادة.
ماذا تختبر وماذا تتجنب؟
لا يمكن اختبار كل شيء، والمهارة في اختيار ما يستحق:
المنطق الجوهري أولًا: حسابات الأسعار وقواعد الصلاحيات والتحقق من البيانات، فأخطاؤها الأعلى كلفة.
الحالات الحدية: القوائم الفارغة والقيم الصفرية والنصوص الطويلة والتواريخ الغريبة، فهي مكمن كثير من الأخطاء.
الأخطاء المعروفة: عند إصلاح خطأ، اكتب اختبارًا يعيد إنتاجه أولًا ثم أصلحه، فلا يعود دون إنذار.
السلوك لا التنفيذ: اختبر ما تفعله الدالة لا كيف تفعله، وإلا انكسرت اختباراتك عند كل إعادة هيكلة.
تجنب اختبار المكتبات: لا تختبر أن الإطار يعمل، اختبر كودك.
لا تلاحق نسبة التغطية: رقم التغطية يخبرك ما لم يُختبر لا أن ما اختُبر جيد. وتغطية 100% باختبارات ضعيفة وهم.
حدد المسارات الحرجة: تسجيل الدخول والدفع وإنشاء الحساب تستحق اختبار طرف للطرف.
راجع الاختبارات كما تراجع الكود: اختبار غامض أو مكرر دَين تقني أيضًا.
كيف تعزل الاعتماديات بالمحاكاة؟
حين يعتمد كودك على شبكة أو قاعدة بيانات أو ساعة النظام، يصبح الاختبار بطيئًا وغير متوقع:
المحاكيات (Mocks) والبدائل (Stubs): كائنات تحل محل التبعية الحقيقية وتعيد ردودًا محددة، فتختبر منطقك وحده.
حقن التبعيات: مرر التبعيات إلى الدالة أو الصنف بدل إنشائها داخله، فيسهل استبدالها في الاختبار.
لا تفرط في المحاكاة: اختبار كله محاكيات قد يمر وتفشل الحقيقة. وازن مع اختبارات تكامل تستعمل قاعدة حقيقية.
الزمن والعشوائية: ثبّت الساعة والقيم العشوائية في الاختبار لتكون النتائج قابلة للتكرار.
قواعد بيانات الاختبار: استعمل قاعدة منفصلة أو حاوية مؤقتة، وانظفها بين الاختبارات.
البيانات الاختبارية: أنشئها بدوال مساعدة (Factories) بدل نسخ ولصق كائنات طويلة.
استقلال الاختبارات: كل اختبار يجب أن ينجح وحده وبأي ترتيب. فالاعتماد على نتائج اختبار سابق يخلق فشلًا متقطعًا.
الاختبارات المتقلبة (Flaky): التي تنجح أحيانًا وتفشل أحيانًا تفقد الثقة. عالجها بسرعة أو عطلها مؤقتًا بعلامة وسبب.
كيف تدمج الاختبارات في عملك اليومي؟
قيمة الاختبارات تتحقق حين تصير جزءًا من العمل لا نشاطًا منفصلًا:
تشغيل تلقائي: في التكامل المستمر عند كل طلب دمج، ويُمنع الدمج عند الفشل.
ابدأ صغيرًا: إن كان مشروعك بلا اختبارات، فأضف اختبارًا عند كل خطأ تصلحه وكل ميزة جديدة، بدل محاولة تغطية الماضي كله.
سرعة الاختبارات: إن استغرقت دقائق، تجنبها المطورون. افصل البطيئة وشغلها أقل تكرارًا.
رسائل فشل مفيدة: تظهر القيمة المتوقعة والفعلية بوضوح.
اجعلها تجربة جماعية: اتفقوا على عرف تسمية وبنية مجلدات، وراجعوا الاختبارات في المراجعات.
تعلم من الفشل: حين يفلت خطأ إلى الإنتاج، اسأل لماذا لم تكشفه اختباراتنا؟ وسد الثغرة.
وازن بين الكلفة والفائدة: نموذج أولي سيُرمى بعد أسبوع لا يحتاج إلى مجموعة اختبارات كاملة.
اقرأ التوثيق الرسمي لأداتك: فهو يشرح مزاياها كالتجهيز والتفكيك والاختبارات المعلمة.
أسئلة شائعة عن الاختبارات الآلية
هل أبدأ بالاختبار أم بالكود؟
كلاهما مقبول. بعض الناس يفضلون كتابة الاختبار أولًا (TDD)، وآخرون يكتبونه بعد الكود. المهم أن تكتبه وأن يكون مفيدًا.
كم نسبة التغطية المطلوبة؟
لا رقم سحري. بعض الفرق تحدد حدًا أدنى كمؤشر، لكن الأهم تغطية المسارات الحرجة بجودة. لا تجعل النسبة هدفًا بحد ذاتها.
هل تغني الاختبارات عن التنقيح؟
لا، لكنها تقلل الحاجة إليه وتحدد موضع الخطأ بسرعة. ستحتاج التنقيح لمشكلات لم تتوقعها.
0 تعليقات