תבניות כתיבה למקרי מבחן באמצעות JUnit 5

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

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

במדריך זה נלמד כיצד ליצור תבנית בדיקה באמצעות JUnit 5.

2. תלות Maven

נתחיל בהוספת התלות שלנו pom.xml.

עלינו להוסיף את ה- JUnit 5 הראשי ג'וניט-צדק-מנוע תלות:

 org.junit.jupiter junit-jupiter-engine 5.7.0 

בנוסף לכך, נצטרך להוסיף את ה- צומת-צדק-אפי תלות:

 org.junit.jupiter junit-jupiter-api 5.7.0 

כמו כן, אנו יכולים להוסיף את התלות הדרושה שלנו build.gradle קוֹבֶץ:

testCompile group: 'org.junit.jupiter', שם: 'junit-jupiter-engine', גרסה: '5.7.0' testCompile group: 'org.junit.jupiter', שם: 'junit-jupiter-api', גרסה : '5.7.0'

3. הצהרת הבעיה

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

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

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

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

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

4. תבניות בדיקה

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

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

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

  • שיטת יעד למבחן
  • שיטת תבנית בדיקה
  • ספק אחד או יותר מההקשר של קריאה הרשומים בשיטת התבנית
  • הקשר או קריאה אחת או יותר המסופקים על ידי כל ספק הקשר הקשר

4.1. שיטת יעד הבדיקה

לדוגמא זו נשתמש בפשטות UserIdGeneratorImpl.generate השיטה כיעד הבדיקה שלנו.

בואו נגדיר את UserIdGeneratorImpl מעמד:

מחלקה ציבורית UserIdGeneratorImpl מיישמת UserIdGenerator {בוליאני פרטי isFeatureEnabled; UserIdGeneratorImpl ציבורי (בוליאני isFeatureEnabled) {this.isFeatureEnabled = isFeatureEnabled; } צורת מחרוזת ציבורית (String firstName, String lastName) {String initialAndLastName = firstName.substring (0, 1) .concat (lastName); החזרה isFeatureEnabled? "bael" .concat (initialAndLastName): initialAndLastName; }}

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

בואו נראה איך זה נראה:

מתג התכונה הנתון מושבת כאשר firstName = "John" ו- lastName = "Smith" ואז "JSmith" מוחזר. מתג התכונה מופעל כאשר firstName = "John" ו- lastName = "Smith" ואז "baelJSmith" מוחזר

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

4.2. שיטת תבנית הבדיקה

להלן תבנית בדיקה לשיטת יעד הבדיקה שלנו UserIdGeneratorImpl.generate:

מחלקה ציבורית UserIdGeneratorImplUnitTest {@TestTemplate @ExtendWith (UserIdGeneratorTestInvocationContextProvider.class) בטל פומבי כאשר UserIdRequested_thenUserIdIsReturnedInCorrectFormat (UserIdGeneratorTestCase testGenerator = UserGeneratorGenerator) (UserIdGeneratorGenerator) (UserIdGeneratorTestCase); מחרוזת actualUserId = userIdGenerator.generate (testCase.getFirstName (), testCase.getLastName ()); assertThat (actualUserId) .isEqualTo (testCase.getExpectedUserId ()); }}

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

להתחיל עם, אנו יוצרים את שיטת תבנית הבדיקה שלנו על ידי סימון אותה ב- JUnit 5 @TestTemplate ביאור.

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

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

מחלקה ציבורית UserIdGeneratorTestCase {בוליאנית פרטית isFeatureEnabled; פרטי מחרוזת firstName; שם משפחה פרטי מחרוזת; מחרוזת פרטית expectUserId; // סטרים וקובעים סטנדרטיים}

לבסוף, אנו קוראים לשיטת יעד הבדיקה וקובעים כי תוצאה זו היא כצפוי

עכשיו הגיע הזמן להגדיר את ספק הקשר ההפעלה שלנו.

4.3. ספק הקשר ההפעלה

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

בעבר, באמצעות @ExtendWith ביאור, נרשמנו UserIdGeneratorTestInvocationContextProvider כספק הקריאה שלנו.

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

מחלקה ציבורית UserIdGeneratorTestInvocationContextProvider מיישם את TestTemplateInvocationContextProvider {// ...}

הקשר הפתיחה שלנו מיישם את TestTemplateInvocationContextProvider ממשק, שיש לו שתי שיטות:

  • תומך TestTemplate
  • supplyTestTemplateInvocationContexts

נתחיל ביישום ה- תומך TestTemplate שיטה:

@Override בוליאני ציבורי תומך TestTemplate (ExtensionContext extensionContext) {return true; }

מנוע הביצוע של JUnit 5 מכנה את תומך TestTemplate שיטה ראשונה לאימות אם הספק חל על הנתון ExecutionContext. במקרה זה, אנחנו פשוט חוזרים נָכוֹן.

עכשיו, בוא נבצע את supplyTestTemplateInvocationContexts שיטה:

@Override זרם ציבורי supplyTestTemplateInvocationContexts (ExtensionContext extensionContext) {boolean featureDisabled = false; תכונה בוליאנית Enable = true; להחזיר Stream.of (featureDisabledContext (UserIdGeneratorTestCase חדש ("מתג התכונה הנתון מושבת כאשר שם המשתמש הוא John Smith ואז userid שנוצר הוא JSmith", featureDisabled, "John", "Smith", "JSmith")), featureEnabledContext (UserIdGeneratorTestCase חדש (" מתג התכונה נתון מופעל כאשר שם המשתמש הוא ג'ון סמית ואז המשתמש שנוצר הוא baelJSmith ", featureEnabled," John "," Smith "," baelJSmith "))); }

מטרת ה - supplyTestTemplateInvocationContexts השיטה היא לספק א זרם שֶׁל TestTemplateInvocationContext מקרים. לדוגמא שלנו, הוא מחזיר שני מופעים, המסופקים על ידי השיטות featureDisabledContext ו featureEnabledContext. כתוצאה מכך, תבנית הבדיקה שלנו תפעל פעמיים.

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

4.4. מופעי ההקשר של הפנייה

הקשרים של קריאה הם יישומים של TestTemplateInvocationContext ממשק ויישם את השיטות הבאות:

  • getDisplayName - ספק שם תצוגה לבדיקה
  • getAdditionalExtensions - להחזיר הרחבות נוספות להקשר הפנייה

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

פרטי TestTemplateInvocationContext featureDisabledContext (UserIdGeneratorTestCase userIdGeneratorTestCase) {החזר TestTemplateInvocationContext חדש () {@Override public String getDisplayName (int invocationIndex) {return userIdGeneratorTestCase.getDisplayName (); } @Override רשימה ציבורית getAdditionalExtensions () {return asList (new GenericTypedParameterResolver (userIdGeneratorTestCase), new BeforeTestExecutionCallback () {@Override public void beforeTestExecution (ExtensionContext extensionContext) {System.out.println ("לפני: Back); AfterTestExecutionCallback חדש () {@Override public void afterTestExecution (ExtensionContext extensionContext) {System.out.println ("AfterTestExecutionCallback: הקשר מושבת");}}); }}; }

ראשית, על הקשר ההפעלה שהחזיר ה- featureDisabledContext השיטה, ההרחבות שאנו רושמים הן:

  • GenericTypedParameterResolver - סיומת לפותר פרמטרים
  • BeforeTestExecutionCallback - סיומת להתקשרות חוזרת במחזור החיים שפועלת מיד לפני ביצוע הבדיקה
  • AfterTestExecutionCallback - סיומת להתקשרות חוזרת של מחזור החיים הפועלת מיד לאחר ביצוע הבדיקה

עם זאת, בהקשר הקריאה השני, שהוחזר על ידי featureEnabledContext שיטה, בוא נרשום קבוצה אחרת של הרחבות (שמירה על GenericTypedParameterResolver):

פרטי TestTemplateInvocationContext featureEnabledContext (UserIdGeneratorTestCase userIdGeneratorTestCase) {להחזיר TestTemplateInvocationContext חדש () {@Override public String getDisplayName (int invocationIndex) {return userIdGeneratorTestCase.getDisplayName (); } @Override רשימה ציבורית getAdditionalExtensions () {חזור asList (חדש GenericTypedParameterResolver (userIdGeneratorTestCase), חדש DisabledOnQAEnvironmentExtension (), חדש BeforeEachCallback () {@ Override public void beforeEach (ExtensionContext ExtensionContext). );}}, AfterEachCallback חדש () {@Override public void afterEach (ExtensionContext extensionContext) {System.out.println ("AfterEachCallback: Enabled context");}}); }}; }

בהקשר הקריאה השני, ההרחבות שאנו רושמים הן:

  • GenericTypedParameterResolver - סיומת לפותר פרמטרים
  • DisabledOnQAEnvironmentExtension - תנאי ביצוע כדי להשבית את הבדיקה אם מאפיין הסביבה (נטען מה- application.properties קובץ) הוא "qa
  • BeforeEachCallback - סיומת להתקשרות חוזרת של מחזור החיים שפועלת לפני כל ביצוע שיטת בדיקה
  • AfterEachCallback - סיומת להתקשרות חוזרת במחזור החיים הפועלת לאחר כל ביצוע שיטת בדיקה

מהדוגמה לעיל, ברור לראות כי:

  • אותה שיטת בדיקה מנוהלת בהקשרים מרובים של קריאה
  • כל הקשר קריאה משתמש במערך הרחבות משלו הנבדל הן במספר והן באופיים מההרחבות בהקשרים אחרים של קריאה

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

5. מסקנה

במאמר זה בדקנו כיצד תבניות הבדיקה של JUnit 5 הן הכללה חזקה של בדיקות פרמטריות וחוזרות ונשנות.

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

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

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


$config[zx-auto] not found$config[zx-overlay] not found