كيفية إجراء الاختبارات الوحدوية في Python باستخدام unittest

تمت الكتابة بواسطة: عبد الحكيم

تارخ آخر تحديث: 10 سبتمبر 2024

محتوى المقال

كيفية إجراء الاختبارات الوحدوية في Python باستخدام unittest

تعتبر الاختبارات الوحدوية (Unit Tests) جزءًا أساسيًا من عملية تطوير البرمجيات، حيث تساعد المطورين في التحقق من أن الوحدات الفردية (مثل الدوال أو الكلاسات) تعمل كما هو متوقع. في لغة البرمجة Python، تعد مكتبة unittest واحدة من الأدوات الأساسية التي تمكن المطورين من كتابة اختبارات وحدوية بطريقة منظمة وسهلة الاستخدام. في هذا المقال، سنتعرف على كيفية استخدام مكتبة unittest لإجراء الاختبارات الوحدوية، وسنستعرض أمثلة عملية على ذلك.

لماذا تعتبر الاختبارات الوحدوية مهمة؟

الاختبارات الوحدوية تساعد في ضمان أن كل جزء من الكود يعمل بشكل صحيح كما هو متوقع. بالإضافة إلى ذلك، تسهم هذه الاختبارات في تحسين جودة البرمجيات من خلال:

  • اكتشاف الأخطاء والمشاكل في وقت مبكر من دورة حياة التطوير.
  • توفير توثيق ضمني للكود عن طريق وصف كيفية توقع عمل الوحدات الفردية.
  • تسهيل عملية إعادة كتابة الكود أو تحسينه (Refactoring) دون الخوف من كسر شيء ما.
  • ضمان استقرار الكود على المدى الطويل عند إدخال تغييرات أو تحسينات جديدة.

تثبيت واستخدام مكتبة unittest

تأتي مكتبة unittest مدمجة مع Python، مما يعني أنك لست بحاجة إلى تثبيتها بشكل منفصل. يمكنك بدء استخدام unittest مباشرة بكتابة الاختبارات في ملفات Python الخاصة بك.

import unittest

class TestStringMethods(unittest.TestCase):
    def test_upper(self):
        self.assertEqual('foo'.upper(), 'FOO')

    def test_isupper(self):
        self.assertTrue('FOO'.isupper())
        self.assertFalse('Foo'.isupper())

    def test_split(self):
        s = 'hello world'
        self.assertEqual(s.split(), ['hello', 'world'])

        with self.assertRaises(TypeError):
            s.split(2)

if __name__ == "__main__":
    unittest.main()

في هذا المثال، نقوم بكتابة ثلاثة اختبارات بسيطة للتحقق من وظائف سلسلة نصية (String). الدالة test_upper() تتحقق من أن الدالة upper() تحول النص إلى حروف كبيرة، بينما تتحقق الدالة test_isupper() من أن النص يتكون بالكامل من حروف كبيرة. أما الدالة test_split() فتتحقق من أن الدالة split() تقوم بتقسيم النص بشكل صحيح.

كيفية تشغيل الاختبارات

لتشغيل الاختبارات التي كتبتها باستخدام unittest، يمكنك استخدام سطر الأوامر (Command Line) ببساطة، عن طريق تنفيذ الملف الذي يحتوي على الاختبارات:

$ python test_example.py

سيقوم unittest بتشغيل جميع الدوال التي تبدأ بــ test_ ويعرض النتائج. إذا كانت جميع الاختبارات ناجحة، ستظهر رسالة OK، وإلا سيتم عرض معلومات حول الاختبارات التي فشلت.

أمثلة متقدمة في كتابة الاختبارات

بينما يعتبر المثال السابق بسيطًا، هناك العديد من المميزات المتقدمة التي يوفرها unittest مثل إعداد الاختبارات وتفكيكها (Setup and Teardown)، واستخدام التوكيلات الوهمية (Mocking)، وإجراء اختبارات متعددة الجوانب (Parameterized Tests).

إعداد وتفكيك الاختبارات

يمكنك استخدام الدوال setUp() و tearDown() لتنفيذ أكواد معينة قبل وبعد كل اختبار. على سبيل المثال، قد ترغب في إعداد بعض البيانات أو الموارد المشتركة للاختبارات:

import unittest

class TestDatabase(unittest.TestCase):
    def setUp(self):
        # إنشاء اتصال بقاعدة البيانات
        self.connection = create_connection()

    def tearDown(self):
        # إغلاق الاتصال بقاعدة البيانات
        self.connection.close()

    def test_insert(self):
        # اختبار إدخال بيانات في قاعدة البيانات
        self.assertTrue(insert_data(self.connection, data))

if __name__ == "__main__":
    unittest.main()

في هذا المثال، نستخدم setUp() لإعداد الاتصال بقاعدة البيانات قبل كل اختبار، وtearDown() لإغلاق الاتصال بعد انتهاء الاختبار. هذا يضمن أن جميع الاختبارات التي تتطلب الاتصال بقاعدة البيانات يمكن أن تعتمد على نفس بيئة الإعداد.

استخدام التوكيلات الوهمية (Mocking)

في بعض الأحيان، قد تحتاج إلى محاكاة (Mock) بعض الدوال أو الكائنات أثناء الاختبار. هذا يكون مفيدًا عندما ترغب في اختبار وحدة دون الاعتماد على الوحدات الخارجية مثل قواعد البيانات أو واجهات برمجة التطبيقات الخارجية.

from unittest import mock

class TestPayment(unittest.TestCase):
    @mock.patch('payment_gateway.charge')
    def test_charge(self, mock_charge):
        mock_charge.return_value = True

        self.assertTrue(process_payment(amount))

if __name__ == "__main__":
    unittest.main()

في هذا المثال، نقوم بمحاكاة الدالة charge() الخاصة ببوابة الدفع للتأكد من أن دالة process_payment() تعمل بشكل صحيح دون الحاجة إلى تنفيذ العملية الفعلية.

أفضل الممارسات في كتابة الاختبارات الوحدوية

لكتابة اختبارات وحدوية فعالة في Python، هنا بعض النصائح التي يمكنك اتباعها:

  • اجعل الاختبارات بسيطة ومركزة: يجب أن يختبر كل اختبار وظيفة أو سلوك واحد فقط. هذا يسهل تحديد مصدر الخطأ عند فشل الاختبار.
  • استخدم أسماء واضحة للدوال: اختر أسماء تصف بوضوح ما يفعله الاختبار، مثل test_addition_of_two_numbers().
  • قم بتغطية الحالات الحديّة: تأكد من اختبار الحالات التي يمكن أن تسبب مشاكل، مثل القيم الصفرية أو القيم الكبيرة جدًا.
  • تحقق من الأداء: في بعض الحالات، قد تحتاج إلى التحقق من أداء الكود، خاصة إذا كان الكود يعتمد على الحلقات أو العمليات المكثفة.
  • اجعل الاختبارات مستقلة: لا تعتمد على نتائج اختبارات أخرى، كل اختبار يجب أن يكون قادرًا على العمل بمفرده.

الخلاصة

تعتبر مكتبة unittest أداة قوية ومرنة لإجراء الاختبارات الوحدوية في Python. من خلال اعتماد أفضل الممارسات وفهم كيفية استخدام الميزات المختلفة مثل إعداد وتفكيك الاختبارات، واستخدام التوكيلات الوهمية، يمكنك تحسين جودة كودك وضمان استقراره على المدى الطويل. تأكد من أن تجعل الاختبارات جزءًا أساسيًا من عملية التطوير، وسترى الفوائد الكبيرة التي تجنيها من ذلك.

طور مهاراتك: مقالات يجب قراءتها في البرمجة