קצת היסטוריה: המשורר הסאטירי הרומי יובנאליס (או יובנל, תלוי באיזה וויקיפדיה אתם מסתכלים) חי במאה הראשונה והשניה. ההשפעה של יובנאליס ניכרת בביטויים שמיוחסים לו ומשמשים אותנו גם היום: "נפש בריאה בגוף בריא", "לחם ושעשועים", וגם כותרת הטור הנוכחי. כיוון שבבדיקות עסקינן, אתם ודאי כבר מבינים במה אני הולך לדון בכתבה הזו: מי ישמור על הבודקים? או במילים אחרות: מי אחראי לבדוק את העבודה שלנו?
תשובה חלקית: שאר החברים בפרוייקט או בקבוצה בה אנו עובדים. בדיקה זו נעשית על ידי תהליכי סקירה (reviews) של תוכנית הבדיקות ומקרי הבדיקה. גם דחייה של דוחות באגים מסיבות של טקסט לא מובן או דיווח על משהו שפשוט אינו באג, הוא סוג של בדיקת האיכות של עבודתנו. אבל האמת היא שדי סומכים עלינו שלא נעשה טעויות: שטסט שעבר אכן מצביע על קוד תקין; שלא שכחנו לבדוק שום דבר חשוב; שהאוטומציה שלנו חפה מבאגים, ועוד, ועוד, מה שבעצם משאיר את האחריות בידינו. מעבר להקפדה על ביצוע סקירות עם המפתחים ומנהלי הפרוייקט, יש עוד דברים שאנחנו יכולים לעשות ללא תלות בקבוצות אחרות. בטור הפעם אציין כמה דברים שנכנסים לקטגוריה של "שמירה על השומרים".
זה בכלל יכול להכשל?
כתבתם מקרה בדיקה. הוא כתוב היטב, ואולי אפילו רץ אוטומטית. נפלא.
האם בדקתם שהטסט אכן יכול ליפול? כלומר, שיש מקרה שבו נריץ אותו ונקבל fail?
הרבה פעמים זו סתם שטות: בזמן דיבוג של קוד האוטומציה, היה נוח להתעלם לרגע משורה בקוד שניגשת לברזלים (ל-HW), אז עשינו לה comment out וכתבנו במקומה משהו שמחזיר תמיד תוצאה נכונה. הדיבוג היה ארוך וקשה, שבסיומו פשוט שכחנו את המעקף הנחמד שעשינו, והקוד נכנס ל-git עם ה"תיקון". הטסט הזה כבר לא ימצא באג שמקורו באותה שורה שנשכחה.
לכן, ובמיוחד במקרה של טסטים אוטומאטיים שמרגע שנכנסו למערכת הבדיקות אף אחד לא יסתכל על הקוד שלהם שוב, חייבים לבדוק שכל טסט שנכנס למערכת הבדיקות אכן נכשל במקרה שבו הוא חייב להכשל. הדוגמא הכי טריוויאלית: אתם בודקים אתר אינטרנט. האם כל הבדיקות נכשלות כשהשרת לא פועל? כמובן שזו דוגמא גסה במיוחד; עבור כל טסט צריך לחשוב: מה היכולת שאנחנו בודקים ואיך אפשר לוודא שכאשר יכולת זו אינה מתפקדת במערכת הנבדקת, הטסט אכן יכשל. לפעמים זה מחייב שימוש בטכניקות של code injection, שימוש ב-debugger או ב-test hook. אבל אתם צריכים הוכחה שהבדיקה אכן בודקת משהו.
האם ה-Setup תקין?
יש מקרים בהם סביבת הבדיקות היא טריוויאלית: יישום שמותקן על מחשב אישי, ובדיקות ידניות. אבל הרבה פעמים – ובמיוחד בהרצה של בדיקות אוטומטיות, סביבת הבדיקות מסובכת למדי. חלק מהסיבוך נובע מהאיפיונים של המערכת הנבדקת (הרבה microservices; זיהוי משתמשים מול שרת מרוחק; שימוש בשירותי סליקה; הבאת נתונים ממאגר מידע משותף למספר יישומים). חלק אחר יכול להיות בגלל מערכת הבדיקות שלנו ("משיכת" הקוד החדש והתקנתו באופן אוטומטי; תלות בכלי בדיקה לדימוי משתמשים רבים; סקריפטים להטענת נתוני דמה לבסיס נתונים). תקלה בכל אחד מאלה תגרום לתוצאה שגויה בחלק מהבדיקות. בהעדר מישהו אחר להפיל את זה עליו, האחריות לוודא – לפני שמריצים בדיקה כלשהיא – שהכנת הסביבה התבצעה כראוי, היא שלנו. כלומר – צריך לכתוב עוד הרבה קוד בתשתיות האוטומציה שכל מטרתו היא לוודא שהאוטומציה עבדה.
אתן כאן מקרה פשוט שאפילו בו יש לא מעט קוד לצורך וידוא שהבדיקה מתבצעת כשהמערכת הנבדקת במצב הנכון.
אני בודק מד-מרחק מבוסס לייזר. המכשיר מאפשר למשתמש לבחור אם לתת את התוצאות בס"מ או באינצ'ים. את זה מבצעים דרך קביעת הגדרות (קינפוג) של המכשיר לפני ביצוע המדידה. יש לי מערכת בדיקות שבה המכשיר מחובר לשולחן, ומכוון למשטח במרחק של 3 מטר. יש קוד בדיקה אוטומאטי שמאפשר להורות למד המרחק לבצע את המדידה, ולהחזיר את הערך הנמדד. אבל מה אם המכשיר מקונפג למדידה באינצ'ים? אוקי. אז צריך עוד צעד בבדיקה, שישנה את הגדרות המכשיר למדידה בס"מ – ורק אז לבצע את המדידה ממש. אבל מה אם יש באג שתמיד משאיר את המכשיר במצב מדידה מטרי (ס"מ), לא משנה מה המשתמש בחר? הבדיקה תעבור למרות באג זה! הממ... אז בעצם צריך:
בקיצור: לחשוד כל הזמן, בהכל. לא לקחת כמובן מאליו שהקוד הנבדק מבצע משהו שביקשנו ממנו, ולוודא שלא רק שדברים בוצעו (ניתן לשנות הגדרות), אלא שיש להם את ההשפעה המצופה (תוצאות המדידה מתקבלות ביחידות המידה שהוגדרו). ומה שלא הזכרתי: גם לבדוק שכשהאוטומציה קוראת ערך מהמכשיר, היא אכן מצליחה לקרוא את הערך הנכון ולא – בגלל באג באוטומציה – משקרת באיזשהו אופן.
אוטומציה זה תוכנה
מיותר להגיד בעצם. אבל הרבה פעמים אנחנו שוכחים שגם אנחנו מפתחים קוד, ואם כך אז (כמעט) בהגדרה יש בו באגים. תמיד משעשע אותי לשים לב שכשאני בודק קוד של מישהו אחר אני עם סכין בין השיניים ומחפש כשלים בכל מקום, כולל קלטים הכי ביזאריים שעולים בדעתי. אבל ברגע שזה מגיע לקוד שאני כתבתי, האדרנלין נעלם; "הרי זה עבד נכון על הדוגמה האחת שניסיתי, אז בטח הכל בסדר...".
מעולם לא נתקלתי בקבוצת אוטומציית בדיקות שיש לה קבוצת בדיקה. במקרה הטוב יש סט של בדיקות CI. שזה אולי מספק, אם הבדיקות נקבעו לאחר תכנון נכון והבטחת כיסוי נאות של קוד האוטומציה. מצד אחד לא צריך להגזים: זו תוכנה פנימית, ויש לנו שליטה מלאה על הקלט שהיא תקבל. כמו כן, אם יהיה בה באג רציני, יש להניח שהמון בדיקות יפלו, ונשים לב שמשהו השתבש. מצד שני, שחרור גרסה בעייתית של האוטומציה לקבוצה גדולה של בודקים יכול לבזבז לא מעט שעות עבודה ולגרום לאיחור משמעותי בסבב בדיקות. וכולנו יודעים שזה יקרה בסבב הבדיקות הכי לחוץ, יומיים לפני תאריך ה-drop dead של שחרור התוכנה ללקוח... מסקנה: בדיקת האוטומציה היא עוד נדבך נדרש ב"שמירה על השומרים".
כמה זמן זה לוקח?
בדרך כלל, הרצת מקרה בדיקה – במיוחד אלה האוטומטיים – לא לוקחת המון זמן. שניות מעטות. הרבה פעמים, זמן הבדיקה מתארך בגלל תלות בחלק אחר של המערכת (למשל, אם צריך לקרוא משהו מבסיס נתונים). כשכותבים בדיקה, צריכה להיות לנו איזושהי הערכה כמה זמן היא תיקח. בדיקה המתארכת יתר על המידה מצביעה על אחת מהאפשרויות האלה:
כלומר, כל פעם שנריץ את הבדיקה הזאת, מובטח לנו שהיא תיקח לפחות 60 שניות – זמן ההמתנה שהגדרנו למקרה הבדיקה. כמובן שאפשר היה לקצר את מקרה הבדיקה אם היינו עושים polling: בודקים מידי 3 שניות אם כבר קיבלנו אישור. אם קיבלנו - אפשר להתקדם בבדיקה. אם לא – נמשיך להמתין עד 60 שניות, תוך כדי polling. התוצאה היא שברוב המקרים הטסט ירוץ משמעותית מהר יותר מ-60 שניות.
זה אולי נראה קצת קטנוני. אז מה אם מחשבי האוטומציה יחכו עוד כמה שניות? זה ממילא רץ בלילה כשאנחנו לא שם. ואכן: אם יש לנו רק מקרה בדיקה אחד, לא נורא אם האוטומציה לא הכי יעילה. אבל אם יש לנו אלפי מקרי בדיקה, וכל אחד מהם גונב כמה שניות מיותרות, סבב הבדיקות יתארך בשעות!
האם ה-test hooks עובדים?
לעיתים יש יכולות בתוכנה שקשה לבדוק. זה יכול להיות כי הם "מוחבאות" עמוק בקוד ואין להן קשר ישיר ל-GUI. זה גם יכול להיות שקל (קונספטואלית) לבדוק את היכולת, אבל זה ייקח הרבה זמן. דוגמא: תוכנה שמפקחת על כרטיס רשת WiFi. על פי הדרישות, התוכנה מציגה למשתמש את רשימת הרשתות האלחוטיות שקיימות בסביבה, והמשתמש יכול לבחור למי להתחבר. התוכנה תומכת בהצגה של עד 32 רשתות. על מנת לבדוק יכולת זו, נצטרך להגדיר מעל ל-32 רשתות (שזה קצת מסובך וגם דורש אולי לקנות כמה וכמה נתבים). אבל אפשר גם אחרת: להכניס לתוכנה הנבדקת קוד ש"ירמה", ויספק למודול שמציג את הרשתות רשימה של 32 רשתות שכאילו קיימות בסביבה. יפה מאוד. אבל... עכשיו הכנסנו למעשה יכולת חדשה לתוכנה – גם אם זו יכולת שנשתמש בה רק לבדיקות, ואולי בכלל תוסר מהקוד במוצר הסופי. כיוון שאנחנו מסתמכים על יכולת זו לצורך בדיקת המוצר, חובה עלינו לוודא שהיא עובדת כראוי. כלומר: כל תוספת שהוכנסה לקוד לצורך עזרה בבדיקות, צריכה להיבדק – בכל release – לפני שמשתמשים בה.
לסיכום
בונים עלינו שאם אמרנו שהתוכנה בסדר, היא באמת בסדר. מילא אם מפספסים פה ושם איזה באג שהמפתחים טמנו עמוק בקוד, והוא התחמק ללקוח – זה כמעט חלק מכללי המשחק של הטכנולוגיה היום. אבל כשהפספוס הזה הוא בגלל שאנחנו לא בדקנו את עצמנו... זה כבר מביך, לא נעים, ולא מקצועי.
"חשוב, אם כן, להוסיף לתהליכי העבודה שלנו גם פעולות שכל מטרתן הוא לשמור עלינו מהטעויות שלנו".