מדריך לכללי JUnit 4

1. סקירה כללית

במדריך זה, אנו נסתכל על תכונת הכללים המסופקת על ידי ספריית JUnit 4.

נתחיל בהכנסת מודל הכללים של JUnit לפני שעבר על כללי הבסיס החשובים ביותר שמספקים ההפצה. בנוסף, נראה גם כיצד לכתוב ולהשתמש בכלל JUnit המותאם אישית שלנו.

למידע נוסף על בדיקות עם JUnit, עיין בסדרת JUnit המקיפה שלנו.

שים לב שאם אתה משתמש ב- JUnit 5, הכללים הוחלפו במודל Extension.

2. מבוא לכללי JUnit 4

כללי JUnit 4 מספקים מנגנון גמיש לשיפור הבדיקות על ידי הפעלת קוד כלשהו סביב ביצוע מקרה הבדיקה. במובן מסוים, זה דומה שיש @לפני ו @לאחר ביאורים בכיתת הבדיקה שלנו.

בואו נדמיין שרצינו להתחבר למשאב חיצוני כמו בסיס נתונים במהלך הגדרת הבדיקה ואז לסגור את החיבור לאחר סיום הבדיקה שלנו. אם ברצוננו להשתמש במסד נתונים זה במספר בדיקות, בסופו של דבר נשכפל קוד זה בכל בדיקה.

על ידי שימוש בכלל, נוכל לבודד הכל במקום אחד ולעשות שימוש חוזר בקוד בקלות ממספר שיעורי בדיקה.

3. שימוש בכללי JUnit 4

אז איך נוכל להשתמש בכללים? אנו יכולים להשתמש בכללי JUnit 4 על ידי ביצוע השלבים הפשוטים הבאים:

  • הוסף פּוּמְבֵּי שדה לשיעור הבדיקה שלנו וודא שסוג השדה הזה הוא תת-סוג של ה org.junit.rules.TestRule מִמְשָׁק
  • הוסף הערה לשדה עם @כְּלָל ביאור

בחלק הבא נראה אילו תלות בפרויקט אנו זקוקים כדי להתחיל.

4. תלות Maven

ראשית, נוסיף את התלות בפרויקט שנצטרך לשם הדוגמאות שלנו. נצטרך רק את ספריית JUnit 4 הראשית:

 צומת צומת 4.12 

כמו תמיד, אנו יכולים להשיג את הגרסה האחרונה ממייבן סנטרל.

5. כללים הניתנים בחלוקה

כמובן, JUnit מספק מספר כללים שימושיים ומוגדרים מראש כחלק מהספרייה. אנו יכולים למצוא את כל הכללים הללו ב org.junit.rules חֲבִילָה.

בחלק זה נראה כמה דוגמאות לשימוש בהן.

5.1. ה תקיה זמנית כְּלָל

בעת בדיקה, לעתים קרובות אנו זקוקים לגישה לקובץ או לתיקיה זמניים. עם זאת, ניהול היצירה והמחיקה של קבצים אלה יכול להיות מסורבל. משתמש ב תקיה זמנית כלל, אנו יכולים לנהל את יצירת הקבצים והתיקיות שיש למחוק לאחר סיום שיטת הבדיקה:

@ כלל ציבורי זמני TmpFolder = זמני זמני (); @Test הציבור בטל givenTempFolderRule_whenNewFile_thenFileIsCreated () זורק IOException {File testFile = tmpFolder.newFile ("test-file.txt"); assertTrue ("היה צריך ליצור את הקובץ:", testFile.isFile ()); assertEquals ("תיקיית Temp וקובץ הבדיקה צריכים להתאים:", tmpFolder.getRoot (), testFile.getParentFile ()); }

כפי שאנו רואים, אנו מגדירים תחילה את תקיה זמנית כְּלָל tmpFolder. לאחר מכן, שיטת הבדיקה שלנו יוצרת קובץ בשם test-file.txt בתיקיה הזמנית. לאחר מכן אנו בודקים שהקובץ נוצר וקיים היכן שהוא צריך. ממש נחמד ופשוט!

לאחר סיום הבדיקה, יש למחוק את התיקיה והקובץ הזמניים. עם זאת, כלל זה אינו בודק אם המחיקה מוצלחת או לא.

יש גם כמה שיטות מעניינות שכדאי להזכיר בשיעור זה:

  • קובץ חדש()

    אם אנו לא מספקים שם קובץ כלשהו, ​​שיטה זו יוצרת קובץ חדש בשם אקראי.

  • newFolder (מחרוזת ... תיקיית שמות)

    כדי ליצור תיקיות זמניות עמוקות רקורסיבית, נוכל להשתמש בשיטה זו.

  • תיקייה חדשה()

    כמו כן, ה תיקייה חדשה() השיטה יוצרת תיקיה חדשה בשם אקראי.

תוספת נחמדה שכדאי להזכיר היא כי החל מגרסת 4.13, ה- תקיה זמנית הכלל מאפשר אימות של משאבים שנמחקו:

@Rule תיקיית TemporaryFolder ציבורית = TemporaryFolder.builder (). AssureDeletion (). Build ();

אם לא ניתן למחוק משאב, הבדיקה עם כישלון עם קביעה שגיאה.

לבסוף, ב- JUnit 5 נוכל להשיג את אותה פונקציונליות באמצעות סיומת מדריך זמני.

5.2. ה ExpectedException כְּלָל

כמו שהשם מרמז, אנחנו יכולים להשתמש ב- ExpectedException כלל לוודא שקוד מסוים יוצא חריג צפוי:

@ כלל גמר ציבורי ExpectedException זרוק = ExpectedException.none (); @Test הציבור בטל givenIllegalArgument_whenExceptionTrowne_MessageAndCauseMatches () {throw.expect (IllegalArgumentException.class); throw.expectCause (isA (NullPointerException.class)); throw.expectMessage ("זה לא חוקי"); לזרוק IllegalArgumentException חדש ("זה לא חוקי", NullPointerException חדש ()); }

כפי שניתן לראות בדוגמה לעיל, אנו מכריזים לראשונה על ה- ExpectedException כְּלָל. ואז, במבחן שלנו, אנו טוענים כי IllegalArgumentException נזרק.

באמצעות כלל זה, אנו יכולים לאמת גם כמה מאפיינים אחרים של החריג, כגון ההודעה והגורם.

לקבלת מדריך מעמיק לבדיקת חריגים עם JUnit, עיין במדריך המצוין שלנו כיצד לטעון חריג.

5.3. ה שם המבחן כְּלָל

במילים פשוטות, ה שם המבחן כלל מספק את שם הבדיקה הנוכחי בשיטת בדיקה נתונה:

@ כלל שם Testname שם = TestName חדש (); @Test public void givenAddition_whenPrintingTestName_thenTestNameIsDisplayed () {LOG.info ("ביצוע: {}", name.getMethodName ()); assertEquals ("givenAddition_whenPrintingTestName_thenTestNameIsDisplayed", name.getMethodName ()); }

בדוגמה טריוויאלית זו, כאשר אנו מריצים את מבחן היחידה, עלינו לראות את שם הבדיקה בפלט:

INFO c.baeldung.rules.JUnitRulesUnitTest - ביצוע: givenAddition_whenPrintingTestName_thenTestNameIsDisplayed

5.4. ה פסק זמן כְּלָל

בדוגמה הבאה זו, נסתכל על ה- פסק זמן כְּלָל. כלל זה מציע חלופה שימושית לשימוש בפרמטר הזמן הקצוב בהערת בדיקה בודדת.

עכשיו, בואו נראה כיצד להשתמש בכלל זה כדי לקבוע פסק זמן גלובלי על כל שיטות הבדיקה בכיתת הבדיקה שלנו:

@ זמן פסק זמן ציבורי globalTimeout = פסק זמן.שניות (10); @Test הציבור בטל givenLongRunningTest_whenTimout_thenTestFails () זורק InterruptedException {TimeUnit.SECONDS.sleep (20); }

בדוגמה הטריוויאלית לעיל, ראשית אנו מגדירים פסק זמן גלובלי לכל שיטות הבדיקה של 10 שניות. לאחר מכן אנו מגדירים בכוונה מבחן שיימשך יותר מ -10 שניות.

כאשר אנו מבצעים בדיקה זו, עלינו לראות כישלון בבדיקה:

org.junit.runners.model.TestTimedOutException: תם הזמן הקצוב לאחר 10 שניות ...

5.5. ה אספן שגיאות כְּלָל

בהמשך אנו נסתכל על ה- אספן שגיאות כְּלָל. כלל זה מאפשר ביצוע בדיקה לאחר שנמצאת הבעיה הראשונה.

בואו נראה כיצד נוכל להשתמש בכלל זה כדי לאסוף את כל השגיאות ולדווח על כולם בבת אחת בסיום הבדיקה:

@ כלל גמר ציבורי ErrorCollector errorCollector = ErrorCollector חדש (); @Test הציבור בטל givenMultipleErrors_whenTestRuns_thenCollectorReportsErrors () {errorCollector.addError (חדש Throwable ("הדבר הראשון השתבש!")); errorCollector.addError (חדש Throwable ("דבר אחר השתבש!"); errorCollector.checkThat ("שלום עולם", לא (containString ("שגיאה!"))); }

בדוגמה שלעיל, אנו מוסיפים שתי שגיאות לאספן. כאשר אנו מריצים את הבדיקה, הביצוע ממשיך, אך הבדיקה תיכשל בסוף.

בפלט נראה שתי השגיאות המדווחות:

java.lang.Trowable: הדבר הראשון השתבש! ... java.lang.Trowable: דבר נוסף השתבש!

5.6. ה מאמת כְּלָל

ה מאמת הכלל הוא מחלקת בסיס מופשטת בה אנו יכולים להשתמש כאשר אנו רוצים לאמת התנהגות נוספת מהבדיקות שלנו. למעשה, ה אספן שגיאות כלל שראינו בפרק האחרון מרחיב את המעמד הזה.

בואו נסתכל על דוגמה טריוויאלית להגדרת המאמת שלנו:

רשימת private messageLog = ArrayList חדש (); @Rule Verifier Verifier verifier = New Verifier () {@Override public void verify () {assertFalse ("יומן ההודעות אינו ריק!", MessageLog.isEmpty ()); }}; 

כאן, אנו מגדירים חדש מאמת ולדרוס את תאשר() שיטה להוסיף קצת לוגיקה לאימות נוסף. בדוגמה פשוטה זו, אנו בודקים אם יומן ההודעות בדוגמה שלנו אינו ריק.

כעת, כאשר אנו מריצים את בדיקת היחידה ומוסיפים הודעה, עלינו לראות שהאימות שלנו הוחל:

@Test public void givenNewMessage_whenVerified_thenMessageLogNotEmpty () {// ... messageLog.add ("יש הודעה חדשה!"); }

5.7. ה DisableOnDebug כְּלָל

לפעמים אנו עשויים לרצות להשבית כלל כשאנחנו באגים. לדוגמא, לרוב רצוי להשבית א פסק זמן שלט בעת ניפוי באגים, כדי למנוע את תזמון הבדיקה שלנו ונכשל לפני שהספקנו לאתר אותו כראוי.

ה DisableOnDebug הכלל עושה בדיוק את זה ומאפשר לנו לתייג כללים מסוימים להיות מושבתים בעת ניפוי באגים:

@ כלל ציבורי DisableOnDebug disableTimeout = DisableOnDebug חדש (Timeout.seconds (30));

בדוגמה לעיל אנו יכולים לראות שכדי להשתמש בכלל זה, אנחנו פשוט מעבירים את הכלל שאנו רוצים להשבית לבנאי.

היתרון העיקרי של כלל זה הוא שאנחנו יכולים להשבית כללים מבלי לבצע שינויים בשיעורי הבדיקה שלנו במהלך ניפוי באגים.

5.8. ה Resource חיצוני כְּלָל

בדרך כלל, בעת כתיבת מבחני אינטגרציה, נרצה להקים משאב חיצוני לפני מבחן ולקרוע אותו לאחר מכן. למרבה המזל, JUnit מספקת מחלקת בסיס שימושית נוספת לכך.

אנו יכולים להרחיב את המעמד המופשט Resource חיצוני להגדרת משאב חיצוני לפני בדיקה, כגון קובץ או חיבור מסד נתונים. למעשה, ה תקיה זמנית הכלל שראינו קודם מתרחב Resource חיצוני.

בואו נסתכל במהירות כיצד נוכל להרחיב את השיעור הזה:

@ כלל גמר ציבורי ExternalResource externalResource = חדש ExternalResource () {@Override מוגן ריק לפני () זורק קוד זורק {// להגדרת משאב חיצוני ספציפי. }; @Override מוגן ריק אחרי () {// קוד להפלת המשאב החיצוני}; };

בדוגמה זו, כאשר אנו מגדירים משאב חיצוני אנו פשוט צריכים לעקוף את ה- לפני() שיטה ו לאחר() שיטה על מנת להקים ולהפיל את המשאב החיצוני שלנו.

6. החלת כללי כיתה

עד כה, כל הדוגמאות שבדקנו חלו על שיטות מקרה בודדות. עם זאת, לפעמים נרצה להחיל כלל ברמת כיתת הבדיקה. אנו יכולים להשיג זאת באמצעות @ ClassRule ביאור.

הערה זו פועלת באופן דומה מאוד ל- @כְּלָל אבל עוטף כלל סביב מבחן שלם - ההבדל העיקרי הוא שהשדה בו אנו משתמשים עבור כלל הכיתות שלנו חייב להיות סטטי:

@ClassRule TemporaryFolder סטטי ציבורי globalFolder = TemporaryFolder חדש ();

7. הגדרת כלל JUnit מותאם אישית

כפי שראינו, JUnit 4 מספק מספר כללים שימושיים מהקופסה. כמובן, אנו יכולים להגדיר כללים מותאמים אישית משלנו. כדי לכתוב כלל מותאם אישית, עלינו ליישם את ה- TestRule מִמְשָׁק.

בואו נסתכל על דוגמה להגדרת כלל רישום שמות שיטת בדיקה מותאמת אישית:

המחלקה הציבורית TestMethodNameLogger מיישמת את TestRule {לוגרית סופית פרטית סופית LOG = LoggerFactory.getLogger (TestMethodNameLogger.class); הצהרה ציבורית @Override חלה (בסיס הצהרה, תיאור תיאור) {logInfo ("לפני הבדיקה", תיאור); נסה {להחזיר הצהרה חדשה () {@ ביטול ציבורי בטל הערכה () זורק זורק {base.evaluate (); }}; } סוף סוף {logInfo ("לאחר הבדיקה", תיאור); }} loginfo ריק ריק (מחרוזת מס ', תיאור תיאור) {LOG.info (msg + description.getMethodName ()); }}

כפי שאנו רואים, TestRule ממשק מכיל שיטה אחת הנקראת החל (הצהרה, תיאור) שעלינו לעקוף כדי להחזיר מופע של הַצהָרָה. ההצהרה מייצגת את הבדיקות שלנו בזמן הריצה של JUnit. כשאנחנו קוראים להעריך() שיטה, זה מבצע את הבדיקה שלנו.

בדוגמה זו, אנו רושמים הודעה לפני ואחרי ונכללים מ- תיאור התנגד לשם השיטה של ​​המבחן האישי.

8. שימוש בשרשראות כלל

בחלק האחרון, נבחן כיצד נוכל להזמין מספר כללי בדיקה באמצעות ה- RuleChain כְּלָל:

שרשרת ציבורי RuleChain @Rule = RuleChain.outerRule (MessageLogger חדש ("הכלל הראשון")) .סביב (MessageLogger חדש ("הכלל השני")) .סביב (MessageLogger חדש ("הכלל השלישי"));

בדוגמה שלעיל, אנו יוצרים שרשרת של שלושה כללים אשר פשוט מדפיסים את המסר שהועבר לכל אחד מהם MessageLogger בַּנַאִי.

כשאנחנו מבצעים את הבדיקה שלנו, נראה כיצד מיישמים את השרשרת לפי הסדר:

התחלה: כלל ראשון התחלה: כלל שני התחלה: כלל שלישי סיים: כלל שלישי סיים: כלל שני סיים: כלל ראשון

9. מסקנה

לסיכום, במדריך זה חקרנו בפירוט את כללי JUnit 4.

ראשית, התחלנו להסביר מהם כללים וכיצד אנו יכולים להשתמש בהם. לאחר מכן בדקנו לעומק את הכללים המגיעים כחלק מהפצת JUnit.

לבסוף בדקנו כיצד אנו יכולים להגדיר כלל מותאם אישית משלנו וכיצד לשרשר כללים יחד.

כמו תמיד, קוד המקור המלא של המאמר זמין באתר GitHub.