זהו מבוא קצר למיפוי בדיקות והסבר על האופן שבו ניתן להתחיל להגדיר בדיקות בקלות ב-Android Open Source Project (AOSP).
מידע על מיפוי בדיקות
מיפוי הבדיקות הוא גישה המבוססת על Gerrit, שמאפשרת למפתחים ליצור כללים לבדיקה לפני ואחרי השליחה ישירות בעץ המקור של Android, ולהשאיר את ההחלטות לגבי ההסתעפויות והמכשירים לבדיקה בתשתית הבדיקה בעצמם. ההגדרות של מיפוי הבדיקות הן קובצי JSON בשם TEST_MAPPING, שאפשר למקם בכל ספריית מקור.
Atest יכול להשתמש בקובצי ה-TEST_MAPPING כדי להריץ בדיקות טרום-שליחה בספריות המשויכות. בעזרת מיפוי בדיקות, אפשר להוסיף את אותה קבוצת בדיקות כדי לשלוח מראש את הבדיקות באמצעות שינוי פשוט בתוך עץ המקור של Android.
דוגמאות:
הוספת בדיקות לשליחה מראש אל TEST_MAPPING עבור services.core
הוספת בדיקות שנשלחו מראש אל TEST_MAPPING עבור כלים או דקסטר שימוש בייבוא
מיפוי הבדיקות מסתמך על Trade Federation (TF) Test Harness כדי לבצע את הבדיקות ועל דיווח על תוצאות.
הגדרה של קבוצות בדיקה
בודקים בדיקות של קבוצות מיפוי באמצעות קבוצת בדיקה. השם של קבוצת הבדיקה יכול להיות כל מחרוזת. לדוגמה, אפשר להגדיר presubmit לקבוצת בדיקות שירוצו בזמן אימות השינויים. ניתן גם להשתמש בבדיקות postsubmit כדי לאמת את ה-builds אחרי מיזוג השינויים.
כללי סקריפט לבניית חבילה
כדי ש-Trade Federation Test Harness יריץ את המודולים לבדיקה של מיפוי ל-build נתון, המודולים האלה חייבים להגדיר את test_Suites ל-Soong או ל-LOCAL_COMPATIBILITY_SUITE בשביל Make לאחת משתי הסוויטות הבאות:
- General-tests – בדיקות שלא תלויות בפונקציונליות ספציפית למכשיר (למשל, חומרה ספציפית לספק שלא מותקנת ברוב המכשירים). רוב הבדיקות צריכות להיות בחבילת הבדיקות הכלליות, גם אם הן ספציפיות ל-ABI אחד, או לביט מסוים או לתכונות חומרה כמו HWASan (יש יעד נפרד של test_Suites לכל ממשק ABI), וגם אם הן צריכות לפעול במכשיר מסוים.
- device-tests – בדיקות שתלויות בפונקציונליות ספציפית למכשיר.
בדרך כלל הבדיקות האלה יימצאו מתחת ל-
vendor/
. מכיוון ש'ספציפי למכשיר' לא מתייחס לפונקציונליות של ABI או SoC שמכשירים אחרים עשויים להכיל, או לא, אלא רק לפונקציונליות שייחודית למכשיר a, היא רלוונטית רק לבדיקות של JUnit באותה מידה כמו בדיקות מקוריות של GTest (ש בדרך כלל אמורות להיותgeneral-tests
גם אם הן ספציפיות ל-ABI).
לדוגמה:
Android.bp: test_suites: ["general-tests"],
Android.mk: LOCAL_COMPATIBILITY_SUITE := general-tests
הגדרת בדיקות להפעלה בחבילת בדיקות
כדי להריץ בדיקה בתוך חבילת בדיקות:
- לא יכול להיות שום ספק build.
- חייבת לנקות אחרי שהסתיימה, לדוגמה, על ידי מחיקה של כל הקבצים הזמניים שנוצרו במהלך הבדיקה.
- לשנות את הגדרות המערכת לערך ברירת המחדל או הערך המקורי.
- לא צריך להניח שהמכשיר במצב מסוים, למשל 'מוכן לרמה הבסיסית' (root). כדי להריץ את רוב הבדיקות, לא נדרשת הרשאת הרמה הבסיסית (root). אם הבדיקה חייבת לדרוש שורש, צריך לציין זאת עם
RootTargetPreparer
ב-AndroidTest.xml
שלה, כמו בדוגמה הבאה:
<target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer"/>
יצירת קובצי מיפוי לבדיקה
מוסיפים לספרייה שבה נדרש כיסוי בדיקה, פשוט מוסיפים קובץ JSON מסוג TEST_MAPPING, שדומה לדוגמה שלמטה. הכללים האלה יבטיחו שהבדיקות ירוצו לבדיקות טרום-שליחה, בכל פעם שנוגעים בקבצים בספרייה הזו או בכל אחת מספריות המשנה שלה.
מעקב אחר דוגמה
הנה קובץ TEST_MAPPING
לדוגמה (הוא בפורמט JSON אבל עם תגובות נתמכות):
{
"presubmit": [
// JUnit test with options and file patterns.
{
"name": "CtsWindowManagerDeviceTestCases",
"options": [
{
"include-annotation": "android.platform.test.annotations.RequiresDevice"
}
],
"file_patterns": ["(/|^)Window[^/]*\\.java", "(/|^)Activity[^/]*\\.java"]
},
// Device-side GTest with options.
{
"name" : "hello_world_test",
"options": [
{
"native-test-flag": "\"servicename1 servicename2\""
},
{
"native-test-timeout": "6000"
}
]
}
// Host-side GTest.
{
"name" : "net_test_avrcp",
"host" : true
}
],
"postsubmit": [
{
"name": "CtsWindowManagerDeviceTestCases"
}
],
"imports": [
{
"path": "frameworks/base/services/core/java/com/android/server/am"
}
]
}
הגדרת מאפיינים
בדוגמה שלמעלה, presubmit
ו-postsubmit
הם השמות של כל קבוצת בדיקה. מידע נוסף על קבוצות בדיקה זמין במאמר הגדרה של קבוצות בדיקה.
אפשר להגדיר את השם של מודול הבדיקה או של שם הבדיקה של השילוב של Trade Federation (נתיב המשאב לקובץ ה-XML לבדיקה, למשל uiautomator/uiautomator-demo) כערך של המאפיין name
. שימו לב שהשדה name לא יכול להשתמש במחלקה name
או בשיטת הבדיקה name
. כדי לצמצם את מספר הבדיקות להרצה, תוכלו להשתמש באפשרויות כמו include-filter
כאן. ראו (שימוש לדוגמה במסנן).
הגדרת המארח של הבדיקה מציינת אם הבדיקה היא בדיקה ללא מכשיר שפועלת על המארח או לא. ערך ברירת המחדל הוא false, כלומר כדי לבצע את הבדיקה נדרשת הרצה של מכשיר. סוגי הבדיקות הנתמכים הם HostGTest לקבצים בינאריים של GTest, ו-HostTest לבדיקות JUnit.
המאפיין file_patterns מאפשר להגדיר רשימה של מחרוזות ביטוי רגולרי (regex) כך שיתאימו לנתיב היחסי של כל קובץ קוד מקור (ביחס לספרייה שמכילה את קובץ TEST_MAPPING). בדוגמה שלמעלה, הבדיקה של CtsWindowManagerDeviceTestCases
תפעל בשליחה מראש רק כשקובץ ג'אווה כלשהו מתחיל ב-window או Activity, שקיימים באותה ספרייה של הקובץ TEST_MAPPING או בכל אחת מספריות המשנה שלו, משתנה. צריך לסמן תווי לוכסן הפוך \ בתו בריחה (escape) כי הם בקובץ JSON.
המאפיין Imports מאפשר לכלול בדיקות בקובצי TEST_MAPPING אחרים בלי להעתיק את התוכן. שימו לב שקובצי ה-TEST_MAPPING בספריות ההורה של הנתיב המיובא ייכללו גם הם. מיפוי הבדיקות מאפשר ייבוא מקונן. המשמעות היא ששני קובצי TEST_MAPPING יכולים לייבא זה את זה, ומיפוי הבדיקות יכול למזג כראוי את הבדיקות שכלולות.
המאפיין options מכיל אפשרויות נוספות לשורת הפקודה של TradeFed.
כדי לקבל רשימה מלאה של האפשרויות הזמינות לבדיקה מסוימת, מפעילים:
tradefed.sh run commandAndExit [test_module] --help
לפרטים נוספים על האפשרויות הזמינות, ראו טיפול באפשרויות של TradeFed .
הרצת בדיקות באמצעות Atest
כדי להפעיל באופן מקומי את כללי הבדיקה לפני הגשה מראש:
- עוברים לספרייה שמכילה את הקובץ TEST_MAPPING.
- מריצים את הפקודה:
atest
כל הבדיקות שנשלחו מראש שהוגדרו בקובצי TEST_MAPPING בספרייה הנוכחית ובספריות ההורה שלה פועלות. Atest יאתר ויריץ שתי בדיקות להגשה מראש (A ו-B).
זו הדרך הפשוטה ביותר להריץ בדיקות לפני שליחה מראש בקובצי TEST_MAPPING בספריית העבודה הנוכחית (CWD) ובספריות ההורה. Atest יאתר את הקובץ TEST_MAPPING ב-CWD ובכל ספריות ההורה שלו וישתמש בו.
קוד המקור של המבנה
הדוגמה הבאה ממחישה איך אפשר להגדיר קובצי TEST_MAPPING בכל עץ המקור.
src
├── project_1
│ └── TEST_MAPPING
├── project_2
│ └── TEST_MAPPING
└── TEST_MAPPING
התוכן של src/TEST_MAPPING
:
{
"presubmit": [
{
"name": "A"
}
]
}
התוכן של src/project_1/TEST_MAPPING
:
{
"presubmit": [
{
"name": "B"
}
],
"postsubmit": [
{
"name": "C"
}
],
"other_group": [
{
"name": "X"
}
]}
התוכן של src/project_2/TEST_MAPPING
:
{
"presubmit": [
{
"name": "D"
}
],
"import": [
{
"path": "src/project_1"
}
]}
ציון ספריות יעד
תוכלו לציין ספריית יעד להרצת בדיקות בקובצי TEST_MAPPING בספרייה הזו. הפקודה הבאה תריץ שתי בדיקות (A, B).
atest --test-mapping src/project_1
הרצת כללים לבדיקה לאחר השליחה
אפשר להשתמש בפקודה הזו כדי להריץ את כללי הבדיקה לאחר השליחה שמוגדרים ב-TEST_MAPPING ב-src_path
(ברירת המחדל היא CWD) ובספריות ההורה שלה:
atest [--test-mapping] [src_path]:postsubmit
הרצת רק בדיקות שלא דורשות מכשיר
אפשר להשתמש באפשרות --host ל-Atest כדי להריץ רק בדיקות שהוגדרו מול המארח ולא דרושות אף מכשיר. בלי האפשרות הזו, Atest יריץ את שתי הבדיקות, את אלה שנדרשת להן מכשיר ואת אלה שפועלות על מארח ולא נדרש מכשיר. הבדיקות ירוצו בשתי חבילות נפרדות.
atest [--test-mapping] --host
זיהוי של קבוצות בדיקה
אפשר לציין קבוצות בדיקה בפקודה Atest. הפקודה הבאה תריץ את כל הבדיקות של postsubmit שקשורות לקבצים בספרייה src/project_1, שמכילה רק בדיקה אחת (C).
לחלופין, אפשר להשתמש בפונקציה :all כדי להריץ את כל הבדיקות, ללא קשר לקבוצה. הפקודה הבאה מריצים ארבע בדיקות (A, B, C, X):
atest --test-mapping src/project_1:all
לכלול ספריות משנה
כברירת מחדל, הרצת בדיקות ב-TEST_MAPPING עם Atest תריץ רק בדיקות לשליחה מראש שהוגדרו בקובץ TEST_MAPPING ב-CWD (או בספרייה הנתונה) ובספריות ההורה שלו. אם רוצים להריץ בדיקות בכל קובצי ה-TEST_MAPPING בספריות המשנה, משתמשים באפשרות --include-subdir
כדי לאלץ את הבדיקה לכלול גם את הבדיקות האלה.
atest --include-subdir
בלי האפשרות --include-subdir
, Atest יריץ רק את בדיקה א'. אם בוחרים באפשרות --include-subdir
, Atest יריץ שתי בדיקות (A ו-B).
יש תמיכה בתגובה ברמת השורה
אפשר להוסיף תגובה בפורמט //
ברמת השורה כדי לרענן את הקובץ TEST_MAPPING עם תיאור של ההגדרה הבאה. ATest ו-Commerce Federation יעבדו מראש את TEST_MAPPING לפורמט JSON תקין ללא תגובות. כדי שקובץ ה-JSON יהיה נקי וקריא, יש תמיכה רק בתגובה בפורמט //
ברמת השורה.
דוגמה:
{
// For presubmit test group.
"presubmit": [
{
// Run test on module A.
"name": "A"
}
]
}