דוגמה לטירגוט אפליקציה

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

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

במדריך הזה נשתמש בבדיקה הבאה כדוגמה:

  • frameworks/base/packages/Shell/tests

מומלץ לעיין בקוד כדי לקבל מושג כללי לפני שממשיכים.

קובעים את מיקום המקור

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

בדוגמה מקצה לקצה לבדיקות עם הטמעה עצמית יש דיונים נוספים על מיקום המקור.

קובץ מניפסט

בדומה לאפליקציה רגילה, לכל מודול של בדיקת מכשור נדרש קובץ מניפסט. אם נותנים לקובץ את השם AndroidManifest.xml ומספקים אותו לצד Android.mk במודול הבדיקה, הוא ייכלל אוטומטית בקובץ ה-makefile הראשי של BUILD_PACKAGE.

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

במאמר הזה מוצגת סקירה כללית של רכיבים בסיסיים בקובץ מניפסט והפונקציות שלהם.

הגרסה האחרונה של קובץ המניפסט לשינוי לדוגמה ב-Gerrit זמינה בכתובת: https://android.googlesource.com/platform/frameworks/base/+/android16-qpr2-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 של ספריית framework נפרדת, ולכן נדרשים רשומות נוספות של classpath כשחבילת הבדיקה מופעלת על ידי framework של האפליקציה.

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 רגילות ומשתמשים בהערות כדי לציין הגדרות ומגבלות מסוימות של בדיקות. בדוגמה הזו, אנחנו מציינים שהמחלקה הזו צריכה לפעול כבדיקת JUnit4 של Android.

ההערה @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.

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