נושא ה-False Alarms הינו נושא מאוד כואב לרוב מפתחי האוטומציה. תמיד בכל פרוייקט אוטומציה מתחיל אנו חווים נפילות בהרצות שלנו על ימין ועל שמאל.
בפוסט הזה אנו נלמד על דרך אחת להתמודד עם הבעיה.
מה זה למעשה המושג הזה: False Alarm ?
תראו, אנחנו אנשי בדיקות בסופו של דבר וכשאשר אנו מריצים את סט הטסטים שלנו ואנו רואים נפילה בדוח עם סיום הריצה, נפילה שמעידה על באמת באג במערכת – אז יפה מאוד, עשינו את עבודתינו נאמנה ומצאנו באג.
אבל המציאות מוכיחה לנו אחרת. בדרך כלל כשאנו מריצים את סט הבדיקות שלנו וישנן נפילות, אז ברוב המקרים לא מדובר כאן בבאג של המערכת, התנהגות זו נקראת False Alarm – אזעקת שווא (הבדיקה נכשלה אבל לא בגלל באג). בדרך כלל בדיקות אלו יכשלו בגלל בעיות סביבה הקשורות לתיזמוני מערכת, בעיות תקשורת, מצב של Stale לאחד מהקומפוננטות אותן אנו בודקים או יכול להיות שהבעיה בכלל נוצרה בגלל באג שלנו בקוד של האוטומציה…
אחת הדרכים לתקוף בעיה זו הינה היכולת להריץ באופן אוטומטי את אותו מקרה בדיקה כמה פעמים, כך שאם הטסט נופל בפעם הראשונה (נגיד בגלל בעיית תיזמונים), ההנחה היא שבריצה השניה או השלישית הוא יעבור, ואם אחרי כמה נסיונות הוא ממשיך ליפול, סביר להניח שיש כאן באג או בעיה אחרת שדורשת טיפול בנפרד.
כשאני חושב על מנגנון ה-Retry אני נזכר במשפט הפתיחה של הסרט "היום השלישי" משנת 1996 : "ביום הראשון הם הגיעו, ביום השני הם תקפו, ביום השלישי השבנו מלחמה" , כאן אנו דרך מנגנון ה-Retry משיבים מלחמה על ה-False Alarms שבאים שוב ושוב ו"תוקפים " אותנו.
ה-False Alarm היא גם אחת מהסיבות המרכזיות שמורידה את ה-ROI של פרוייקט אוטומציה, תחשבו על זה, כמה שווה להשקיע במערכת של בדיקות אוטומטיות, עם הקצאות של זמן, כלים, רישיונות, מפתחים כשאר כל הזמן אנו מוצאים את עצמינו תקועים באותם מקרי בדיקה שנופלים שלא בגלל באג במוצר הנבדק ?
אז איך ממשמים את מנגנון ה-Retry ?
הפתרון שאציג כאן בפוסט זה הינו פתרון המבוסס על Junit , ובפוסט הבא (חלק ב') אראה פתרון נוסף.
זה ידוע כי כשעובדים עם Junit אנו יכולים ליצור לעצמנו מערכת חוקים, או Rules. החוק הוא איזושהי אימפלמנטציה לפעולה מסויימת אותה אנו נרצה לממש ולהחביא אל מאחורי הקלעים. ב-Junit אותו חוק שאנו נכתוב יתקיים תחת אנוטציית ה-@Rule.
אז תחילה אנו ניצור מחלקה המממשת ממשק (Interface) שנקרא: TestRule , זהו ממשק המגיע ביחד עם Junit. בתוכה נגדיר בנאי שיקבל כפרמטר את מספר ההרצות החוזרות שנבצע במקרה של כישלון.
כמו כן נגדיר את מתודת ה-Stetement בה אנו נממש את הפעולה החוזרת (לולאה) של ההרצה.
כך למשל המחלקה שלנו אמורה להיראות:
public class RetryRule implements TestRule { private int retryCounter; public RetryRule (int retryCounter) { this.retryCounter = retryCounter; } public Statement apply(Statement base, Description description) { return statement(base, description); } private Statement statement(final Statement base, final Description description) { return new Statement() { @Override public void evaluate() throws Throwable { Throwable caughtThrowable = null; for (int i = 0; i < retryCounter; i++) { try { base.evaluate(); return; } catch (Throwable t) { caughtThrowable = t; System.out.println(description.getDisplayName() + ": Execution #" + (i + 1) + " Failed."); } } System.out.println(description.getDisplayName() + ": That's it, I give up, I tried " + retryCounter + " times, Now you should check it up"); throw caughtThrowable; } } } }
בנוסף לכך, עלינו ליצור את מחלקת הטסטים שלנו.
במחלקה זו נממש את האנוטציות של Junit כמו ה-BeforeClass , Test , AfterClass… ממש כמו במקרים הרגילים של אוסף בדיקות, רק שהפעם אנחנו נגדיר גם את אנוטציית ה-@Rule ובתוכה נגדיר אובייקט ממחלקת ה-RetryRule שראינו מקודם, כך:
@Rule public RetryRule retry = new RetryRule(NumOfRetries);
מקרה הבדיקה שלקחתי הינו להיכנס לאתר: http://atidcollege.co.il ולוודא כי הלוגו של עתיד האוטומציה מוצג:
השתמשתי פה במתודת ה-isDisplayed, זוהי דוגמא למקרה של הרצה מוצלחת של בדיקה:
assertTrue(driver.findElement(By.className("fw-site-logo")).isDisplayed());
זה לפי ה-inspect של האתר ממנו לקחתי את המידע:
אז התוכנית המלאה להרצה תראה כך:
public class TestCases { static WebDriver driver; String URL = "http://atidcollege.co.il"; int NumOfRetries = 3; @BeforeClass public static void setupTest() { System.setProperty("webdriver.chrome.driver", "D:/Projects/chromedriver.exe"); driver = new ChromeDriver(); driver.manage().window().maximize(); driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS); } @Rule public RetryRule retry = new RetryRule(NumOfRetries); @Test public void CheckMyLogo() { driver.get(URL); assertTrue(driver.findElement(By.className("fw-site-logo")).isDisplayed()); } @AfterClass public static void close() { driver.quit(); } }
זוהי דוגמא לכך שהתוכנית תעבור ללא בעיות.
אך במידה ואשנה את ערך זיהוי התמונה ל-Kuku כך למשל:
assertTrue(driver.findElement(By.className("Kuku")).isDisplayed());
מה שיקרה בפועל כשאריץ את התוכנית, זה שהתוכנית תיכנס לאתר, תנסה למצוא את התמונה ותיכשל, היא תבצע את פעולת הכניסה לאתר ווידוא הצגת התמונה 3 פעמים, כי זהו הפרמטר שהגדרתי לו תחת :
int NumOfRetries = 3
כשאביט ב-Console אראה את ההודעות הבאות (בדיוק כפי שהגדרתי לו במחלקת ה-RetryRule):
כך אני רואה בוודאות כי הטסט שלי רץ 3 פעמים לפני שהוא הודיע על כישלון כללי ומעבר לטסט הבא.
עד כאן להפעם, בפוסט הבא עדיין אמשיך לדבר על Retries באוטומציה, אך הפעם עם מימוש ב-Framework אחר.
יש למה לחכות 🙂