מחפש צרות | מיכאל שטאל

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

(boundary value analysis)  בספרים. לכן אני תמיד נהנה כשמוצאים באג ש"מתיישב" יפה על התיאוריה.

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

הבאג הנעלם

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

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

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

לך עכשיו תוכיח שיש לך אחות.

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

מה שכן, זו דוגמה (לא קלאסית!) לאפקט הגשושית.

אפקט הגשושית (Probe effect)

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

א) תוספת של debug prints לקוד, לצורך זמני (למשל, לעזור בתהליך debugging) או באופן קבוע על מנת לאפשר מצב הפעלה מיוחד לאיתור תקלות לאחר שחרור המוצר ללקוחות. תוספת זמן העיבוד שההדפסות מכניסות משנות את התנהגות המוצר, ותופעות שנצפו ללא ההדפסות, נעלמות כשההדפסות מופעלות (או להיפך:  ההדפסות גורמות לתקלות פונקציונאליות במוצר).

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

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

מורשת קרב (1) – בדיקת אפליקציית ראייה ממוחשבת

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

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

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

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

הנה דוגמה למה שהתסריט הציג:

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

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

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

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

כעס!

שינוי קטן בתסריט ייצר הוראות בפונט גדול יותר:

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

 

מורשת קרב (2) – מאיפה הקלט

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

נניח שאנו בודקים מערכת לזיהוי פנים. לגמרי לא יעיל להעמיד כל סבב בדיקות אנשים מול המצלמה על מנת לוודא שהמערכת זיהתה אותם. במקום זה מקליטים סרטונים של מספר גדול של אנשים, ומזינים אותם למערכת כאילו הם מגיעים מהמצלמה. ה"כאילו" הזה טומן בחובו הזדמנויות רבות לאפקט הגשושית: האם התמונות מוזנות לתוכנה באותו הקצב שהם מגיעות ממצלמה? האם התמונות עוברות אם אותו קדם-עיבוד (pre-processing) שמבוצע על תמונות מהמצלמה? אם לצורך ביצוע קדם-עיבוד זה כתבנו קוד נוסף הרי שאנחנו מעמיסים את המערכת מעבר למה שמצלמה מעמיסה; האם קריאת הסרטונים מהדיסק משנה את התנהגות המערכת כולה? ועוד ועוד.

מוסר השכל

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