الميزة الجيدة هي تقديم 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()));
شكرا على رفع هذا الموضوع.
أفضل ألا تضيف 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 في اختبارات الوحدة الخاصة بنا.