الاختبار القائم على الخصائص في Java: كسر الكود أسرع من Junit

مدرب بايثون أونلاين للمبتدئين

تعلم Python بسهولة دون إرهاق نظري. حل مهام عملية مع التحقق التلقائي واكتب الكود مباشرة في المتصفح.

ابدأ الدورة

الاختبار القائم على الخصائص في Java: عندما يحل اختبار واحد محل ألف اختبار

\n\n

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

\n\n

هذا النهج مفيد بشكل خاص لـ مطوري Java الذين يكتبون خوارزميات معقدة، أو يعملون مع المجموعات، أو المحللات اللغوية، أو الدوال الرياضية. في هذه المقالة، سنشرح كيفية دمج الاختبار القائم على الخصائص في مشروعك باستخدام مكتبة jqwik، وسنعرض أمثلة كود حقيقية.

\n\n

ما هو الاختبار القائم على الخصائص وكيف يختلف عن الاختبار التقليدي؟

\n\n

في النهج الكلاسيكي، تكتب:

\n\n
@Test\nvoid testAddition() {\n    assertEquals(4, Calculator.add(2, 2));\n    assertEquals(0, Calculator.add(-1, 1));\n}
\n\n

كل شيء جيد، حتى يقوم شخص ما بتمرير Integer.MAX_VALUE. أو null. أو رقم سالب كبير جدًا. الاختبار القائم على الخصائص يقلب المنطق: أنت لا تقول "أتوقع هذه النتيجة"، بل تقول "لأي بيانات إدخال صحيحة، النتيجة تحقق الخاصية X".

\n\n

على سبيل المثال، خاصية الجمع: add(a, b) == add(b, a) (التبديلية). أو add(a, 0) == a (العنصر المحايد). يقوم الإطار بتوليد آلاف الأزواج العشوائية a و b ويتحقق من عدم انتهاك الخاصية.

\n\n

المزايا الرئيسية لـ الاختبار القائم على الخصائص:

\n
    \n
  • توليد تلقائي لبيانات الاختبار — تجد أخطاء لم تفكر فيها حتى.
  • \n
  • تقليل عدد الاختبارات — اختبار خاصية واحد يحل محل عشرات الاختبارات القائمة على الأمثلة.
  • \n
  • التحقق من الحالات الحدودية — تستطيع المولدات إنشاء قيم "خطيرة" (0، null، سلاسل فارغة، أعداد كبيرة).
  • \n
  • التصغير (Shrinking) — إذا فشل الاختبار، يقوم الإطار بتقليل بيانات الإدخال إلى أبسط مثال يمكن إعادة إنتاج الخطأ فيه.
  • \n
\n\n

مكتبات الاختبار القائم على الخصائص في Java

\n\n

هناك عدة حلول ناضجة في السوق:

\n
    \n
  • jqwik — حديثة، خفيفة الوزن، تتكامل بشكل ممتاز مع JUnit 5. أوصي بها للبدء.
  • \n
  • QuickTheories — سريعة، ولكنها أقل شهرة.
  • \n
  • JUnit QuickCheck — فرع من أداة Scala القديمة، ولكن الدعم ضعيف.
  • \n
\n\n

سنستخدم jqwik، لأنه يحتوي على واجهة برمجة تطبيقات (API) الأكثر ملاءمة ووثائق ممتازة. أضف التبعية إلى pom.xml:

\n\n
<dependency>\n    <groupId>net.jqwik</groupId>\n    <artifactId>jqwik</artifactId>\n    <version>1.8.4</version>\n    <scope>test</scope>\n</dependency>
\n\n

أو لـ Gradle:

\n\n
testImplementation 'net.jqwik:jqwik:1.8.4'
\n\n

كتابة أول اختبار قائم على الخصائص في Java

\n\n

لنفترض أن لدينا دالة تعكس سلسلة نصية:

\n\n
public static String reverse(String s) {\n    if (s == null) return null;\n    return new StringBuilder(s).reverse().toString();\n}
\n\n

ما الخاصية التي يمكن التحقق منها؟ إذا قمت بعكس السلسلة مرتين، ستحصل على السلسلة الأصلية. هذه خاصية مثالية لـ الاختبار القائم على الخصائص.

\n\n
import net.jqwik.api.*;\nimport static org.assertj.core.api.Assertions.assertThat;\n\nclass StringProperties {\n                

المدونات

توصيات الكتب