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

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

המשמעות היא שבדיקת אינסטרומנטציה לא יכולה להחדיר את עצמה ל-Android [framework], שנקרא גם שרת המערכת, לביצוע. כדי לבדוק את ה-Android , קוד הבדיקה יכול להפעיל רק פלטפורמות API ציבוריות, או פלטפורמות שנחשפו באמצעות 'שפת הגדרה של ממשק Android' AIDL בעץ המקור של הפלטפורמה. אין משמעות לטירגוט חבילה מסוימת של בדיקות לקטגוריית הבדיקות הזו. לכן מקובל ליצור מכשירים שמוצהרים כמיועדים לטרגט את חבילת אפליקציות הבדיקה שלה, כמו מוגדר בתג <manifest> משלו של AndroidManifest.xml.

בהתאם לדרישות, ניתן לבדוק חבילות אפליקציה לבדיקה בקטגוריה הזו גם:

  • מקבץ פעילויות שנדרשות לבדיקה.
  • משתפים את מזהה המשתמש עם המערכת.
  • להיות חתומות במפתח הפלטפורמה.
  • להיות יעברו הידור לפי המקור של ה-framework ולא לפי ה-SDK הציבורי.

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

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

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

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

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

בהנחה שמיקום הבסיס של מקור הרכיב הוא <component source root>, לרוב הרכיבים יש src ו-tests תיקיות מתחתיו, וחלקם קבצים נוספים כגון Android.mk (או מחולקים ל-.mk קבצים נוספים), קובץ המניפסט AndroidManifest.xml וקובץ התצורה לבדיקה AndroidTest.xml.

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

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

בלי קשר למבנה, בסופו של דבר יאכלסו את הספרייה tests או את ספריית המשנה החדשה שנוצרה, וכוללת קבצים שדומים לאלה שנכללים בה שינוי הספרייה instrumentation ב-Grit לדוגמה. הפרטים של כל אחד מהכרטיסים מוסבר בהמשך המאמר.

קובץ מניפסט

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

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

הנה קובץ AndroidManifest.xml לדוגמה:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
  android:sharedUserId="android.uid.system"
  package="android.test.example.helloworld" >

    <application>
       <uses-library android:name="android.test.runner"/>
    </application>

    <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
                     android:targetPackage="android.test.example.helloworld"
                     android:label="Hello World Test"/>

</manifest>

הערות נבחרות לגבי קובץ המניפסט:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="android.test.example.helloworld" >

המאפיין package הוא שם החבילה של האפליקציה: זהו השם הייחודי שבו נעשה שימוש ב-framework של אפליקציות Android כדי לזהות (או בהקשר זה: אפליקציית הבדיקה שלך). כל משתמש במערכת יכול להתקין רק אפליקציה אחת עם שם החבילה הזה.

בנוסף, המאפיין package זהה למה שמוחזר על ידי ComponentName#getPackageName(), וגם זה שמשתמשים בו כדי לקיים אינטראקציה עם פקודות משנה שונות של pm באמצעות adb shell.

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

android:sharedUserId="android.uid.system"

ההצהרה הזו מצהירה שבמועד ההתקנה יש להעניק לקובץ ה-APK הזה את את אותו User ID, כלומר זהות בזמן ריצה, כמו הפלטפורמה המרכזית. לתשומת ליבכם: תלויה בכך שה-APK ייחתם עם אותו אישור כמו הפלטפורמה העיקרית (ראו LOCAL_CERTIFICATE בקטע קודם), אך הם שונים של המושגים:

  • חלק מההרשאות או מממשקי ה-API מוגנים בחתימה, ולכן אישור חתימה
  • חלק מההרשאות או ממשקי ה-API דורשים את זהות המשתמש system של מבצע הקריאה החוזרת, ולכן חבילת הקריאה החוזרת צריכה לשתף את מזהה המשתמש עם system, אם היא חבילת API נפרדת מהפלטפורמה עצמה
<uses-library android:name="android.test.runner" />

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

android:targetPackage="android.test.example.helloworld"

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

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

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

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

במקרים מורכבים יותר כאלה, צריך גם לכתוב הגדרת תצורה לבדיקה עבור מסגרת הבדיקה של Android, Trade Federation (איחוד המסחר).

בהגדרות האישיות של הבדיקה אפשר לציין אפשרויות הגדרה מיוחדות של המכשיר וברירת מחדל ארגומנטים שיספקו את מחלקת המבחן. אפשר לראות את הדוגמה בכתובת /platform_testing/tests/example/instrumentation/AndroidTest.xml.

צירפנו כאן קובץ snapshot לנוחותכם:

<configuration description="Runs sample instrumentation test.">
  <target_preparer class="com.android.tradefed.targetprep.TestFilePushSetup"/>
  <target_preparer class="com.android.tradefed.targetprep.TestAppInstallSetup">
    <option name="test-file-name" value="HelloWorldTests.apk"/>
  </target_preparer>
  <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer"/>
  <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer"/>
  <option name="test-suite-tag" value="apct"/>
  <option name="test-tag" value="SampleInstrumentationTest"/>

  <test class="com.android.tradefed.testtype.AndroidJUnitTest">
    <option name="package" value="android.test.example.helloworld"/>
    <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="HelloWorldTests.apk"/>
</target_preparer>

הפקודה הזו מורה ל-Trade Federation להתקין את HelloWorldTests.apk במכשיר היעד באמצעות target_preparer שצוין. יש הרבה מהלכי הכנה זמינים למפתחים ב-Trends Federation ואפשר להשתמש בהם כדי שהמכשיר מוגדר בצורה תקינה לפני בדיקת הביצוע.

<test class="com.android.tradefed.testtype.AndroidJUnitTest">
  <option name="package" value="android.test.example.helloworld"/>
  <option name="runner" value="android.support.test.runner.AndroidJUnitRunner"/>
</test>

מציין את מחלקת הבדיקה של Trade Federation שתשמש לביצוע הבדיקה מעביר את החבילה שבמכשיר להפעלה שהיא JUnit במקרה הזה.

מידע נוסף זמין במאמר הבא: הגדרות של מודול הבדיקה

התכונות של JUnit4

שימוש בספרייה android-support-test כהרצת הבדיקה מאפשר אימוץ של פיצ'רים חדשים מחלקות המבחנים בסגנון JUnit4, והשינוי לדוגמה של גרביט כולל כמה מרכיבים בסיסיים מאוד לשימוש בתכונות שלו. אפשר לעיין בדוגמה שבכתובת /platform_testing/tests/example/instrumentation/src/android/test/example/helloworld/HelloWorldTest.java.

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

@RunWith(JUnit4.class)
public class HelloWorldTest {

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

    @BeforeClass
    public static void beforeClass() {
    ...
    @AfterClass
    public static void afterClass() {
    ...
    @Before
    public void before() {
    ...
    @After
    public void after() {
    ...
    @Test
    @SmallTest
    public void testHelloWorld() {
    ...

ההערות @Before ו-@After משמשות בשיטות של JUnit4 כדי לבצע הגדרה מוקדמת של הבדיקה וניתוק הבדיקה. באופן דומה, @BeforeClass וגם אנחנו משתמשים בהערות @AfterClass בשיטות של JUnit4 כדי לבצע הגדרה לפני ביצוע כל הבדיקות בכיתת מבחן, ולאחר מכן פריקה. שימו לב השיטות להגדרה של היקף הכיתה והשיטות להסרה חייבות להיות סטטיות. בנוגע לשיטות הבדיקה, שלא כמו בגרסה הקודמת של JUnit, הם כבר לא צריכים להתחיל את שם ה-method עם test, במקום זאת צריך להוסיף לכל אחד מהם הערות עם @Test. כרגיל, שיטות הבדיקה צריכות להיות ציבוריות, להצהיר שאין ערך החזרה, לא לכלול פרמטרים עלול לגרום חריגות.

גישה לכיתת אינסטרומנטציה

למרות שלא נכלל בדוגמה הבסיסית של 'בעולם השלום', זה די נפוץ בדיקת Android שנדרשת בשביל הגישה למכונה Instrumentation: זהו ה-API המרכזי ממשק שמספק גישה להקשרים של אפליקציות, למחזור החיים של פעילות ממשקי API לבדיקה קשורים ועוד.

מכיוון שהבדיקות של JUnit4 כבר לא מחייבות מחלקה בסיסית משותפת, הן כבר לא נדרש כדי לקבל את מכונת Instrumentation דרך InstrumentationTestCase#getInstrumentation(), במקום זאת, בהרצה החדשה מנהל אותו דרך InstrumentationRegistry שבה תשתיות ההקשר והסביבה שנוצרות באמצעות מסגרת האינסטרומנטציה .

כדי לגשת למופע של מחלקה Instrumentation, פשוט קוראים ל-method הסטטי getInstrumentation() בכיתה אחת (InstrumentationRegistry):

Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation()

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

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

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