"אי אפשר לבדוק קוד שרץ על חומרה" — באמת?

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

למה זה באמת קשה יותר מבתוכנה רגילה

  • תלות ישירה בחומרה. קוד שכותב לרגיסטר של המיקרו-בקר לא ירוץ על מחשב הפיתוח — הוא בכלל לא יתקמפל לארכיטקטורה אחרת בלי הכנה.
  • ספריות יצרן (HAL) בכל מקום. כשהלוגיקה העסקית קוראת ישירות לפונקציות של יצרן השבב, אי אפשר לבודד אותה.
  • תזמון ופסיקות. התנהגות שתלויה בטיימרים, ב-ISR ובמצבי ריצה מקביליים קשה לשחזר בסביבה סינתטית.
  • משאבים מוגבלים. להריץ Framework בדיקות על 32KB זיכרון — לא ריאלי.

המפתח: הפרדה בין לוגיקה לחומרה

הפתרון לכל הבעיות האלה אחד — שכבת הפשטה. במקום שהלוגיקה תקרא ישירות ל-HAL, היא עובדת מול ממשק מופשט ("קרא טמפרטורה", "שלח הודעה"), ומאחורי הממשק יש שני מימושים: אחד אמיתי שרץ על המוצר, ואחד מדומה (Mock) שרץ בבדיקות. ברגע שההפרדה קיימת, מתברר שרוב הקושחה בכלל לא "קוד חומרה": מכונות מצבים, פענוח פרוטוקולים, לוגיקת התראות, חישובי כיול — הכול לוגיקה טהורה שנבדקת מצוין על המחשב. לא במקרה כתבנו שתכנון נכון של מכונת מצבים בקושחה הוא לב המוצר — מכונת מצבים מופרדת היטב היא גם הקוד הכי קל לבדיקה: בדיקה שמזינה רצף אירועים ומוודאת את המצב הסופי רצה באלפיות שנייה, ומכסה תרחישים שכמעט בלתי אפשרי לשחזר על לוח אמיתי — ניתוקים פתאומיים, רצפי קלט חריגים ומקרי קצה של Timeout. שפת הפיתוח משפיעה גם היא על קלות הבידוד — ראו את ההשוואה במאמר פיתוח embedded ב-C או ב-Rust.

הכלים והתהליך בפועל

עולם ה-embedded פיתח כלים ייעודיים לזה: Frameworks קלים כמו Unity ו-CppUTest, וכלי עזר שמייצרים Mocks אוטומטית מקבצי כותרת. את הבדיקות מריצים כחלק מתהליך הבנייה על מחשב הפיתוח — קומפילציה ל-Host במקום ל-Target — כך שכל בדיקה רצה באלפיות שנייה, בלי צריבה ובלי חומרה על השולחן. משם הדרך קצרה לאינטגרציה רציפה: כל Commit מריץ את כל הבדיקות אוטומטית, ורגרסיה נתפסת תוך דקות במקום להתגלות אצל לקוח. הקמת סביבה כזו היא חלק מהחלטות התשתית של הפרויקט, שסקרנו במאמר על בחירת סביבת פיתוח ו-Toolchain. מדד כיסוי (Coverage) עוזר לכוון את המאמץ — לא כדי לרדוף אחרי מאה אחוז, אלא כדי לוודא שהמודולים הקריטיים באמת מכוסים: פענוח פרוטוקול, ניהול צריכת חשמל, לוגיקת בטיחות. ובפרויקטים מפוקחים, כמו מכשור רפואי, בדיקות מתועדות הן דרישה רגולטורית של ממש — לא רק תרבות פיתוח טובה.

מה בדיקות יחידה לא יתפסו

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

ההשקעה שמחזירה את עצמה

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

רוצים להפוך רעיון למוצר? צרו קשר עם צוות פרוג'קטס האוס בע"מ – טלפון: 054-8936922 | דוא"ל: info@projects-house.com – ונשמח ללוות אתכם משלב הרעיון ועד המדף.