تعلم كتابة اختبارات الوحدة (Unit Testing) في جافا باستخدام JUnit: تحسين جودة التطبيقات

Amine
30/09/2024

ما هي اختبارات الوحدة (Unit Testing)؟

اختبارات الوحدة (Unit Testing) هي عملية اختبار الأجزاء الصغيرة من البرنامج (الوحدات) بشكل فردي للتحقق من أنها تعمل بشكل صحيح. تُعتبر هذه الاختبارات جزءًا أساسيًا من عملية تطوير البرمجيات، لأنها تساعد على اكتشاف الأخطاء في وقت مبكر وتحسين جودة التطبيق بشكل عام. في جافا، تُستخدم مكتبة JUnit على نطاق واسع لكتابة اختبارات الوحدة وإدارتها.

ما هو JUnit؟

JUnit هي مكتبة مفتوحة المصدر تُستخدم لكتابة وتشغيل اختبارات الوحدة في جافا. توفر JUnit مجموعة من الدوال والميزات لإنشاء الاختبارات والتحقق من صحة النتائج، مثل التحقق من القيم، استثناءات الأخطاء، وإعداد البيانات قبل الاختبار. يمكن دمج JUnit بسهولة مع أدوات إدارة المشاريع مثل Maven وGradle، ومع بيئات التطوير المتكاملة (IDEs) مثل IntelliJ IDEA وEclipse.

إعداد JUnit في مشروع جافا

للبدء في استخدام JUnit، تأكد من إضافته إلى مشروعك. إذا كنت تستخدم Maven، أضف التالي إلى ملف pom.xml:

<dependency>
   <groupId>org.junit.jupiter</groupId>
   <artifactId>junit-jupiter</artifactId>
   <version>5.7.0</version>
   <scope>test</scope>
</dependency>

إذا كنت تستخدم Gradle، أضف التالي إلى ملف build.gradle:

testImplementation 'org.junit.jupiter:junit-jupiter:5.7.0'

بمجرد إضافة المكتبة، يمكنك البدء في كتابة اختبارات الوحدة الخاصة بك باستخدام JUnit.

كتابة اختبار بسيط باستخدام JUnit

لإنشاء اختبار، تحتاج إلى كتابة فئة اختبار (Test Class) تحتوي على دوال اختبار (Test Methods). يتم استخدام التعليمة التوضيحية @Test لتحديد دوال الاختبار، ودوال التحقق assertEquals و assertTrue للتحقق من صحة النتائج. مثال:

import static org.junit.jupiter.api.Assertions.assertEquals;
import org.junit.jupiter.api.Test;

class CalculatorTest {

   @Test
   void testAddition() {
      Calculator calc = new Calculator();
      int result = calc.add(2, 3);
      assertEquals(5, result, "يجب أن يكون مجموع 2 و 3 هو 5");
   }
}

class Calculator {
   int add(int a, int b) {
      return a + b;
   }
}

في هذا المثال، قمنا بإنشاء فئة اختبار CalculatorTest واختبرنا دالة add للتحقق من أن مجموع 2 و 3 هو 5. استخدمنا assertEquals للتحقق من صحة النتيجة.

شرح الكود:

  • assertEquals(5, result, "يجب أن يكون مجموع 2 و 3 هو 5"): تتحقق من أن القيمة الفعلية result تساوي 5.
  • @Test: تحدد أن هذه الدالة هي دالة اختبار.
  • إذا كانت النتيجة صحيحة، يمر الاختبار. إذا كانت النتيجة غير صحيحة، سيفشل الاختبار.

إنشاء اختبارات متقدمة باستخدام JUnit

يمكنك استخدام JUnit لكتابة اختبارات أكثر تعقيدًا باستخدام ميزات مثل:

  • اختبار الاستثناءات (Exception Testing): للتحقق من أن الكود يقوم بإطلاق الاستثناءات بشكل صحيح عند حدوث خطأ.
  • إعداد البيانات قبل وبعد الاختبار: باستخدام التعليمات التوضيحية @BeforeEach و @AfterEach.
  • الاختبارات المتكررة (Repeated Tests): لتنفيذ نفس الاختبار عدة مرات باستخدام @RepeatedTest.

اختبار الاستثناءات (Exception Testing)

يمكنك التحقق من أن الكود يقوم بإطلاق الاستثناءات بشكل صحيح باستخدام الدالة assertThrows. مثال:

import static org.junit.jupiter.api.Assertions.assertThrows;
import org.junit.jupiter.api.Test;

class CalculatorTest {

   @Test
   void testDivisionByZero() {
      Calculator calc = new Calculator();
      assertThrows(ArithmeticException.class, () -> calc.divide(5, 0), "يجب أن يطلق قسمة على صفر استثناء");
   }
}

class Calculator {
   int divide(int a, int b) {
      return a / b;
   }
}

في هذا المثال، قمنا باختبار دالة divide للتحقق من أنها تطلق استثناء عند قسمة عدد على صفر. استخدمنا assertThrows للتحقق من أن ArithmeticException يتم إطلاقه.

إعداد البيانات قبل وبعد الاختبار

يمكنك إعداد البيانات قبل بدء الاختبار أو تنظيفها بعد انتهاء الاختبار باستخدام التعليمات التوضيحية @BeforeEach و @AfterEach. مثال:

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Test;

class CalculatorTest {
   Calculator calc;

   @BeforeEach
   void setUp() {
      calc = new Calculator();  // إنشاء كائن قبل كل اختبار
   }

   @AfterEach
   void tearDown() {
      calc = null;  // إعادة التهيئة بعد كل اختبار
   }

   @Test
   void testAddition() {
      int result = calc.add(2, 3);
      assertEquals(5, result);
   }
}

class Calculator {
   int add(int a, int b) {
      return a + b;
   }
}

في هذا المثال، استخدمنا @BeforeEach لإنشاء كائن جديد من الفئة Calculator قبل كل اختبار، و @AfterEach لإعادة التهيئة بعد انتهاء كل اختبار.

اختبارات الوحدة المتكررة (Repeated Tests)

إذا كنت ترغب في تنفيذ نفس الاختبار عدة مرات، يمكنك استخدام التعليمة التوضيحية @RepeatedTest. مثال:

import org.junit.jupiter.api.RepeatedTest;

class CalculatorTest {

   @RepeatedTest(5)  // تكرار الاختبار 5 مرات
   void testRepeatedAddition() {
      Calculator calc = new Calculator();
      int result = calc.add(2, 3);
      assertEquals(5, result);
   }
}

class Calculator {
   int add(int a, int b) {
      return a + b;
   }
}

في هذا المثال، يتم تنفيذ دالة testRepeatedAddition خمس مرات للتحقق من أن دالة add تعمل بشكل صحيح في كل مرة.

مقارنة بين JUnit 4 و JUnit 5

JUnit 5 هو الإصدار الأحدث من JUnit، ويوفر ميزات جديدة وتحسينات مقارنة بالإصدار السابق JUnit 4. بعض الاختلافات الرئيسية تشمل:

  • JUnit 5: يتكون من ثلاثة مكونات رئيسية: JUnit Platform، JUnit Jupiter، و JUnit Vintage. يوفر ميزات جديدة مثل @BeforeEach و @AfterEach.
  • JUnit 4: يستخدم التعليمات التوضيحية @Before و @After، ولا يدعم بعض الميزات المتقدمة الموجودة في JUnit 5.

تمرين (مستوى متوسط): كتابة اختبارات وحدة لتطبيق حسابي

في هذا التمرين، سنقوم بكتابة اختبارات وحدة لتطبيق حسابي يحتوي على الدوال add، subtract، multiply، و divide. سنختبر جميع الدوال ونتأكد من أنها تعمل بشكل صحيح.

المتطلبات:

  • إنشاء فئة Calculator تحتوي على الدوال الأربعة.
  • كتابة اختبارات لكل دالة باستخدام JUnit.
  • التحقق من صحة النتائج باستخدام assertEquals و assertThrows.

الكود:

import static org.junit.jupiter.api.Assertions.*;
import org.junit.jupiter.api.Test;

class CalculatorTest {

   Calculator calc = new Calculator();

   @Test
   void testAddition() {
      assertEquals(7, calc.add(3, 4), "يجب أن يكون مجموع 3 و 4 هو 7");
   }

   @Test
   void testSubtraction() {
      assertEquals(1, calc.subtract(5, 4), "يجب أن يكون ناتج طرح 5 من 4 هو 1");
   }

   @Test
   void testMultiplication() {
      assertEquals(20, calc.multiply(5, 4), "يجب أن يكون ناتج ضرب 5 في 4 هو 20");
   }

   @Test
   void testDivision() {
      assertEquals(5, calc.divide(20, 4), "يجب أن يكون ناتج قسمة 20 على 4 هو 5");
   }

   @Test
   void testDivisionByZero() {
      assertThrows(ArithmeticException.class, () -> calc.divide(10, 0), "يجب أن يطلق قسمة على صفر استثناء");
   }
}

class Calculator {
   int add(int a, int b) {
      return a + b;
   }

   int subtract(int a, int b) {
      return a - b;
   }

   int multiply(int a, int b) {
      return a * b;
   }

   int divide(int a, int b) {
      return a / b;
   }
}

شرح الكود:

  • قمنا بإنشاء فئة Calculator تحتوي على الدوال الأربعة (add، subtract، multiply، divide).
  • أنشأنا اختبارات لكل دالة للتحقق من صحة النتائج.
  • اختبرنا استثناء ArithmeticException عند قسمة عدد على صفر.

جرّب تنفيذ هذا البرنامج بنفسك، وشارك نتيجتك معنا في التعليقات! إذا واجهتك أي مشكلة أو كان لديك سؤال، لا تتردد في طرحه.

خاتمة

في هذا الدرس، تعرفنا على كيفية كتابة اختبارات الوحدة (Unit Testing) في جافا باستخدام JUnit. تعلمنا كيفية كتابة اختبارات بسيطة، التحقق من صحة النتائج، واختبار الاستثناءات. نوصي بممارسة التمرين المقدم لاكتساب المزيد من الخبرة في كتابة اختبارات الوحدة. لا تنسَ ترك تعليق أو مشاركة هذا الدرس مع أصدقائك على وسائل التواصل الاجتماعي إذا وجدته مفيدًا!

التعليقات

اترك تعليقاً