Thursday, February 2, 2017

non coders and unit tests

(Hebrew version will be at the end of the post this time)

During Tuesday Night Testing, one of the subjects was "can non-coding testers contribute to unit testing?", and the discussion around the question soon moved from "can they?" to "how they can?". Personally, I feel that it's something that should be available out there in the open, since I hear this question (or similar ones) often enough. I also want to take the opportunity to elaborate a bit over what I felt was relevant in the actual discussion itself.
For the time being, I will put aside my urge to rant on the term "non-coding testers", and go directly to the subject.
The first thing that must be said, is that it helps quite a lot to understand code and to be able to write simple code in whichever language there is. Understanding stuff such as functions, classes, variables (and their scope) and perhaps a thing or two about data structures is not completely necessary to read code, but it sure does help a lot in understanding what you are reading 1.
The second thing that is important to know, is that unless you are working on some assembly code, all good code is very much like reading English, and bad code is like reading the JabberWocky - you can still make sens out of most of it. It's only the really horrifying code that is completely undecipherable.
Armed with those two assumptions, there are several ways to contribute to the unit testing:

  1. Review unit tests for coverage: No, not code coverage, there are automated tools for that. Requirements coverage is perhaps more suitable (but still not quite it). The idea is to read the titles of the unit tests (you don't even need to read what the test actually does, it should be clear from the title), and see that they are testing the functionality that they should. In order to do so, one must first understand the role of the unit under test (usually it will be a class or a method, it might be a somewhat larger component), and just make sure that every requirement (written or implied) that is relevant for that level is covered in a unit test.
    For example: I was reviewing unit tests of a class that was meant to validate a token. The token had 3 parts: a timestamp, a user_id and a signature. I saw some tests around the time - valid time, expired token, malformed timestamp. I simply asked "what if the timestamp is in the future?", we added the test to find out that the code didn't deal with it the way we wanted to. 
  2. Use it to do a code review: While reviewing the unit tests of the same feature, I've noticed that the tokens actually had another part in them. I don't recall what it was, but I noticed that there are no tests around it. When I asked, the developer said that there's no need for unit tests since that part is not processed. If it's not processed, why are we sending it? we fixed the code on the spot. 
  3. Suggest ideas for test cases: As a tester, you are probably more familiar than the developer with the system scope, and know better which parts of data go where. Leverage this knowledge to suggest ideas. "I know that the component you are working on get's input from the component over there. When there are problems with it, we get a number of -1 instead of the number between 0 and 1000 we expect", or "those 3 config files must be aligned, let's write a test to make sure they are" (it's more of an integration test, but still useful). You will also be surprised at how innovative simple ideas such as boundary value testing will seem to some of your developers. 
  4. Be a rubber duck: Rubber ducking is helpful, but speaking to a rubber duck is a bit embarrassing at first. So you help just by asking the developer writing the unit test to show you around, and asking an occasional "why do you that?" or "what are you doing here?". During your duckling career, you will be able to spot stupid mistakes the developer is writing and help fix them fast. 

So, now you know what can be done. Only question is - how to start? 
Ideally, you'll have the full cooperation of the developer, who sees value in your feedback and all you have to do is to ask, and make some time for that. 
Other times, the developer won't seek out your help, but will be happy to help you if you just ask "can you show me around the unit tests so that I can learn?" 
A great idea that was raised by Katrina, was to make this knowledge transfer bi-directional - let's meet and share what was done, and what I'm about to do. Maybe some of the things I was planning to do were already covered (or can be covered easily) by the unit tests, and maybe I'm missing a point that you are concerned about". By putting both of us under inspection, it makes the tester and developer more equal, and reduce resistance since it's not a tester critiquing the developer, but two colleagues collaborating.
But sometimes, especially if you are perceived as "non-programmer", programmers will look down on you and ask you politely to scram out of their way ("but you don't code", "you won't understand", "I don't have time to walk you through this", etc...) In such case, do the review by yourself. You have a source control system, just look into the code there and approach your developer with a question: "Hi, I saw that in your unit tests that you don't check for username format, is this covered elsewhere?", or (and this is a real case) "I looked into the algorithm you've checked-in, and I think there's a bug for this input, could we add a unit test for that?" What was that you are saying there? you don't have access to your source control? go and watch this. One thing to take care of if you are going down that path, is to make sure that your developers know that you are doing this, so that they won't think you are "sneaking up on them". 


I had a great time discussing this and the other subjects with Andrew Morton, Cassandra Leung, Claire Reckless, Katrina Clokie, Tracey Baxter and the event organiser Simon Tomes - thank you all for a great hour. 



1 ↩ If you can afford the time, take some time to complete a MOOC on programming (here, there) or watch this YouTube list (about 30 hours, I skipped the first video which is irrelevant), or use one of the many other ways to learn the basics of programming (hour of code, khan academy & codeacademy are some easy examples). Please note - I'm not suggesting to you (here) to learn to code, just to learn reading it, which is a whole lot easier.





-------------------------------------------------

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

  1. סקירת בדיקות היחידה לכיסוי: לא, אני לא מדבר על כיסוי קוד, בשביל זה יש כלים אוטומטיים, והם טובים יותר בזה. אני מתייחס למשהו שקרוב יותר לכיסוי דרישות - הרעיון הוא לקרוא את כותרות בדיקות היחידה (אין צורך לקרוא את המימוש, בשלב הזה אנחנו סומכים על המתכנת שהבדיקה אכן בודקת מה שהיא מתיימרת לבדוק) מסביב לנושא ספציפי ולראות אם הבדיקות מכסות את כל המקרים המעניינים.
    למשל, לפני זמן מה, ישבתי לסקירה כזו עם מפתח. המחלקה שבדקנו טיפלה בטוקן שהורכב מכמה חלקים- זמן, שם משתמש וחתימה. היו כל מיני בדיקות סביב הזמן - פורמט לא חוקי, זמן תקין, טוקן פג תוקף, טוקן כמעט פג תוקף. מה לא היה שם? טוקן שהזמן המצויין בו נמצא בעתיד. מה מסתבר? לא רק שחסר מקרה בדיקה, גם אין טיפול במצב הזה בקוד. 
  2. אפשר להשתמש בהם כדרך לסקירת קוד: זה די דומה למקרה הראשון, אבל טיפה שונה. כאן אנחנו בעצם מסתכלים על מה שנבדק כדי לנסות להבין מה לא נכתב, או מה מיותר. למשל, כשעברנו על הבדיקות של אותו פיצ'ר, שמתי לב לשדה נוסף שאין סביבו שום בדיקות - אפילו לא אכיפה של פורמט. כששאלתי למה, המפתח ענה "אני ממילא לא מעבד את הנתון הזה, אז לבדוק אותו לא מוסיף לי כלום". שאלת ההמשך שלי הייתה "אז למה אנחנו שולחים את הנתון הזה?" הורדנו אותו. 
  3. אפשר להציע מקרי בדיקה: כבודקים, אנחנו לרוב מכירים טוב יותר את ההקשר הרחב, איזה רכיב מדבר עם איזה רכיב ומה סוג ההפתעות להן ניתן לצפות בהקשר מסויים. אפשר לנצל את הידע הזה כדי להציע מקרי בדיקה מעניינים. "אני יודע שהרכיב הזה שאמור לספק מספרים אקראיים בין 1 ל1000 לא תמיד מגיב בזמן, ואז אנחנו שולחים מינוס 1 כדי לציין את השגיאה, אולי כדאי שנבדוק איך מה שאנחנו כותבים כאן מתמודד עם מספרים שליליים?" או "יש קשר חזק בין שלושת הקבצים האלה, אולי כדאי שנכתוב משהו שעובר עליהם ומוודא שהם עדיין מסונכרנים?"(נכון, זה קצת יותר קרוב לבדיקת אינטגרציה). חוץ מזה, תופתעו לגלות עד כמה מפתחים מסויימים מתרשמים מדברים בסיסיים כמו מחלקות שקילות ובדיקות גבולות. 
  4. אפשר להיות ברווז גומי: על ניפוי שגיאות בעזרת ברווז גומי שמעתם? זו שיטה אפקטיבית למדי לטיפול בקוד, בעיקר בקוד סבוך. אבל לדבר עם ברווז גומי זה קצת מביך, בעיקר בהתחלה. לעומת זאת, להסביר דברים לבודק תוכנה שלא מבין מילה בתכנות זה לגמרי לגיטימי. ככה אפשר לעזור פשוט על ידי ישיבה בשקט, ושאלה מתוזמנת של "רגע, מה בעצם קורה כאן?" על הדרך, תוכלו לאתר שגיאות מטופשות שהמתכנת עושה ולוודא מה בדיקות היחידה מכסות. 
אלה, בגדול, כמה רעיונות לדרכים לתרום לבדיקות היחידה בלי לכתוב קוד. שימו לב, כל הדרכים האלה מצריכות תקשורת עם מי שכותב את בדיקות היחידה. 
השאלה שנותר להתמודד איתה היא "איך להתחיל?" 

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

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

אני מאוד נהניתי לדבר במשך כשעה עם
וכמובן גם עם מארגן האירוע, Simon Tomes. תודה לכולכם (אם מישהו מכם קורא עברית) על הדיון!

No comments:

Post a Comment