יכול להיות שיהיה קשה להפוך את בדיקת המשחקים לאוטומטית אם אפליקציות המשחקים מבוססות על מסגרות שונות של ממשקי משתמש. בדיקות Game Loop מאפשרות לכם לשלב את הבדיקות המקוריות שלכם עם Test Lab ולהריץ אותן בקלות במכשירים שתבחרו. בדיקת Game Loop מריצה את הבדיקה באפליקציית המשחק שלכם תוך סימולציה של פעולות של שחקן אמיתי. במדריך הזה נסביר איך להריץ בדיקה של Game Loop, ואז להציג ולנהל את תוצאות הבדיקה במסוף Firebase.
מהו מבחן של לולאת משחק?
אפליקציות של משחקים מבוססות על מנועים ו-frameworks שונים של ממשקי משתמש, כמו Unity, Unreal או קוד OpenGL/Vulkan C++, ולכן כלי אוטומציה רגילים לא יכולים לבדוק את רכיבי ממשק המשתמש או לבצע פעולות בהם. בדיקת לולאת משחק מאפשרת לכם לשלב את בדיקות המנוע המקוריות שלכם עם Test Lab על ידי הפעלת המשחק עם intent שמכיל מספר של תרחיש ספציפי. מספר התרחיש הזה מנחה את האפליקציה להריץ לוגיקה מוכנה מראש, סימולציות של AI או בדיקות ביצועים ישירות במנוע המשחק.
אחרי ההפעלה, Test Lab לא יוצר יותר אינטראקציה עם ממשק המשתמש של המשחק. במקום זאת, Test Lab פועל כסביבת בדיקה וכאמצעי העברה: הוא מפעיל את התרחיש הספציפי, עוקב אחרי קריסות ופסק זמן, ואוסף יומני תוצאות בהתאמה אישית כשהאפליקציה מסיימת להריץ את הלולאה.
מה ההבדל בין לולאות משחק לבין בדיקות מכשור
- בדיקות אינסטרומנטציה (כמו Espresso או UI Automator) מסתמכות על מסגרות חיצוניות כדי להפעיל אינטראקציות עם ממשק המשתמש, ללחוץ על לחצנים ולקבוע את מצב האפליקציה בהיררכיית התצוגה של Android מחוץ לאפליקציה.
- בדיקות של לולאת משחק מעבירות את לוגיקת הבדיקה לאפליקציה. האפליקציה מריצה לולאת בדיקה פנימית או סימולציה משלה בלי אינטראקציה חיצונית עם ממשק המשתמש, בזמן ש-Test Lab מפעיל את התרחיש ואוסף את תוצאות הבדיקה.
דוגמאות
נניח שאתם רוצים לוודא שהמשחק שלכם שומר על לפחות 60 פריימים לשנייה במכשירים פיזיים שונים. אתם יכולים להטמיע תרחיש 1 בתוך קוד המשחק כדי לטעון את השלב הכי מורכב מבחינה ויזואלית ולאפשר לשחקן AI או לסקריפט אוטומטי לשחק בו במשך שתי דקות.
כש-Test Lab מפעיל את התרחיש 1, המשחק מתחיל את ההפעלה של ה-AI, עוקב אחרי זמני העיבוד של הפריימים ושימוש הזיכרון, מעביר את המדדים האלה לקובץ יומן פלט מותאם אישית (logFile) וקורא ל-finish() כשהוא מסתיים.
Test Lab ואז המערכת מצלמת את קובץ היומן ומאפשרת לכם לגשת אליו ב-Cloud Storage ובמסוף Firebase.
תרחישים לדוגמה
בהתאם למנוע המשחק, אפשר להטמיע בדיקות עם לולאה אחת או עם כמה לולאות. לולאה היא הרצה מלאה או חלקית של הבדיקה באפליקציית המשחק. אפשר להשתמש בלולאות של משחקים כדי:
- מריצים שלב במשחק בדיוק כמו שמשתמש קצה משחק בו. אפשר לתכנת את הקלט של המשתמש, לאפשר למשתמש להיות במצב בלי פעילות או להחליף את המשתמש ב-AI אם זה הגיוני במשחק (לדוגמה, אם יש לכם אפליקציית משחקים של מכוניות מירוץ וכבר הטמעתם AI, אתם יכולים להציב נהג AI שאחראי על הקלט של המשתמש).
- כדי לבדוק אם המכשירים תומכים בהגדרה הזו, מריצים את המשחק בהגדרת האיכות הכי גבוהה.
- להריץ בדיקה טכנית (קומפילציה של כמה הצללות, הפעלה שלהן, בדיקה שהפלט הוא כמו שציפיתם וכו').
אפשר להריץ בדיקה של לולאת משחק במכשיר בדיקה יחיד, בקבוצה של מכשירי בדיקה או ב-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
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
yourActivity.finish()
Java
yourActivity.finish();
האפליקציה תיסגר כשהבדיקה של לולאת המשחק תסתיים. הבדיקה מסתמכת על מסגרת ממשק המשתמש של האפליקציה כדי להתחיל את הלולאה הבאה, וסגירת האפליקציה מציינת שהבדיקה הסתיימה.
יצירה והרצה של בדיקת game loop
אחרי שמגדירים את האפליקציה לבדיקות של לולאות משחק, אפשר ליצור בדיקה ולהריץ אותה באפליקציית המשחק באופן מיידי. אפשר להריץ בדיקה ב-Test Lab באמצעות מסוף Firebase או ממשק שורת הפקודה (CLI) של gcloud, או במכשיר מקומי באמצעות Test Loop Manager.
הרצה במכשיר מקומי
Test LabTest Loop Manager היא אפליקציה בקוד פתוח שעוזרת לשלב בדיקות של Game Loop ולהריץ אותן במכשירים המקומיים. היא גם מאפשרת לצוות בקרת האיכות להריץ את אותם לולאות משחק במכשירים שלהם.
כדי להריץ בדיקה במכשיר מקומי באמצעות Test Loop Manager:
- מורידים את Test Loop Manager לטלפון או לטאבלט ומריצים את הפקודה הבאה כדי להתקין אותו:
adb install testloopmanager.apk
- במכשיר, פותחים את האפליקציה Test Loop Apps בטלפון או בטאבלט. באפליקציה מוצגת רשימה של אפליקציות במכשיר שאפשר להפעיל באמצעות לולאות משחק. אם אפליקציית המשחקים לא מופיעה כאן, צריך לוודא שמסנן Intent תואם לזה שמתואר בשלב הראשון של הקטע 'לפני שמתחילים'.
- בוחרים את אפליקציית המשחקים ואז את מספר הלולאות שרוצים להפעיל. הערה: בשלב הזה אפשר לבחור להפעיל קבוצת משנה של לולאות במקום רק לולאה אחת. מידע נוסף על הפעלת כמה לולאות בו-זמנית זמין במאמר בנושא תכונות אופציונליות.
- לוחצים על הפעלת הבדיקה. הבדיקה מתחילה לפעול מיד.
ריצה ב-Test Lab
אפשר להריץ בדיקה של Game Loop ב-Test Lab באמצעות מסוף Firebase או ה-CLI של gcloud. לפני שמתחילים, אם עדיין לא עשיתם את זה, פותחים את מסוף Firebase ויוצרים פרויקט.
שימוש במסוף Firebase
- במסוף Firebase, לוחצים על Test Lab בחלונית הימנית.
- לוחצים על הפעלת הבדיקה הראשונה (או על הפעלת בדיקה אם כבר הפעלתם בדיקה בפרויקט).
- בוחרים באפשרות Game Loop כסוג הבדיקה ולוחצים על המשך.
- לוחצים על עיון ואז עוברים לקובץ
.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 מציע כמה תכונות אופציונליות שמאפשרות לכם להתאים אישית את הבדיקות, כולל האפשרות לכתוב נתוני פלט, תמיכה בכמה לולאות משחק ותוויות ללולאות קשורות.
כתיבת נתוני פלט
כש-Test Lab מפעיל את המשחק, הוא מציין כתובת URL שמפנה לקובץ תוצאות מקומי במכשיר הבדיקה, שאפשר לגשת אליו באמצעות launchIntent.getData(). המשחק יכול לכתוב תוצאות בדיקה, מדדי ביצועים ויומנים (logFile) ישירות למיקום הזה במהלך הרצת הבדיקה.
אפשר לכתוב כל תוכן שרירותי אל logFile, כמו טקסט פשוט, נתוני CSV, זמני עיבוד של פריימים או דוחות אבחון בהתאמה אישית. אין הגבלות או דרישות עיצוב לתוכן שאתם כותבים. הקובץ נשמר כשמסיימים את הבדיקה ומועלה למאגר Cloud Storage לצד פריטי המידע האחרים מהבדיקה.
Test Lab פועלת לפי השיטות המומלצות לשיתוף קובץ בין אפליקציות, שמתוארות במאמר שיתוף קובץ.
בשיטת onCreate() של הפעילות, שבה נמצאת הכוונה, אפשר לאחזר ולבדוק את קובץ פלט הנתונים על ידי הרצת הקוד הבא:
Kotlin
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
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); }
דוגמה לקובץ פלט
למרות שלא נדרש פורמט ספציפי ל-logFile ב-Test Lab, אם תגדירו את הפלט כ-JSON שתואם לסכימה שבהמשך, מסוף Firebase (https://console.firebase.google.com/project/_/testlab) יוכל לנתח ולהציג מדדי סיכום לבדיקת לולאת המשחק.
פרטים חשובים לגבי הדוגמה הזו:
- מי מספק את הנתונים: אתם (מפתחי הבדיקה) אחראים לחישוב כל המדדים ולכתיבתם בקובץ הזה מתוך קוד המשחק. Test Lab לא אוסף או יוצר באופן אוטומטי את נקודות הנתונים האלה בשבילכם.
- הוספת שדות בהתאמה אישית: האזורים שמסומנים ב-
/.../מציינים איפה אפשר להוסיף צמדים שרירותיים של מפתח/ערך בהתאמה אישית (לדוגמה,"rendered_vertices": 12000או"ai_error_count": 0). אפשר להוסיף כל מאפיין JSON תקין לפלט כשכותבים את הקובץ מהאפליקציה, כל עוד שמות השדות לא מתנגשים עם שדות סכימה כמוnameאוstart_timestamp. - איפה אפשר למצוא את קובץ הפלט: אחרי שהבדיקה מסתיימת, קובץ הפלט הגולמי מאוחסן וזמין להורדה בתיקיית הארטיפקטים של הרצת הבדיקה, בקטגוריית התוצאות (
GCS) של Cloud Storage בפרויקט. אפשר גם לראות ולבדוק את הפלט המנותח בדף Test Lab במסוף Firebase.
הנה דוגמה לקובץ פלט JSON מובנה:
{
"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" />
ה-Intent להפעלת האפליקציה מכיל את לולאת היעד כפרמטר מסוג integer. בשדה
android:valueאפשר לציין מספר שלם מ-1 עד 1024 (המספר המקסימלי של לולאות שמותרות לבדיקה אחת). הערה: האינדקס של לולאות מתחיל מ-1 ולא מ-0.באפליקציה Test Loop Manager, מופיע מסך בחירה שמאפשר לבחור אילו לולאות רוצים להריץ. אם בוחרים כמה לולאות, כל לולאה מופעלת ברצף אחרי שהלולאה הקודמת מסתיימת.
אם אתם מריצים בדיקה באמצעות מסוף Firebase, מזינים רשימה או טווח של מספרי לולאות בשדה תרחישים.
אם אתם מריצים בדיקה באמצעות ה-CLI של gcloud, ציינו רשימה של מספרי לולאות באמצעות הדגל
--scenario-numbers. לדוגמה,--scenario-numbers=1,3,5מפעיל את לולאות 1, 3 ו-5.אם אתם כותבים קוד C++ ורוצים לשנות את ההתנהגות של הלולאה, צריך להעביר את התוסף הבא לקוד C++ המקורי:
Kotlin
val launchIntent = intent val scenario = launchIntent.getIntExtra("scenario", 0)
Java
Intent launchIntent = getIntent(); int scenario = launchIntent.getIntExtra("scenario", 0);
עכשיו אפשר לשנות את ההתנהגות של הלולאה על סמך
intהערך שמתקבל.
תוויות של לולאות משחק
כשמסמנים לולאות משחק בתווית תרחיש אחת או יותר, אתם וצוות בקרת האיכות יכולים להפעיל בקלות קבוצה של לולאות משחק קשורות (למשל, 'כל לולאות המשחק של התאימות') ולבדוק אותן במטריצה אחת. אתם יכולים ליצור תוויות משלכם או להשתמש בתוויות המוגדרות מראש שמוצעות על ידי 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:
במניפסט של האפליקציה, מוסיפים את שורת המטא-נתונים הבאה ומחליפים את 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 תומך באפליקציות שמשתמשות בשירות App Licensing שמוצע על ידי Google Play. כדי לבדוק את הרישוי בהצלחה כשבודקים את האפליקציה באמצעות Test Lab, צריך לפרסם את האפליקציה בערוץ הייצור בחנות Play. כדי לבדוק את האפליקציה בערוץ אלפא או בטא באמצעות Test Lab, צריך להסיר את בדיקת הרישיון לפני שמעלים את האפליקציה אל Test Lab.
בעיות מוכרות
הבעיות הבאות מוכרות בבדיקות של לולאות משחק ב-Test Lab:
- חלק מהקריסות לא תומכות ב-backtrace. לדוגמה, יכול להיות שבחלק מהגרסאות לא יופיע הפלט של תהליך
debuggerdבאמצעותprctl(PR_SET_DUMPABLE, 0). מידע נוסף זמין במאמרdebuggerd. - כרגע אין תמיכה ברמת API 19 בגלל שגיאות בהרשאות לקבצים.