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

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

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

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

  • frameworks/base/packages/Shell/tests

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

בחירת מיקום המקור

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

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

קובץ מניפסט

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

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

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

ניתן לגשת לגרסה האחרונה של קובץ המניפסט של שינוי ה-Grit לדוגמה בכתובת: https://android.googlesource.com/platform/frameworks/base/+/main/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" />

הדבר נדרש לכל בדיקות ה-Instrumentation כי הכיתות הקשורות ארוזות בקובץ ספרייה נפרד של framework jar, ולכן נדרשות רשומות נוספות ב-classpath כשחבילת הבדיקה מופעלת על ידי מסגרת האפליקציה.

android:targetPackage="com.android.shell"

הפקודה הזו מגדירה את חבילת היעד של הכלי למדידה כ-com.android.shell. כשמפעילים את האינסטרומנטציה באמצעות הפקודה am instrument, המסגרת מפעילה מחדש את התהליך com.android.shell ומחדירה לתוכו את קוד האינסטרומנטציה לצורך ביצוע הבדיקה. המשמעות היא גם שלקוד הבדיקה תהיה גישה לכל המופעים של הכיתה שפועלים באפליקציה שנבדקת, ויכול להיות שהוא יוכל לשנות את המצב בהתאם ל-test hooks שנחשפו.

קובץ תצורה פשוט

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

קובץ תצורה מורכב

כדי לבצע בדיקות מורכבות יותר, צריך גם לכתוב קובץ תצורה לבדיקה של מסגרת הבדיקה של 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 שרוצים להשתמש בו כדי להריץ את הבדיקה, ומעבירים את החבילה במכשיר שרוצים להריץ אותה ואת מסגרת ה-test runner, שהיא JUnit במקרה הזה.

כאן אפשר למצוא מידע נוסף על הגדרות של מודול בדיקה

תכונות של JUnit4

השימוש בספריית android-support-test כהרצת בדיקה מאפשר שימוש במחלקות חדשות בסגנון JUnit4, ושינוי המדגם כולל שימוש בסיסי מאוד בתכונות שלו.

אפשר לגשת לקוד המקור העדכני ביותר לשינוי ה-Grit לדוגמה בכתובת: frameworks/base/packages/Shell/tests/src/com/android/shell/BugreportReceiverTest.java.

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

@SmallTest
@RunWith(AndroidJUnit4.class)
public final class FeatureFactoryImplTest {

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

בהערה @SmallTest צוין גודל בדיקה לכל מחלקה של הבדיקה: כל שיטות הבדיקה שנוספו לכיתת הבדיקה הזו מקבלות בירושה את ההערה של גודל הבדיקה. לפני הגדרת הכיתה, לאחר הבדיקה ואחריה הפריקה של הכיתה אחרי הבדיקה: דומה ל-methods 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() דרך methods של מחלקת הבסיס. במקום זאת, ההרצה של הבדיקה החדשה מנהלת אותן באמצעות InstrumentationRegistry כאשר הגדרה לפי הקשר וסביבתית שנוצרה על ידי מסגרת האינסטרומנטציה נשמרת. אפשר גם להשתמש בכיתה הזו כדי לבצע את הפונקציות הבאות:

  • getInstrumentation(): המופע למחלקה Instrumentation
  • getArguments(): הארגומנטים בשורת הפקודה שהועברו אל am instrument דרך -e <key> <value>

פיתוח ובדיקה באופן מקומי

בתרחישים הנפוצים ביותר לדוגמה, כדאי להשתמש ב-Atest.

במקרים מורכבים יותר שדורשים התאמה אישית משמעותית יותר, פועלים לפי הוראות המדידה.