Junit4: يقدم التسلسل الهرمي BiMatcher

تم إنشاؤها على ٨ فبراير ٢٠١٨  ·  9تعليقات  ·  مصدر: junit-team/junit4

الميزة الجيدة هي تقديم BiMatcher التسلسل الهرمي (تناظري org.hamcrest.Matcher ، لكن يستهلك 2 args). بدلاً من ذلك ، يمكن استخدام Comparator القياسي لهذا الغرض. يمكن أيضًا استخدام BiPredicate (سيؤدي هذا إلى ربط JUnit بجافا 8 ، ولكنه سيضيف منطق AND / OR / NOT خارج الصندوق).
بضع ملاحظات لجميع التعليمات البرمجية الإضافية:

  • سيتم استخدام أسماء BiMatcher و BiPredicate و Comparator بالتبادل.
  • كل التعليمات البرمجية ليست نهائية وهي مجرد فكرة عامة.

الطرق الرئيسية لإضافة فئة Assert :

  • assertThat(T expected, T actual, Comparator<T> biMatcher);
  • assertThat(String message, T expected, T actual, Comparator<T> biMatcher); (ربما ليس ضروريًا ، انظر أدناه).
  • طرق متعددة assertArray() (انظر أدناه).

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

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

مع قدرات JUnit الحالية سيبدو كما يلي:
أقصر:

for (int i = 0; i < elements.length - 1; i++) {
  if (checkSame) { // Same
    assertSame("elements must be the same.", elements[i], elements[i + 1]);
  } else { // Not same
    assertNotSame("elements must be not the same.", elements[i], elements[i + 1]);
  }
}

أداء أفضل (لكن من يهتم بالأداء في الاختبارات):

if (checkSame) { // Same
  for (int i = 0; i < elements.length - 1; i++) {
    assertSame("elements must be the same.", elements[i], elements[i + 1]);
  }
else { // Not same
  for (int i = 0; i < elements.length - 1; i++) {
    assertNotSame("elements must be not the same.", elements[i], elements[i + 1]);
  }
}

يمكننا أيضًا تنفيذ Comparator واستخدام assertTrue()/assertFalse() ، لكن كود إنشاء المقارنات سيكون كبيرًا أيضًا (ما لم نستخدم lambdas).

مع رمز النهج الجديد سيبدو أقصر وأنظف بكثير بالنسبة لي ، مثل هذا:

Comparator<T> comparator = checkSame ? BiMatchers.same() : BiMatchers.notSame();
String message = checkSame ? "elements must be the same." : "elements must be not the same.";
for (int i = 0; i < elements.length - 1; i++) {
  assertThat(message, elements[i], elements[i + 1], comparator);
}

لجعلها أقصر ، يمكننا تمديد Comparator إلى MessagedComparator مع خاصية message اختيارية ، لذلك ستأخذها JUnit من هناك بطريقة ما. مثله:

MessagedComparator<T> comparator = checkSame ? BiMatchers.same("elements must be the same.") : BiMatchers.notSame("elements must be not the same.");
for (int i = 0; i < elements.length - 1; i++) {
  assertThat(message, elements[i], elements[i + 1], comparator);
}

العواقب بعيدة المدى:
1) ستكون فئة Assert مرنة جدًا بشكل عام ، لأنه يمكنك استخدام أي مقارن قياسي أو مقارن خاص بدون الكثير من التعليمات البرمجية.
2) نتيجة لما سبق ، يمكن استخدام لامدا بسهولة أكبر لحقن أي شروط.
3) يمكن إضافة تسلسل منطقي إضافي (AND ، OR ، NOT) خارج الصندوق (شيء مشابه لـ org.hamcrest.CoreMatchers ). مطلوب حاليًا طريقة جديدة لأي ميزة مصغرة جديدة ، على سبيل المثال assertNotSame() بجانب assertSame() إلخ. أو مرة أخرى نحتاج إلى طرق assertTrue()/assertFalse() .
4) يمكن إعادة هيكلة فئة Assert بالكامل إلى نموذج موحد. مجرد مثال واحد:

public static void assertSame(String message, Object expected, Object actual) {
  assertThat(message, expected, actual, BiMatchers.same())
}

public static void assertThat(String message, T expected, T actual, Comparator<T> biMatcher) {
...
}

أو كما سبق ذكره:

public static void assertSame(String message, Object expected, Object actual) {
  assertThat(expected, actual, BiMatchers.same(message))
}

public static void assertThat(T expected, T actual, MessagedComparator<T> biMatcher) {
...
}

5) يمكن إضافة طرق assertArray() (وبالتالي إعادة بناء الطرق القديمة). على سبيل المثال:

public static void assertArrayEquals(boolean[] expecteds, boolean[] actuals) {
  assertArray(expecteds, actuals, BiMatchers.equals());
}

public static void assertArray(boolean[] expecteds, boolean[] actuals, Comparator<Boolean>) {
...
}

لذلك على سبيل المثال ، يمكنك التحقق من أن جميع العناصر في صفيفتين متطابقة بسهولة:

Assert.assertArray(array1, array2, BiMatchers.same());

يمكن أيضًا التحكم في طول المصفوفة أو عمليات التحقق الأخرى بشكل منفصل. كود مزيف:

Assert.assertArray(array1, array2, and(sameLength(), same()));

ال 9 كومينتر

شكرا على رفع هذا الموضوع.

أفضل ألا تضيف JUnit 4.x المزيد من DSLs التوكيدية. من الصعب حقًا الحصول على DSL صحيحًا ومرنًا ، ولست متأكدًا من أنه من المنطقي قضاء الوقت والجهد في ذلك في JUnit عندما تكون هناك أطر تأكيد جيدة لجهات خارجية مثل Truth أو Fest.

أيضًا ، يجب أن تنتقل الميزات التي تتطلب Java 8 إلى http://github.com/junit-team/junit5

gitIvanB شكرا لفتح العدد. مثل kcooney ، أعتقد أيضًا أنه من الأفضل معالجة ذلك من خلال مكتبة التأكيد ، مثل AssertJ.

kcooney ، marcphilipp ، شكرًا على التلميح. يبدو أن استخدام libs التوكيد هو أفضل ممارسة هنا.
سؤال إضافي واحد. هل يمكنني استخدام كقاعدة عامة أن استخدام Assert متوقف (أو لا ينصح به)؟ خاصة مع مراعاة الترقية المستقبلية المحتملة من JUnit-4 إلى JUnit-5.

gitIvanB السؤال غير واضح بعض الشيء. في حالة التطوير مقابل junit4 ، يستخدم الفرد org.junit.Assert ، وإذا كان التطوير مقابل junit5 ، فسيتم استخدام org.junit.jupiter.api.Assertions

الأسلوب الموصى به هو استيراد طرق منه بشكل ثابت ، لتجنب وجود Assert. في كل سطر.

gitIvanB يجب عليك بالتأكيد عدم استخدام junit.framework.Assert ، لكن org.junit.Assert جيد. عندما تقوم بالترقية ، يمكنك استخدام IDE لتحويل تأكيدات JUnit 4 إلى JUnit Jupiter (IDEA تدعمها بالفعل). الاختلاف الأكبر هو أن معلمة الرسالة الاختيارية تأتي أولاً في JUnit 4 ولكنها تأتي أخيرًا في كوكب المشتري. بدلاً من ذلك ، يمكنك أن تقرر استخدام مكتبة تأكيدات مختلفة الآن والاستمرار في استخدامها عند الانتقال من Vintage إلى Jupiter.

panchenko ، marcphilipp لذا كما فهمت ، فإن JUnit-4 org.junit.Assert مغلق ولن يتم إثرائه بأساليب جديدة. في JUnit-5 ، أحتاج إلى استخدام إما org.junit.jupiter.api.Assertions (كبديل لـ org.junit.Assert ) أو بعض أدوات التأكيد.
أحتاج إلى بعض الوقت لتعلم JUnit-5 ، ولكن من النظرة الأولى إلى org.junit.jupiter.api.Assertions يبدو أن نهجها بشكل عام يشبه org.junit.Assert . لذا فهي فرصة كبيرة أن أحتاج إلى إنشاء تذكرة مماثلة لـ JUnit-5 :) أعتقد أنه يجب على JUnit-5 إما تقديم تأكيدات كاملة أو تفويض كامل لمراجع التأكيد.

تكمن فلسفة

للتأكيدات ، هناك العديد من المشاريع التي تقدم مجموعة أكثر ثراءً من التأكيدات ، أحيانًا بطريقة قابلة للتوسيع.
على سبيل المثال ، هناك Google Truth (https://github.com/google/truth) و FEST (https://github.com/alexruiz/fest-assert-2.x) و AssertJ (http: // joel- costigliola.github.io/assertj/) و Hamcrest (http://hamcrest.org/JavaHamcrest/).

نظرًا لوجود العديد من مكتبات التأكيد المدهشة هناك ، فقد كنت مترددًا في قبول طلبات الميزات الجديدة مقابل org.junit.Assert . لن أعتبرها مجمدة (على الرغم من أنني سأعتبر junit.framework.Assert مجمدة). في الواقع ، سيقدم 4.13 assertThrows . ولكن نظرًا لأننا لن نحظى أبدًا بمجموعة غنية من التأكيدات مثل تلك المشاريع ، فإننا نشعر بالراحة في توفير الأساسيات.

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

لا يمكنني التحدث عن JUnit5 ، لكني أتخيل أن المطورين الأصليين شعروا أنهم لا يستطيعون إطلاق الجيل التالي من JUnit بدون أساس جيد لأساليب التأكيد (أو ربما شعروا بأنهم أفضل طريقة لضمان عمل إطار العمل الجديد و كان المصقول لاختبار JUnit5 باستخدام JUnit5). تسببت ممارسات البرمجة الجديدة في اتخاذهم قرارات مختلفة بشأن الشكل الذي ستبدو عليه واجهة برمجة التطبيقات الأساسية للتأكيد عما فعلته كينت وإريش وديفيد ، لذلك سترى بعض الاختلافات. لكن من المحتمل ألا ترى في JUnit مجموعة غنية من التأكيدات كما هو الحال مع Hamcrest أو DSL القابل للتوسيع مثل Truth.

أترك الأمر لفريق JUnit5 لتحديد أنواع التغييرات التي سينظرون فيها. إذا كنت تشعر بقوة أن ملف
تعتبر الطرق التي تقترحها مهمة كأساس لكتابة اختبارات جيدة ، فلا تتردد في إنشاء مشكلة هناك.

عندما بدأنا العمل على JUnit 5 (الاسم الرمزي "JUnit Lambda" في ذلك الوقت) ، ناقشنا نطاق ما أردنا تحقيقه. تم تحديد كتابة نوع جديد من مكتبة التأكيد بشكل صريح بحيث لا تدخل ضمن النطاق.

أو كما يوضح دليل مستخدم JUnit 5 :

على الرغم من أن تسهيلات التأكيد التي يوفرها JUnit Jupiter كافية للعديد من سيناريوهات الاختبار ، إلا أن هناك أوقاتًا تكون فيها الطاقة والوظائف الإضافية مثل المطابقات مطلوبة أو مطلوبة. في مثل هذه الحالات ، يوصي فريق JUnit باستخدام مكتبات التأكيد التابعة لجهات خارجية مثل AssertJ و Hamcrest و Truth وما إلى ذلك. وبالتالي ، يتمتع المطورون بحرية استخدام مكتبة التأكيد التي يختارونها.

لذلك ، لم يتم تجميده أيضًا ، لكن الهدف مشابه لما في JUnit 4 ، وهو توفير مجموعة أساسية من التأكيدات لبدء المستخدمين. حتى أننا نستخدم AssertJ في اختبارات الوحدة الخاصة بنا.

هل كانت هذه الصفحة مفيدة؟
0 / 5 - 0 التقييمات