הקטגוריה הזו של בדיקות אינסטרומנטציה לא שונה בהרבה מבדיקות שמיועדות לאפליקציות רגילות ל-Android. חשוב לציין שאפליקציית הבדיקה שכוללת את המכשור צריכה להיות חתומה באותו אישור כמו האפליקציה שהיא מיועדת לה.
שימו לב: במדריך הזה אנחנו מניחים שיש לכם כבר ידע מסוים בתהליך העבודה של עץ המקור של הפלטפורמה. אם לא, כדאי לעיין בדרישות. הדוגמה שמוסברת כאן היא כתיבה של בדיקת אינסטרומנטציה חדשה עם חבילת יעד שהוגדרה בחבילת אפליקציית הבדיקה שלה. אם אתם לא מכירים את המושג, כדאי לקרוא את ההקדמה לבדיקות פלטפורמה.
במדריך הזה נשתמש בבדיקה הבאה כדוגמה:
- frameworks/base/packages/Shell/tests
מומלץ לעיין בקוד כדי לקבל מושג כללי לפני שממשיכים.
קובעים את מיקום המקור
מכיוון שבדיקת אינסטרומנטציה תכוון לאפליקציה, המוסכמה היא למקם את קוד המקור של הבדיקה בספרייה tests מתחת להרמה הבסיסית (root) של ספריית קובצי המקור של הרכיב בעץ המקור של הפלטפורמה.
אפשר לקרוא עוד על מיקום המקור בדוגמה מקצה לקצה לבדיקות עם הגדרה עצמית.
קובץ מניפסט
בדומה לאפליקציה רגילה, לכל מודול של בדיקת אינסטרומנטציה נדרש קובץ מניפסט. אם קוראים לקובץ AndroidManifest.xml ומספקים אותו לצד Android.mk במודול הבדיקה, הוא ייכלל אוטומטית ב-makefile הראשי של BUILD_PACKAGE.
לפני שממשיכים, מומלץ מאוד לעיין בסקירה הכללית של קובץ המניפסט של האפליקציה.
במאמר הזה מוצגת סקירה כללית של רכיבים בסיסיים בקובץ מניפסט והפונקציות שלהם.
אפשר לגשת לגרסה האחרונה של קובץ המניפסט לשינוי לדוגמה ב-Gerrit בכתובת: https://android.googlesource.com/platform/frameworks/base/+/android17-release/packages/Shell/tests/AndroidManifest.xml
לנוחותכם, הנה תמונת מצב:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.shell.tests">
<application>
<uses-library android:name="android.test.runner" />
<activity
android:name="com.android.shell.ActionSendMultipleConsumerActivity"
android:label="ActionSendMultipleConsumer"
android:theme="@android:style/Theme.NoDisplay"
android:noHistory="true"
android:excludeFromRecents="true">
<intent-filter>
<action android:name="android.intent.action.SEND_MULTIPLE" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="*/*" />
</intent-filter>
</activity>
</application>
<instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
android:targetPackage="com.android.shell"
android:label="Tests for Shell" />
</manifest>
כמה הערות על קובץ המניפסט:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.shell.tests">
מאפיין package הוא שם חבילת האפליקציה: זהו המזהה הייחודי שמשמש את מסגרת האפליקציה ל-Android לזיהוי אפליקציה (או בהקשר הזה: אפליקציית הבדיקה שלכם). כל משתמש במערכת יכול להתקין רק אפליקציה אחת עם שם החבילה הזה.
מכיוון שמדובר בחבילת אפליקציה לבדיקה, שאינה תלויה בחבילת האפליקציה שנבדקת, צריך להשתמש בשם חבילה שונה. אחת מהמוסכמות הנפוצות היא להוסיף את הסיומת .test.
בנוסף, מאפיין package זה זהה למה שמוחזר על ידי ComponentName#getPackageName(), וגם למה שמשמש לאינטראקציה עם פקודות משנה שונות של pm באמצעות adb shell.
חשוב גם לציין שלמרות ששם החבילה בדרך כלל זהה לסגנון של שם חבילה ב-Java, בפועל אין לו קשר רב אליו. במילים אחרות, חבילת האפליקציה (או הבדיקה) יכולה להכיל מחלקות עם שמות חבילות כלשהם, אבל מצד שני, אפשר לבחור בפשטות ולתת לחבילת ה-Java ברמה העליונה באפליקציה או בבדיקה שם זהה לשם חבילת האפליקציה.
<uses-library android:name="android.test.runner" />
הדבר נדרש לכל בדיקות המכשור, כי המחלקות הקשורות ארוזות בקובץ ספריית jar של מסגרת נפרדת, ולכן נדרשים רשומות נוספות של classpath כשחבילת הבדיקה מופעלת על ידי מסגרת האפליקציה.
android:targetPackage="com.android.shell"
ההגדרה הזו קובעת את חבילת היעד של המדידה כ-com.android.shell.
כשמפעילים את המכשור באמצעות הפקודה am instrument, המסגרת מפעילה מחדש את התהליך com.android.shell ומזריקה קוד מכשור לתהליך לצורך ביצוע הבדיקה. המשמעות היא גם שלקוד הבדיקה תהיה גישה לכל המופעים של המחלקה שפועלים באפליקציה שנבדקת, והוא יוכל לשנות את המצב בהתאם לנקודות הבדיקה שמוצגות.
קובץ תצורה פשוט
לכל מודול בדיקה חדש צריך להיות קובץ תצורה שמנחה את מערכת ה-build באמצעות מטא-נתונים של המודול, יחסי תלות בזמן הקומפילציה והוראות אריזה. ברוב המקרים, האפשרות של קובץ Blueprint שמבוסס על Soong מספיקה. פרטים נוספים זמינים במאמר בנושא הגדרה פשוטה של בדיקה.
קובץ תצורה מורכב
בנוסף, כדי לבצע בדיקות מורכבות יותר, צריך לכתוב קובץ הגדרות בדיקה עבור מסגרת הבדיקה של Android, Trade Federation.
בהגדרת הבדיקה אפשר לציין אפשרויות מיוחדות להגדרת המכשיר וארגומנטים שמוגדרים כברירת מחדל כדי לספק את מחלקת הבדיקה.
אפשר לגשת לגרסה העדכנית של קובץ התצורה של שינוי לדוגמה ב-Gerrit בכתובת: frameworks/base/packages/Shell/tests/AndroidTest.xml
לנוחותכם, הנה תמונת מצב:
<configuration description="Runs Tests for Shell.">
<target_preparer class="com.android.tradefed.targetprep.TestAppInstallSetup">
<option name="test-file-name" value="ShellTests.apk" />
</target_preparer>
<option name="test-suite-tag" value="apct" />
<option name="test-tag" value="ShellTests" />
<test class="com.android.tradefed.testtype.AndroidJUnitTest" >
<option name="package" value="com.android.shell.tests" />
<option name="runner" value="android.support.test.runner.AndroidJUnitRunner" />
</test>
</configuration>
כמה הערות על קובץ ההגדרה של הבדיקה:
<target_preparer class="com.android.tradefed.targetprep.TestAppInstallSetup">
<option name="test-file-name" value="ShellTests.apk"/>
</target_preparer>
הפקודה הזו אומרת ל-Trade Federation להתקין את ShellTests.apk במכשיר היעד באמצעות target_preparer שצוין. יש הרבה כלי הכנה ליעדים שזמינים למפתחים ב-Trade Federation, ואפשר להשתמש בהם כדי לוודא שהמכשיר מוגדר בצורה נכונה לפני הפעלת הבדיקה.
<test class="com.android.tradefed.testtype.AndroidJUnitTest">
<option name="package" value="com.android.shell.tests"/>
<option name="runner" value="android.support.test.runner.AndroidJUnitRunner"/>
</test>
הפרמטר הזה מציין את מחלקת הבדיקה של Trade Federation שבה יש להשתמש כדי להריץ את הבדיקה, ומעביר את החבילה במכשיר להרצה ואת מסגרת ההרצה של הבדיקה, שהיא JUnit במקרה הזה.
מידע נוסף על הגדרות של מודול בדיקה
תכונות של JUnit4
השימוש בספריית android-support-test ככלי להרצת בדיקות מאפשר אימוץ של מחלקות בדיקה חדשות בסגנון JUnit4, ושינוי Gerrit לדוגמה מכיל שימוש בסיסי מאוד בתכונות שלה.
קוד המקור העדכני של שינוי לדוגמה ב-Gerrit זמין בכתובת: frameworks/base/packages/Shell/tests/src/com/android/shell/BugreportReceiverTest.java
דפוסי בדיקה הם בדרך כלל ספציפיים לצוותי רכיבים, אבל יש כמה דפוסי שימוש שימושיים באופן כללי.
@SmallTest
@RunWith(AndroidJUnit4.class)
public final class FeatureFactoryImplTest {
הבדל משמעותי ב-JUnit4 הוא שלא נדרש יותר שהבדיקות יירשו ממחלקת בדיקה בסיסית משותפת. במקום זאת, כותבים בדיקות במחלקות Java רגילות ומשתמשים בהערות כדי לציין הגדרות ומגבלות מסוימות של הבדיקה. בדוגמה הזו, אנחנו מציינים שהמחלקה הזו צריכה לפעול כבדיקת Android JUnit4.
ההערה @SmallTest מציינת גודל בדיקה לכל מחלקת הבדיקה: כל שיטות הבדיקה שנוספו למחלקת הבדיקה הזו מקבלות בירושה את הערת גודל הבדיקה הזו.
הגדרה לפני מחלקת הבדיקה, ניקוי אחרי הבדיקה וניקוי אחרי מחלקת הבדיקה:
בדומה לשיטות setUp ו-tearDown ב-JUnit4.
ההערה Test משמשת להערות על הבדיקה בפועל.
@Before
public void setup() {
...
@Test
public void testGetProvider_shouldCacheProvider() {
...
ההערה @Before משמשת בשיטות של JUnit4 כדי לבצע הגדרה לפני הבדיקה.
למרות שלא נעשה בו שימוש בדוגמה הזו, יש גם @After לניקוי אחרי הבדיקה.
באופן דומה, אפשר להשתמש בהערות @BeforeClass ו-@AfterClass במתודות של JUnit4 כדי לבצע הגדרה לפני הפעלת כל הבדיקות בכיתת בדיקה, ופירוק לאחר מכן. שימו לב: שיטות ההגדרה וההסרה של היקף המחלקה חייבות להיות סטטיות.
בנוגע לשיטות הבדיקה, בניגוד לגרסה קודמת של JUnit, כבר לא צריך להתחיל את שם השיטה ב-test, אלא כל אחת מהן צריכה להיות מסומנת ב-@Test. כמו תמיד, שיטות בדיקה צריכות להיות ציבוריות, לא להצהיר על ערך החזרה, לא לקבל פרמטרים ולהיות מסוגלות להחזיר חריגים.
Context context = InstrumentationRegistry.getTargetContext();
מכיוון שבדיקות JUnit4 לא דורשות יותר מחלקת בסיס משותפת, אין יותר צורך להשיג מופעים של Context באמצעות getContext() או של getTargetContext() באמצעות שיטות של מחלקת בסיס. במקום זאת, רץ הבדיקות החדש מנהל אותם באמצעות InstrumentationRegistry, שבו מאוחסן ההגדרה ההקשרית והסביבתית שנוצרה על ידי מסגרת המכשור. במסגרת השיעור הזה, אפשר גם להתקשר אל:
-
getInstrumentation(): המכונה למחלקהInstrumentation -
getArguments(): הארגומנטים בשורת הפקודה שמועברים אלam instrumentדרך-e <key> <value>
פיתוח ובדיקה באופן מקומי
בתרחישים הנפוצים ביותר, כדאי להשתמש ב-Atest.
במקרים מורכבים יותר שדורשים התאמה אישית נרחבת, צריך לפעול לפי ההוראות להטמעה.