יכול להיות שיהיה קשה להפוך את בדיקת המשחקים לאוטומטית כשאפליקציות המשחקים מבוססות על מסגרות UI שונות. בדיקות לולאת משחקים מאפשרות לשלב את הבדיקות המקוריות עם Test Lab ולהריץ אותן בקלות במכשירים נבחרים. בבדיקה של Game Loop, הבדיקה מתבצעת באפליקציית המשחק תוך סימולציה של הפעולות של שחקן אמיתי. במדריך הזה מוסבר איך להריץ בדיקת Game Loop, ואז להציג ולנהל את תוצאות הבדיקה במסוף Firebase.
בהתאם למנוע המשחקים שלכם, תוכלו להטמיע בדיקות עם לולאה אחת או עם כמה לולאות. לולאה היא הרצה מלאה או חלקית של הבדיקה באפליקציית המשחקים. אפשר להשתמש בלופ של משחקים כדי:
- הפעלת שלב במשחק באותו אופן שבו משתמש קצה יכול לשחק בו. אפשר לכתוב סקריפט של הקלט של המשתמש, לאפשר למשתמש להיות במצב חוסר פעילות או להחליף את המשתמש ב-AI אם זה הגיוני במשחק (לדוגמה, אם יש לכם אפליקציית משחק מכוניות מרוץ שכבר הטמעתם בה AI. אפשר בקלות להעביר את הטיפול בקלט של המשתמש ל-AI).
- אפשר להריץ את המשחק בהגדרה של האיכות הגבוהה ביותר כדי לראות אם מכשירים תומכים בו.
- מריצים בדיקה טכנית (מפעילים כמה שגיאות, מריצים אותן, בודקים שהפלט תואם לציפיות וכו').
אפשר להריץ בדיקת Game Loop במכשיר בדיקה אחד, בקבוצת מכשירי בדיקה או ב-Test Lab. עם זאת, לא מומלץ להריץ בדיקות Game Loop במכשירים וירטואליים כי קצב הפריימים של הגרפיקה בגרפיקה נמוך יותר מאשר במכשירים פיזיים.
לפני שמתחילים
כדי להטמיע בדיקה, קודם צריך להגדיר את האפליקציה לבדיקות של Game Loop.
בקובץ המניפסט של האפליקציה, מוסיפים מסנן 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 באמצעות כוונה ספציפית.
.בקוד (מומלץ להוסיף את הקוד הזה בתוך ההצהרה על השיטה
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 }
כך הפעילות תוכל לבדוק את הכוונה שהפעילה אותה. תוכלו להוסיף את הקוד הזה גם מאוחר יותר (למשל, אחרי הטעינה הראשונית של מנוע המשחק).
מומלץ: בסוף הבדיקה, מוסיפים:
Kotlin+KTX
yourActivity.finish()
Java
yourActivity.finish();
הפקודה הזו תסגור את האפליקציה בסיום הבדיקה של Game Loop. הבדיקה מסתמכת על מסגרת ממשק המשתמש של האפליקציה כדי להתחיל את הלולאה הבאה, ועצירתה של האפליקציה מסמנת לה שהבדיקה הסתיימה.
יצירת בדיקת Game Loop והפעלתה
אחרי שמגדירים את האפליקציה לבדיקות של לולאת משחקים, אפשר מיד ליצור בדיקה ולהריץ אותה באפליקציית המשחקים. אפשר להריץ בדיקה ב-Test Lab באמצעות המסוף Firebase או באמצעות ממשק שורת הפקודה של gcloud (CLI), או במכשיר מקומי באמצעות מנהל לולאת הבדיקה.
הפעלה במכשיר מקומי
Test Loop Manager של Test Lab היא אפליקציה בקוד פתוח שבעזרתה אפשר לשלב בדיקות של Game Loop ולהריץ אותן במכשירים המקומיים. היא גם מאפשרת לצוות הבטחת האיכות להריץ את אותם לולאות משחק במכשירים שלהם.
כדי להריץ בדיקה במכשיר מקומי באמצעות Test Loop Manager:
- מורידים את Test Loop Manager לטלפון או לטאבלט ומתקינים אותו באמצעות הפקודה:
adb install testloopmanager.apk
- במכשיר, פותחים את האפליקציה אפליקציות בדיקה לולאה בטלפון או בטאבלט. באפליקציה מוצגת רשימת האפליקציות במכשיר שאפשר להריץ באמצעות לולאות משחק. אם אפליקציית המשחקים לא מופיעה כאן, צריך לוודא שמסנן הכוונה תואם למסנן שמתואר בשלב הראשון בקטע לפני שמתחילים.
- בוחרים את אפליקציית המשחקים ואז בוחרים את מספר הלולאות שרוצים להריץ. הערה: בשלב הזה תוכלו להפעיל קבוצת משנה של לולאות במקום רק לולאה אחת. מידע נוסף על הפעלת כמה לולאות בו-זמנית זמין בקטע תכונות אופציונליות.
- לוחצים על הפעלת בדיקה. הבדיקה תתחיל לפעול באופן מיידי.
הפעלה ב-Test Lab
אפשר להריץ בדיקת Game Loop ב-Test Lab באמצעות מסוף Firebase או CLI של gcloud. לפני שמתחילים, אם עדיין לא עשיתם זאת, פותחים את מסוף Firebase ויוצרים פרויקט.
שימוש במסוף Firebase
- במסוף Firebase, לוחצים על Test Lab בחלונית הימנית.
- לוחצים על Run Your First Test (הרצת בדיקה ראשונה) (או על Run a Test אם כבר הרצתם בדיקה בפרויקט).
- בוחרים באפשרות Game Loop (מחזור משחק) בתור סוג הבדיקה ולוחצים על Continue (המשך).
- לוחצים על עיון ועוברים לקובץ
.apk
של האפליקציה. הערה: בשלב הזה, אפשר להריץ קבוצת משנה של לולאות במקום רק לולאה אחת. מידע נוסף על הפעלת כמה לולאות בו-זמנית זמין בקטע תכונות אופציונליות. - לוחצים על המשך.
- בוחרים את המכשירים הפיזיים שבהם רוצים לבדוק את האפליקציה.
- לוחצים על התחלת הבדיקות.
מידע נוסף על תחילת העבודה עם מסוף Firebase זמין במאמר תחילת הבדיקה באמצעות מסוף Firebase.
שימוש בשורת הפקודה (CLI) של gcloud
אם עדיין לא עשיתם זאת, מורידים ומתקינים את Google Cloud SDK.
נכנסים ל-CLI של gcloud באמצעות חשבון Google:
gcloud auth login
מגדירים את פרויקט Firebase ב-gcloud, כאשר
PROJECT_ID
הוא המזהה של פרויקט Firebase:gcloud config set project PROJECT_ID
מריצים את הבדיקה הראשונה:
gcloud firebase test android run \ --type=game-loop --app=<var>path-to-apk</var> \ --device model=herolte,version=23
למידע נוסף על תחילת העבודה עם ה-CLI של gcloud, ראו תחילת הבדיקה משורת הפקודה של gcloud.
תכונות אופציונליות
ב-Test Lab יש כמה תכונות אופציונליות שמאפשרות להתאים אישית את הבדיקות עוד יותר, כולל היכולת לכתוב נתוני פלט, תמיכה במספר לולאות משחק ותוויות ללולאות קשורות.
כתיבת נתוני פלט
בדיקת Game Loop יכולה לכתוב פלט לקובץ שצוין ב-method 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, תוכלו להפעיל ישירות את הלולאה של המשחק כדי לשחזר את הקריסה ולבדוק את תיקוני הבאגים.
כדי לאפשר לאפליקציה להריץ כמה לולאות בו-זמנית:
אם אתם מריצים בדיקה באמצעות Test Loop Manager:
מוסיפים את השורה הבאה למניפסט של האפליקציה, בתוך הרכיב
<application>
:<meta-data android:name="com.google.test.loops" android:value="5" />
כוונת ההפעלה הזו מכילה את לולאת היעד כפרמטר של מספר שלם. בשדה
android:value
אפשר לציין מספר שלם מ-1 עד 1024 (מספר הלולאות המקסימלי שמותר לבדיקה אחת). שימו לב שלולאות נוספות לאינדקס החל מ-1 ולא מ-0.באפליקציית Test Loop Manager מופיע מסך בחירה שמאפשר לבחור את הלולאות שרוצים להריץ. אם בוחרים כמה לולאות, כל לולאה מופעלת ברצף אחרי שהלולאה הקודמת מסתיימת.
אם מריצים בדיקה באמצעות מסוף Firebase, מזינים רשימה או טווח של מספרי לולאות בשדה Scenarios.
אם אתם מריצים בדיקה עם ה-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
: ללולאות שמשמשות לבדיקת בעיות שקשורות ל-GPU. מטרת הבדיקה באמצעות הלולאות האלה היא להריץ קוד GPU שייתכן שלא יפעל כראוי בסביבת הייצור, כדי לחשוף בעיות בחומרה ובמנהלי התקנים.com.google.test.loops.compatibility
: לולאות For שמשמשות לבדיקת מגוון רחב של בעיות תאימות, כולל בעיות קלט/פלט ובעיות ב-OpenSSL.com.google.test.loops.performance
: לולאות For שמשמשות לבדיקת הביצועים של המכשיר. לדוגמה, משחק עשוי לפעול עם ההגדרות הגרפיות המורכבות ביותר כדי לראות איך מכשיר חדש מתנהג.
כדי לאפשר לאפליקציה להריץ לולאות עם אותה תווית:
אם אתם מריצים בדיקה באמצעות מנהל לולאת הבדיקה:
במניפסט של האפליקציה, מוסיפים את שורת המטא-נתונים הבאה ומחליפים את 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.באפליקציית Test Loop Manager, מזינים תווית אחת או יותר בשדה Labels.
אם אתם מפעילים בדיקה באמצעות מסוף Firebase, מזינים תווית אחת או יותר בשדה Labels.
אם מריצים בדיקה באמצעות ה-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 בגלל שגיאות בהרשאות הקבצים.