לפחות, טרם שמעתי על מקום בו התופעה הזו לא קיימת בכלל – אנשים משקיעים וכותבים סט מבדקים אוטומטיים לתפארת: הקוד כתוב יפה, בעל מטרה ברורה, בלי שטויות מיותרות. מה יש לומר? חבורה של אנשים מוכשרים השקיעה זמן ומחשבה בבניית הכלי הנכון למשימה. הכל טוב ככל שהוא רק יכול להיות. כלומר, חוץ מדבר אחד קטן. ממש פצפון. מדי פעם, בלי שלמישהו יש מושג למה, אחד המבדקים, בדרך כלל מבדק ברמה מערכתית, נכשל. למעשה, לא מדובר במבדק יחיד. יש חבורה שלמה של החוליגנים האלה. כשמערך המבדקים שרצים בכל פעם גדל, הסיכוי שלא ניתקל במבדק סורר כזה מתחיל להתקרב באופן מדאיג למדי לאפס1
אז מה עושים? מריצים שוב. אם מי שנכשל מצליח לעבור בפעם השנייה (או פעם אחת מתוך שלוש, או חמש פעמים מתוך שבע) – אנחנו מכריזים על הצלחה ומעבירים את המבדק.  
ויש עוד מגוון טכניקות לשיפור מצב הבדיקות השבירות – אנחנו מחכים נצח וחצי כדי שכל רכיבי הממשק הגרפי יספיקו להיטען, כותבים כלי חכם שיודע להחזיר אותנו לנקודת ההתחלה בכל פעם, מתעלמים מחלק מהתמונה שאנחנו משווים כי יש שם פרסומת מתחלפת, מכניסים לתשתית שלנו ניסוי מחדש של פעולות מסויימות ש”סתם נופלות” לפעמים, ועוד. 
בסוף התהליך הזה, יש לנו ריצה שמצליחה לעבור בכל פעם וכשיש נפילה, אנחנו די בטוחים שמדובר בתקלה. 
אבל עשינו עוד משהו – כדי להיפטר מהכישלונות השגויים הוספנו מנגנונים שהופכים את המבדקים שלנו לרגישים פחות והגדלנו את הסיכוי שתקלה אמיתית תחמוק מבעד למסננים שלנו. ולא מדובר רק במבדקים האוטומטיים – מתי הפעם האחרונה שמעתם (או אמרתם) את המשפט “זה קורה לפעמים, אחרי ריסטארט הבעיה נפתרת” ?
כשבוחנים יעילות של מכשור לזיהוי ביומטרי יש שני מדדים שמתייחסים אליהם – רמת אי התאמה מוטעית ורמת קבלה מוטעית. כלומר – מה הסיכוי של אדם לא להיות מזוהה כעצמו בטעות, ומה הסיכוי של אדם להיות מזוהה כאדם אחר בטעות. הטעויות האלה נקראות: 
FRR (False Rejection Rate)
FAR (False Acceptance Rate)
כמו שניתן לנחש, אפשר לכייל את רמת הרגישות של הסורק הביומטרי כדי לשנות את הסיכויים של כל סוג טעות (ככלל, ככל שהסורק רגיש יותר, כך הסיכוי לאי התאמה מוטעית עולה, והסיכוי לקבלה מוטעית יורד). מתוך שני המדדים האלה, נגזר מדד שלישי – CER – Crossover Error Rate, שמציין מה היא מידת הטעות כאשר שני המדדים לעיל שווים. ככל שמדד CER נמוך יותר, כך הפשרה שנעשה תהיה קטנה יותר והשיטה נחשבת טובה יותר (כמובן, במקרה של צרכים ספציפיים כמו למשל בבסיס צבאי – תהיה חשיבות גבוהה יותר לאחד המדדים, אבל CER הוא כלל אצבע יעיל למדי ברוב המקרים האחרים).

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

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


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


————————————————————————————————————–

It happens to everyone. 
At least, I have not yet heard of a place where this phenomenon does not exist – People are building a nifty test harness to run some automated checks, and let’s even assume they’re doing a really good job: They write clean code, check at the proper levels, use decent programming instead of just piling something that works, and generally are using the right tool for the task. Everything is as good as it gets. Yet, something is still amiss. There’s this small, annoying problem: Some of the checks, usually at the system level, are “flaky”, which is to say they fail sometimes with no apparent reason. Even when the flakiness rate is pretty low, after a while there’s a whole hoard of slightly flaky checks and almost every run is failing1. So we re-run the checks. if they pass the 2nd time (or the 3rd, or five passes out of seven) – we call the run a success. There are, naturally, many other ways of doing it – we add waits and check for page load, we retry simple actions within our framework, ignore part of the screen during image comparison since there’s an alternating ad in that part.
By the end of this process we have a suite of checks that is almost always failing on real bugs. Cool. However, to achieve that we increased the automation fault-tolerance, and introduced a greater risk of missing (sometimes not so) subtle problems. Keep in mind – this is not unique to automated checks. When was the last time you’ve heard (or used) the phrase “it happens sometimes, but it’s gone after a restart”?

When referring to biometric systems, there are two common KPIs that are being used to measure a system effectiveness:
FRR (False Rejection Rate): The rate in which a system will not correctly identify a person.
FAR (False Acceptance Rate): The rate in which a system falsely “recognizes” a person, despite that person being someone else.
As you can guess, a biometric scanner can be calibrated to different sensitivity levels, impacting both of those KPIs. As a rule of thumb, making a scanner more sensitive will increase FRR and decrease FAR, allowing to choose the suitable settings for the situation (On your private phone, having to scan your finger twice each time is rather annoying, but in the case of a high-security military base, you’d rather scan your palm for 10 full seconds than allow unauthorized personnel in).
When comparing two biometric systems, one of the quick comparison points is CER (Crossover Error rate) – which is the point where FRR is equal to FAR. A system with lower CER is considered better for most use cases.

I think that using such a measurement for checks, and especially for automated checks, can be useful. If the null hypothesis is “The software is clear of bugs that the automated check is expected to find”, then FRR will be the flakiness rate of a test (number of failed runs with no actual bug, divided by the total number of runs), and the FAR will be the number of passed runs where there is a bug, divided by the total number of runs. True, it’s not a simple thing to measure (How do you count runs on bug that you didn’t catch? Probably you’ll need to leverage the source control to do that analysis). But even without having exact numbers – using the language of CER reminds us that sometimes we need to invest also in improving the total accuracy of our checks, instead of simply shifting the balance between FRR and FAR.

And one final thing – one of the benefits of taking so long to write a blog post, is that I have the chance to stumble upon some interesting reading materials. In this post, Bas Dijkstra gives a very interesting perspective on checks reliability.


1 Google, Despite their best efforts, are seeing 1.5% flakiness ratio. Most companies I heard of can only envy such numbers. Yet – such a number means that at least one of the flaky checks will fail in every run.

also: