לדלג לתוכן

פירמידת הבדיקות בבקאנד - Unit, Integration ו-E2E

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

למה בכלל צורה של פירמידה

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

הבסיס - בדיקות יחידה

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

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

האמצע - בדיקות אינטגרציה

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

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

הפסגה - בדיקות מקצה לקצה

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

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

קונוס הגלידה - כשהפירמידה הפוכה

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

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

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

לסיכום

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

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

הצטרפו לקהילה בדיסקורד