להתחיל לבדוק זה נראה קל.. כשצריך לבדוק משהו כמו: דרישה, תאור, הנחה או ידע אישי. נריץ את האפליקציה ונראה אם התוצאה בהתאם לציפיות שלנו.
אבל זו רק ההתחלה. אנחנו רוצים לדעת לא רק "מה שצריך" אלא גם "מה אם". אז אנחנו מנסים לחשוב על עוד מקרים. לפעמים זה קל, אבל ברוב הפעמים יש גבול לדמיון שלנו. הגבול הזה תוחם את הבדיקות שלנו, וכתוצאה מכך, את היכולת שלנו להבין איך האפליקציה מתנהגת בכל מיני מקרים (שבטוח יקרו ב-production). גם אם לא נחשוב על המקרים, הם יקרו. אז עדיף לחשוב עליהם לפני שיצאו החוצה.
אז איך מייצרים מקרי בדיקה מקיפים יותר?
תכנון בדיקות (test planning), זו מיומנות. אפשר להתאמן עליה ואפשר להשתפר בה. אנשים חכמים חשבו על זה ונתנו את דעתם. אחד הדברים שגילו בדרך שסיעור מוחות (brainstorming) יעיל יותר. חשיבה על מקרי בדיקה היא לא לינארית, כלומר כשחושבים על רעיון למקרה אחד, פתאום חושבים על עוד מקרים, ובעוד יומיים כשנבדוק שוב, נחשוב על עוד מקרים. זה לא רק אתם.
כתוצאה מכך אפשר להתחיל ממצב "יותר טוב". יש כמה שיטות, והיום נתמקד ב SFDIPOT. נשמע כמו מילת קסם, ולפעמים עם אותה התוצאה.
SFDIPOT זה ראשי תיבות של מספר דברים – פרספקטיבות להסתכל על המוצר – שג'יימס באך יצר כהיוריסטיקה לבניית אסטרטגיה לבדיקות.
החלק השני יותר ברור, אסטרטגיה היא סוג של תכנית לבדיקות. אבל מה זה היוריסטיקה?
מכירים את המושג best practice? אם משהו הוא best, זה אומר שהוא best תמיד. כלומר, משהו שתמיד עובד תמיד, לכל אחד ובכל זמן. אבל אנחנו יודעים שבעולם האמיתי, אין דבר כזה באמת. דברים שנכונים עבור אפליקציה עם database, פחות נכונים לכזו עם חומרה. ולהפך. אבל יש דברים שעובדים רוב הזמן לרוב האנשים. זו היוריסטיקה – פתרון לבעיה, שרוב הפעמים עובד (ולפעמים פחות טוב).
SFDIPOT הוא מודל היוריסטי לפיתוח תכניות בדיקה. הוא עובד היטב הרבה פעמים, להרבה מאד אנשים בכל מיני תחומים. קיים סיכוי שיעבוד פחות טוב במקרים ספציפיים. וזה בסדר, הניסיון להגיע לשלמות לא תמיד צלח אבל הדרך לשם הוציאה כמה תכניות לא רעות בכלל. בטח כנקודת התחלה.
הרעיון מאחורי המודל הוא לפרק את המוצר שלנו בכמה צורות, לחשוב עליו אחרת וכתוצאה מהפירוק הזה יעלו לנו רעיונות שונים. אחד המקרים שאנחנו נופלים בו, זו ההצמדות לדרישות. זה לא דבר רע, אבל די מגביל אותנו. אם נחשוב על המוצר מכיוונים שונים, נגלה עוד מקרים שאולי נרצה לבדוק, וזו המטרה של המודל הזה - לפתוח לנו את הראש כדי שיהיו לנו יותר מקרים לבדוק (ומתוכם נחליט מה יותר חשוב).
למטרת הדיון שלנו, נחשוב על אפליקציית ניהול אי-מיילים. נקרא לה Outlike. כולם מכירים משהו דומה והשתמשו במוצר ולא צריך spec. לכתוב תכנית בדיקות ל-Outlike זה פרויקט גדול (אבל שווה לעשות כתרגיל, נסו).
נתחיל לדבר על הפרספקטיבות השונות, וננסה לראות מה זה אומר לגבי סוגי בדיקות שאפשר לעשות על תוכנה כזו.
חשוב לי לומר לפני שמתחילים – זה לא הפתרון היחיד לבעיה (יצירת רשימת המקרים). וכמו שמשתמע מכך שמדובר בהיוריסטיקה – יכול להיות שלא יתאים למקרה הספציפי שלכם. הרעיונות שנדבר עליהם ניתנים למיקוד שיתאים להרבה מאד מקרים, כנראה גם למקרה שלכם.
SFDIPOT הוא נקודת התחלה, וגם שימוש במודל יהיה יותר יעיל כשנתאמן עליו - גם זו מיומנות. הוא כלי נהדר כחלק ממארג הכלים שלנו בתכנון בדיקות.
באותה מידה, לא משנה מאיפה מגיע הרעיון. אם חשבתם עליו מפרספקטיבה כזו או אחרת - העיקר שהרעיון הועלה.
עוד משהו – זה מתכון ל-brainstorming, אבל העבודה לא נגמרת כאן. אח"כ צריך לנהל את רשימת הבדיקות, לתעדף את הבדיקות שחשוב לעשות קודם ושאר הבדיקות אח"כ. להחליט איך לבצע את הבדיקות (ידנית, אוטומטית) וכו'.
בואו נתחיל.
אז קודם פירוק השם המוזר לראשי התיבות:
Structure |
- |
S |
Functionality |
- |
F |
Data |
- |
D |
Interface |
- |
I |
Platform |
- |
P |
Operation |
- |
O |
Time |
- |
T |
דברים נראים קצת יותר בהירים עכשיו. אבל מה כל אחד אומר? ומה זה אומר לגבי הבדיקות? בואו נצלול.
1.Structure – מבנה. בד"כ הכוונה למבנה פנימי. אפליקציות יכולות להיות בעלות מבנה שונה, והמבנה הזה יכול לעורר שאלות שנרצה לענות עליהן בבדיקות.
מבנה יכול להיות client-server. הוא יכול להיות רק שרת או All-in-one זה יכול להיות תכנית אחת שרצה ב-process אחד, או אוסף של microservices. ויכול להיות שהחלקים השונים מדברים בפרוטוקולים שונים. זה יכול להיות בקריאותREST API, או תקשורת בשליחת הודעות על Kafka.
נסתכל על כמה דוגמאות שקשורות ב-Outlike. ברור שיש לנו client. והוא עובד מול שרת כלשהו. רק המבנה הזה מאפשר לנו לשאול: מה קורה כש:
- אנחנו מחכים למייל
- אנחנו לא מחוברים
- אנחנו התחברנו שוב
- אנחנו שולחים מייל כשאנחנו מנותקים
ועוד שאלות. אם הכל (שרת ולקוח) היה process אחד. זה לא היה מעניין. לא היו ניתוקים, לא היו delays. אבל אנחנו יודעים שהמבנה של המוצר משפיע על ההתנהגות שלו, ואנחנו רוצים לענות על השאלות הללו.
נניח שה-Outlike שלנו מדבר עם השרת שלנו, שחושף API (כמו כל תוכנה מודרנית). מה קורה כשהאפליקציה עובדת On Prem, ומול הענן? מה קורה עם השרת עובד עם איזשהו -Gateway – האם הביצועים אותו דבר? מה המשמעות של timeouts וניתוקים בכל המקרים האלה - האם זו אותה התנהגות?
האם המערכת מפעילה caching? ולפי איזו מדיניות מנקים מידע שנשמר ב-cache? האם רואים הבדל בשימוש ב-cache בתסריטים השונים?
עוד דבר שקשור למבנה הוא תצורה – האם אפשר להריץ את ה-Outlike שלנו על טלפון או שעון? מה מגבלות הזיכרון שצריך להתחשב בהן?
נוכל לשאול את השאלות, רק אם יש לנו מידע על המבנה. לשאלות האלה יש תשובות שמעניינות אותנו (חלקן יותר מאחרות). שימו לב שהשאלות (ולכן מקרי הבדיקה) נובעות ממבנה המוצר. למעשה, ההבנה של הארכיטקטורה, ה-design ואפילו הקוד, יכולים לכוון אותנו למקרי בדיקה נוספים.
יותר מזה ידע על הארכיטקטורה יכול לתת לנו כיווני בדיקה שלא חשבנו עליהם. נניח שהשרת עוד לא נבנה, נוכל לבדוק את ה-client מול סימולטור. אם השרת חושף API אפשר להשתמש בכלי כמו WireMock. אפשר לחשוב על בדיקות בטיחות ע"י sniffing רק מידע על המבנה.
נמשיך.
2. Functionality. האמת שעל נושא זה אין לי מה להרחיב. על רוב מה שממילא אנחנו חושבים בבדיקות זה פונקציונליות. לשלוח מייל, לקבל, לערוך, למחוק – פונקציונליות היא דיון בפני עצמו, ובהתאם למוצר. ובמוצר שלכם אתם הרי מומחים. אז הרשו לי לקפוץ לנושא הבא, שהוא סוג של הרחבה לנושא הפונקציונליות.
3. Data. נתונים יכולים להיות כל דבר שאנחנו שולחים, מקבלים, מייצאים, שומרים ומייבאים.. עם כל אלה אפשר לשחק ולבדוק מה קורה אם...
נתחיל עם המייל שלנו – עם קובץ מצורף, בלי קובץ, עם תוכן ריק, בלי כותרת, כותרת בערבית, תוכן באנגלית, וכל קומבינציה שלהם.
נתונים כמובן קשורים לפונקציונליות. המטרה של ההפרדה היא רק לאפשר חשיבה מכיוון אחר. זה לא חשוב מתי חשבתם על מקרי הבדיקה (מייל ללא כותרת – זה פונקציונליות או נתונים?) – העיקר שחשבתם על זה.
ה-client שלנו קורא ל-API של השרת. מה קורה כשאנחנו שולחים ל-API גוף בפורמט JSON/XML וסתם טקסט? האם הוא יקבל את זה? מה הוא יחזיר? ובמקרי שגיאה? והאם זה תמיד נכון?
כששמרתי את המייל שלי, האם אני יכול לקרוא אותו שוב? גם בגרסה מתקדמת של Outlike? ומה לגבי גרסה מוקדמת? האם מעבד התמלילים Weird יוכל לקרוא אותו?
ומה לגבי מסד הנתונים עצמו? איך המידע נשמר? מה קורה אם הוא נמחק? כי לפעמים מחיקה עדיין משאירה אותו (באפליקציות שהן regulated מידע לא ממש נמחק, הוא רק מסומן ככזה), ואיך מוציאים מידע כזה?
מה קורה כשמסד הנתונים ריק? ומה קורה כשהוא מתמלא? אפילו שאלות של ביצועים קשורות לנתונים. האם המידע נדחס? אם כן, האם הוא נפרש נכון? איך יודעים שהדחיסה עובדת נכון?
יש הרבה שאלות מעבר ל-valid data שאפשר לשאול, ולבדוק את ההתנהגות.
4. Interface. בד"כ הדבר שנשאל לגבי ממשק הוא web או mobile. האם נראה אותה התנהגות? אבל ממשקים יש הרבה. לדוגמא, אם יש command line האם הוא מתנהג כמו קריאת API? האם השרת שלנו עונה באותה צורה לכולם?
לדוגמא, Weird מאפשר לערוך את המייל, ו-PowerPint מאפשר לשלוח מייל אוטומטי להזמנה לפאב. את כל ההתקשרויות האלה נרצה לבדוק. כולל מה קורה כשהן לא עובדות. מה קורה אם Weird לא מותקן? האם Weird מגרסה ישנה, עובד נכון עם ה-Outlike המודרני שלנו? ועד איזו גרסה?
בדרך כלל אנחנו חושבים על ממשקים כאלה. אבל יש נוספים – פרוטוקולים שונים מאפשרים התחברות. לדוגמא, השעון של Outlike נלקח משירות השעון העולמי. מה קורה כשהקשר הזה מנותק? אחד הפיצ'רים החדשים של Outlike, הוא שימוש בשירות חיצוני מבוסס AI לכתיבת מיילים אוטומטים. מה קורה כשהשירות לא עובד? וכשהקשר מתחדש? ואם לא שילמנו את החשבון עבור שירותי הפרמיום שלו, ושונמכנו לשירות החינמי, איך נראית האינטגרציה אז?
גם כאן אפשר לחשוב על דברים חופפים מאזורים שכבר הכרנו – פונקציונליות, מבנה או נתונים. אבל כמו שאמרנו, זה פחות חשוב איך הגענו לשאלות האלה. מה שחשוב שהעלנו אותן.
5. Platform. תחת הקטגוריה הזו אפשר לחשוב על הסביבה שבה רצה האפליקציה. Windows או Linux? האם זה רץ אותו דבר? אם לא, מה ההבדלים?
כמובן שאת ה-platform אפשר לקחת גם לכיוון של רכיבים. אינטגרציה קשורה לא רק בממשקים חיצוניים. פנימית, המוצר שלנו בנוי על רכיבים שלא אנחנו בנינו. כמו ה-Database וספריות כמו: react ו-node.
אפילו שפת התכנות היא לא שלנו. לכל אחד מאלה יש גרסה מסוימת, והמוצר שלנו תלוי בהם. הידע של תמיכה בגרסאות של תת מוצרים, חבילות, ואפילו קומפיילר יכול להשפיע על הבדיקות שלנו.
סביבת הבנייה והריצה יכולות להשפיע על הביצועים (מישהו אמר works on my machine?). כשאנחנו מדברים על הרצה ב-containers, גם יש משמעות להרצה מקבילית, ניחשף לעולם חדש של "כמעט". הנתונים זמינים כמעט בכל ה-instances. כמעט השלמנו את כל התהליך. ההודעה האחרונה תכף מגיעה. הרבה פעמים, אנחנו לא בודקים בסביבות ממוקבלות, אבל זו לא סיבה לא לנסות (או לבדוק ב-production, אבל זה כבר סיפור אחר).
מה קורה כשרץ אנטי-וירוס ברקע – האם הוא משפיע על התנהגות של Outlike? האם הוא בודק את הקבצים המצורפים? מה קורה כשהוא מצא וירוס? האם נראה אותם ביצועים עבור כל תוכנת אנטי-וירוס?
6. Operation. נהוג לומר שלקוד יש 3 מאפיינים. איך הוא כתוב (מעולמות הקוד הנקי עד legacy), מה הוא עושה (פונקציונלית) ואיך הוא רץ. במאפיין הראשון נגענו קצת ב-structure. בשני ב-functionality. והנה הגענו לשלישי.
אפשר להסתכל על שימוש בקוד, פיצ'ר או כל המוצר. שימושים שונים של אותה פונקציונליות
ה-Outlike שלנו, עובד כמובן לפי הרשאות משתמש. אותו קוד מופעל עבור משתמש רגיל ועבור admin. אבל לא בהכרח עם אותה תוצאה. זוכרים את עניין המחיקה, אז משתמש רגיל מוחק "בכאילו", ו-admin באמת.
ניקח את זה לעולם של API. אותו API יכול להיות כתוב בצורה אחת, אבל מופעל בצורה אחרת. אם יש שדות authentication ב-header, שרת יכול להחליט אם ואיך להתייחס אליהם. לפעמים זה אפילו לא קוד שלנו, כי ה-gateway מחליט. ולפעמים זה כן הקוד שלנו.
מה קורה כאשר אותה פעולה מה-UI, נעשית ע"י job אוטומטי, האם תהיה לה אותה תוצאה? תחת המשקפיים של Operation, אנחנו שואלים על התנהגות פונקציונלית תחת הקשרים השונים. מי המשתמש, צורת הרצה, עומס או כולם ביחד.
7. Time. השפעה של זמן יכולה להיות ב-29 בפברואר, או במעבר לשעון קיץ. אבל זה גם יכול להיות מה שקורה ב-Black Friday. האם השרת יעמוד בעומס הקניות של הלקוחות? מה קורה באותו Black Friday כשהמסך לא מגיב?
אבל "זמן" זה לא רק תלות בזמן. זה יכול להיות גם תדירות. מה קורה עם אותו API נקרא מהר מאד 20 פעם על אותה מכונה? מה קורה אם יש פניה לאותו API בעומס של 5000 פניות באותו רגע?
ומה קורה אם אני משאיר את Outlike פתוח לשבוע? האם כשאחזור מהחופשה הוא עדיין יעבוד, או שהמחשב כולו יהיה תקוע?
כשאנחנו חושבים על זמן, יש הרבה אלמנטים (חלקם פונקציונליים) שהם תוצאה של המתנה, timeouts, תדירות ו-delays. וככל שחושבים יותר, נרצה תשובות על השאלות.
כפי שאתם רואים, SFDIPOT זה כלי לא רע לחשוב על מקרים שונים של בדיקות מערכת. בעזרת "הפרד ומשול" אפשר להתמקד באספקטים שונים של המערכת ולשאול שאלות לעומק. בהתאם לעניין שיש לנו בשאלות, ניתן לבחור במה להתמקד בבדיקות. בדוגמה שלנו, ניתחנו את Outlike מכל מיני כיוונים, כולל שימושים שונים, התייחסות למבנה האפליקציה ואיך היא מתנהגת תחת תנאים שונים.
שמתם לב שרוב הזמן דיברתי על "מוצר". למעשה, את השיטה הזו אפשר להפעיל על דברים בכל סדר גודל מערכת או תת מערכת, פיצ'ר או אפילו קריאת API