איך מתחילים לעבוד עם בדיקות של לולאת משחקים

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

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

  • הפעלת שלב במשחק באותו אופן שבו משתמש קצה יכול לשחק בו. אפשר לכתוב סקריפט של הקלט של המשתמש, לאפשר למשתמש להיות במצב חוסר פעילות או להחליף את המשתמש ב-AI אם זה הגיוני במשחק (לדוגמה, אם יש לכם אפליקציית משחק מכוניות מרוץ שכבר הטמעתם בה AI. אפשר בקלות להקצות ל-AI את האחריות על הקלט של המשתמש).
  • אפשר להריץ את המשחק בהגדרה של האיכות הגבוהה ביותר כדי לראות אם מכשירים תומכים בו.
  • מריצים בדיקה טכנית (הדרת מספר תוכנות הצללה (shader), מבצעים אותם ומוודאים הפלט אמור לעבוד כמצופה וכו').

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

לפני שמתחילים

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

  1. במניפסט של האפליקציה, מוסיפים מסנן Intent חדש לפעילות:

    <activity android:name=".MyActivity">
       <intent-filter>
           <action android:name="com.google.intent.action.TEST_LOOP"/>
           <category android:name="android.intent.category.DEFAULT"/>
           <data android:mimeType="application/javascript"/>
       </intent-filter>
       <intent-filter>
          ... (other intent filters here)
       </intent-filter>
    </activity>
    

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

    .
  2. בקוד (מומלץ להוסיף את הקוד הזה בתוך ההצהרה על השיטה onCreate), מוסיפים את הקוד הבא:

    Kotlin+KTX

    val launchIntent = intent
    if (launchIntent.action == "com.google.intent.action.TEST_LOOP") {
        val scenario = launchIntent.getIntExtra("scenario", 0)
        // Code to handle your game loop here
    }

    Java

    Intent launchIntent = getIntent();
    if(launchIntent.getAction().equals("com.google.intent.action.TEST_LOOP")) {
        int scenario = launchIntent.getIntExtra("scenario", 0);
        // Code to handle your game loop here
    }

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

  3. מומלץ: בסוף הבדיקה, מוסיפים:

    Kotlin+KTX

    yourActivity.finish()

    Java

    yourActivity.finish();

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

יצירת בדיקת Game Loop והפעלתה

אחרי שמגדירים את האפליקציה לבדיקות של Game Loop, אפשר ליצור בדיקה מיד ולהריץ אותה באפליקציית המשחקים. אפשר להריץ בדיקה ב-Test Lab באמצעות מסוף Firebase או ממשק שורת הפקודה (CLI) של gcloud, או במכשיר מקומי באמצעות Test Loop Manager.

הפעלה במכשיר מקומי

Test Loop Manager של Test Lab היא אפליקציה בקוד פתוח שבעזרתה אפשר לשלב בדיקות של Game Loop ולהריץ אותן במכשירים המקומיים. היא גם מאפשרת לצוות הבטחת האיכות להריץ את אותם לולאות משחק במכשירים שלהם.

כדי להריץ בדיקה במכשיר מקומי באמצעות Test Loop Manager:

  1. מורידים את מנהל לולאת הבדיקה בטלפון או בטאבלט, ולהתקין אותם באמצעות:
    adb install testloopmanager.apk
  2. במכשיר, פותחים את האפליקציה אפליקציות לבדיקה של לולאת בדיקה בטלפון או הטאבלט. האפליקציה מציגה במכשיר רשימה של אפליקציות שניתן להריץ עם לולאות של משחקים. אם אפליקציית המשחקים לא מופיעה כאן, צריך לוודא שמסנן הכוונה תואם למסנן שמתואר בשלב הראשון בקטע לפני שמתחילים.
  3. בוחרים את אפליקציית המשחקים ואז בוחרים את מספר הלולאות שרוצים להריץ. הערה: בשלב הזה, אפשר להפעיל קבוצת משנה של לולאות במקום רק לולאה אחת. מידע נוסף על הפעלת כמה לולאות בו-זמנית זמין בקטע תכונות אופציונליות.
  4. לוחצים על הפעלת הבדיקה. הבדיקה תתחיל לפעול באופן מיידי.

הפעלה בTest Lab

אפשר להריץ בדיקה של לולאת משחקים ב-Test Lab באמצעות המסוף של Firebase או של ה-CLI של gcloud. לפני שמתחילים, אם עדיין לא עשיתם זאת, פותחים את מסוף Firebase ויוצרים פרויקט.

שימוש במסוף Firebase

  1. במסוף Firebase, לוחצים על Test Lab בחלונית הימנית.
  2. לוחצים על Run Your First Test (או על Run a Test אם כבר הרצתם בדיקה בפרויקט).
  3. בוחרים באפשרות לולאת משחקים בתור סוג הבדיקה, ואז לוחצים על המשך.
  4. לוחצים על Browse (עיון) ועוברים לקובץ .apk של האפליקציה. הערה: בשלב הזה, אפשר להפעיל קבוצת משנה של לולאות במקום רק לולאה אחת. מידע נוסף על הפעלת כמה לולאות בו-זמנית זמין בקטע תכונות אופציונליות.
  5. לוחצים על המשך.
  6. בחירת המכשירים הפיזיים שישמשו לבדיקת האפליקציה שלך.
  7. לוחצים על התחלת הבדיקות.

מידע נוסף על תחילת העבודה עם מסוף Firebase זמין במאמר תחילת הבדיקה באמצעות מסוף Firebase.

שימוש בשורת הפקודה (CLI) של gcloud

  1. אם עדיין לא עשיתם זאת, מורידים ומתקינים את Google Cloud SDK.

  2. נכנסים ל-CLI של gcloud באמצעות חשבון Google:

    gcloud auth login

  3. מגדירים את פרויקט Firebase ב-gcloud, כאשר PROJECT_ID הוא המזהה של פרויקט Firebase:

    gcloud config set project PROJECT_ID
    
  4. מריצים את הבדיקה הראשונה:

    gcloud firebase test android run \
     --type=game-loop --app=<var>path-to-apk</var> \
     --device model=herolte,version=23
    

למידע נוסף על תחילת העבודה עם ה-CLI של gcloud, ראו תחילת הבדיקה משורת הפקודה של gcloud.

תכונות אופציונליות

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

כתיבת נתוני פלט

הבדיקה של לולאת המשחק יכולה לכתוב פלט לקובץ שצוין ב אמצעי תשלום אחד (launchIntent.getData()). אחרי שמריצים בדיקה, אפשר לגשת נתוני פלט בקטע Test Lab במסוף Firebase (מידע נוסף זמין בקטע דוגמה לקובץ פלט בדיקה של לולאת משחק).

Test Lab פועלת לפי השיטות המומלצות לשיתוף קבצים בין אפליקציות, כפי שמתואר בקטע שיתוף קובץ. כדי לבדוק את קובץ הפלט של הנתונים, מריצים את הקוד הבא ב-method‏ onCreate() של הפעילות, שבו נמצאת הכוונה:

Kotlin+KTX

val launchIntent = intent
val logFile = launchIntent.data
logFile?.let {
    Log.i(TAG, "Log file ${it.encodedPath}")
    // ...
}

Java

Intent launchIntent = getIntent();
Uri logFile = launchIntent.getData();
if (logFile != null) {
    Log.i(TAG, "Log file " + logFile.getEncodedPath());
    // ...
}

אם רוצים לכתוב לקובץ מהצד C++ של אפליקציית המשחק, אפשר מעבירים את מתאר הקובץ במקום את נתיב הקובץ:

Kotlin+KTX

val launchIntent = intent
val logFile = launchIntent.data
var fd = -1
logFile?.let {
    Log.i(TAG, "Log file ${it.encodedPath}")
    fd = try {
        contentResolver
            .openAssetFileDescriptor(logFile, "w")!!
            .parcelFileDescriptor
            .fd
    } catch (e: FileNotFoundException) {
        e.printStackTrace()
        -1
    } catch (e: NullPointerException) {
        e.printStackTrace()
        -1
    }
}

// C++ code invoked here.
// native_function(fd);

Java

Intent launchIntent = getIntent();
Uri logFile = launchIntent.getData();
int fd = -1;
if (logFile != null) {
    Log.i(TAG, "Log file " + logFile.getEncodedPath());
    try {
        fd = getContentResolver()
                .openAssetFileDescriptor(logFile, "w")
                .getParcelFileDescriptor()
                .getFd();
    } catch (FileNotFoundException e) {
        e.printStackTrace();
        fd = -1;
    } catch (NullPointerException e) {
        e.printStackTrace();
        fd = -1;
    }
}

// C++ code invoked here.
// native_function(fd);

C++‎

#include <unistd.h>
JNIEXPORT void JNICALL
Java_my_package_name_MyActivity_native_function(JNIEnv *env, jclass type, jint log_file_descriptor) {
// The file descriptor needs to be duplicated.
int my_file_descriptor = dup(log_file_descriptor);
}

דוגמה לקובץ פלט

אפשר להשתמש בקובצי נתוני פלט (בפורמט כמו הדוגמה שבהמשך) כדי להציג את תוצאות הבדיקה של לולאת המשחק בקטע Test Lab במסוף Firebase. האזורים שמוצגים בתור /.../ יכולים להכיל כל שדה בהתאמה אישית שצריך, כל עוד הם לא מתנגשים עם שמות של שדות אחרים שמופיעים בקובץ הזה:

{
  "name": "test name",
  "start_timestamp": 0, // Timestamp of the test start (in us).
                           Can be absolute or relative
  "driver_info": "...",
  "frame_stats": [
    {
      "timestamp": 1200000, // Timestamp at which this section was written
                               It contains value regarding the period
                               start_timestamp(0) -> this timestamp (1200000 us)
      "avg_frame_time": 15320, // Average time to render a frame in ns
      "nb_swap": 52, // Number of frame rendered
      "threads": [
        {
          "name": "physics",
          "Avg_time": 8030 // Average time spent in this thread per frame in us
        },
        {
          "name": "AI",
          "Avg_time": 2030 // Average time spent in this thread per frame in us
        }
      ],
      /.../ // Any custom field you want (vertices display on the screen, nb units …)
    },
    {
      // Next frame data here, same format as above
    }
  ],
  "loading_stats": [
    {
      "name": "assets_level_1",
      "total_time": 7850, // in us
      /.../
    },
    {
      "name": "victory_screen",
      "total_time": 554, // in us
      /.../
    }

  ],
  /.../, // You can add custom fields here
}

מספר לולאות של משחקים

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

כדי לאפשר לאפליקציה להריץ כמה לולאות בו-זמנית:

  • אם אתם מריצים בדיקה באמצעות מנהל לולאת הבדיקה:

    1. מוסיפים את השורה הבאה למניפסט של האפליקציה, בתוך הרכיב <application>:

      <meta-data
        android:name="com.google.test.loops"
        android:value="5" />
      

      כוונת ההפעלה הזו מכילה את לולאת היעד כפרמטר של מספר שלם. בשדה android:value אפשר לציין מספר שלם מ-1 עד 1,024 (מספר הלולאות המקסימלי המותר לבדיקה אחת). הערה שלולאות נוצרות באינדקס החל מ-1 ולא מ-0.

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

  • אם מתבצעת בדיקה באמצעות מסוף Firebase, צריך להזין רשימה או טווח מספרי הלולאה בשדה תרחישים.

  • אם אתם מריצים בדיקה באמצעות ה-CLI של gcloud, עליכם לציין רשימה של מספרי לולאה באמצעות הדגל --scenario-numbers. לדוגמה, --scenario-numbers=1,3,5 מפעיל את לולאות 1, 3 ו-5.

  • אם אתם כותבים C++ ואתם רוצים לשנות את ההתנהגות של הלולאה, העבירו את שבהמשך לקוד C++ המקורי:

    Kotlin+KTX

    val launchIntent = intent
    val scenario = launchIntent.getIntExtra("scenario", 0)

    Java

    Intent launchIntent = getIntent();
    int scenario = launchIntent.getIntExtra("scenario", 0);

    עכשיו אפשר לשנות את התנהגות הלולאה על סמך ה-int שמתקבל עם ערך מסוים.

מתן תוויות ל-game loops

אם מתייגים את לולאות המשחק בתווית אחת או יותר של תרחיש, אתם ובקרת האיכות יכול להשיק בקלות קבוצה של לולאות משחקים קשורות (למשל, "כל לולאות המשחקים התואמות") ולבדוק אותן במטריצה אחת. אפשר ליצור תוויות משלך או צריך להשתמש בתוויות המוגדרות מראש שמוצעות על ידי Test Lab:

  • com.google.test.loops.player_experience: לולאות For שמשמשות לשחזור החוויה של משתמש אמיתי במהלך המשחק. המטרה של במסגרת לולאות אלה, נוכל לגלות בעיות שמשתמש אמיתי ייתקל בהן לשחק את המשחק.
  • com.google.test.loops.gpu_compatibility: לולאות For שמשמשות לבדיקת בעיות שקשורות ל-GPU. מטרת הבדיקה באמצעות הלולאות האלה היא להריץ קוד GPU שעשוי שלא לפעול כמו שצריך בסביבת הייצור, כדי לחשוף בעיות בחומרה ובדריברים.
  • com.google.test.loops.compatibility: לולאות For שמשמשות לבדיקת מגוון רחב של בעיות תאימות, כולל בעיות קלט/פלט ובעיות ב-OpenSSL.
  • com.google.test.loops.performance: לולאות For שמשמשות לבדיקת הביצועים של המכשיר. לדוגמה, משחק עשוי לפעול ברמת המורכבות ביותר הגרפיקה כדי לראות את ההתנהגות של מכשיר חדש.

כדי לאפשר לאפליקציה להריץ לולאות עם אותה תווית:

  • אם אתם מריצים בדיקה באמצעות Test Loop Manager:

    1. במניפסט של האפליקציה, צריך להוסיף את שורת המטא-נתונים הבאה ולהחליף LABEL_NAME בתווית לבחירתכם:

      <meta-data
       android:name="com.google.test.loops.LABEL_NAME"
       android:value="1,3-5" />
      

      בשדה android:value, אפשר לציין טווח או קבוצה של מספרים שלמים מ-1 עד 1024 (המספר המקסימלי של לולאות שמותר לבדיקה אחת) שמייצגים את הלולאות שרוצים לתייג. חשוב לדעת שהאינדקס של הלולאות מתחיל ב-1 ולא ב-0. לדוגמה, android:value="1,3-5" חל LABEL_NAME ללולאות 1, 3, 4 ו-5.

    2. באפליקציית Test Loop Manager, מזינים תווית אחת או יותר בשדה Labels.

  • אם מתבצעת בדיקה באמצעות מסוף Firebase, צריך להזין לפחות שם אחד תוויות בשדה תוויות.

  • אם מריצים בדיקה באמצעות ה-CLI של gcloud, מציינים תווית אחת או יותר של תרחיש באמצעות הדגל --scenario-labels (למשל, --scenario-labels=performance,gpu).

תמיכה בהקצאת רישיונות לשימוש באפליקציות

Test Lab תומך באפליקציות שמשתמשות בשירות רישוי אפליקציות ש-Google Play מציע. איך לבדוק את הרישוי במהלך הבדיקה את האפליקציה באמצעות Test Lab, חובה לפרסם את האפליקציה בערוץ הייצור בחנות Play. כדי לבדוק את האפליקציה בערוץ אלפא או בטא באמצעות Test Lab, יש להסיר את בדיקת הרישיון לפני העלאת האפליקציה אל Test Lab

בעיות מוכרות

בבדיקות של Game Loop ב-Test Lab יש את הבעיות הידועות הבאות:

  • בחלק מהקריסות אין תמיכה ב-backtraces. לדוגמה, בחלק מהגרסאות ה-build של גרסאות הפצה יכול להיות שהפלט של התהליך debuggerd יושתק באמצעות prctl(PR_SET_DUMPABLE, 0). מידע נוסף זמין במאמר debuggerd.
  • רמת ה-API ברמה 19 לא נתמכת כרגע עקב שגיאות בהרשאות הקובץ.