وقتی برنامههای بازی در چارچوبهای واسط کاربر متفاوتی ساخته میشوند، خودکارسازی آزمایش بازی میتواند دشوار باشد. آزمایشهای «حلقه بازی» به شما امکان میدهد آزمایشهای بومیتان را با Test Lab ادغام کنید و بهراحتی آنها را در دستگاههای انتخابیتان اجرا کنید. آزمایش «حلقه بازی» آزمایش شما را ازطریق برنامه بازیتان اجرا میکند و درعینحال کنشهای بازیکن واقعی را شبیهسازی میکند. این راهنما به شما نشان میدهد که چگونه آزمایش «حلقه بازی» را اجرا کنید، سپس نتایج آزمایشتان را در کنسول Firebase مشاهده و مدیریت کنید.
آزمایش حلقه بازی چیست؟
ازآنجاییکه برنامههای بازی در چارچوبها و موتورهای مختلف میانای کاربر، مانند Unity، Unreal، یا کد OpenGL/Vulkan C++، پردازش میشوند، ابزارهای خودکارسازی استاندارد نمیتوانند عناصر میانای کاربر را بررسی کنند یا با آنها تعامل داشته باشند. آزمایش حلقه بازی به شما امکان میدهد آزمایشهای موتور بومیتان را با Test Lab ادغام کنید. این کار با راهاندازی بازیتان با هدفی که حاوی شماره سناریو خاصی است انجام میشود. این شماره سناریو برنامه شما را وادار میکند تا منطق ازپیشنوشتهشده، شبیهسازیهای هوش مصنوعی، یا بررسیهای عملکرد را مستقیماً در موتور بازی شما اجرا کند.
پساز راهاندازی، Test Lab دیگر با میانای کاربری بازیتان تعامل نمیکند. درعوض، Test Lab بهعنوان محیط و انتقال آزمایشی عمل میکند: سناریو خاصی را راهاندازی میکند، خرابیها و وقفههای زمانی را پایش میکند، و وقتی برنامه اجرای حلقه را بهپایان میرساند، گزارشهای نتایج سفارشی را جمعآوری میکند.
تفاوت حلقههای بازی با آزمایشهای ابزار دقیق
- آزمایشهای ابزار دقیق (مانند Espresso یا UI Automator) به چارچوبهای خارجی برای هدایت تعاملات میانای کاربر، کلیک کردن روی دکمهها، و تأیید وضعیت برنامه در سلسلهمراتب «نمای Android» از خارج از برنامه شما متکی هستند.
- آزمایشهای حلقه بازی منطق آزمایش را به برنامهتان واگذار میکند. برنامهتان حلقه آزمایش داخلی یا شبیهسازی خودش را بدون تعامل میانای کاربر خارجی اجرا میکند، درحالیکه Test Lab سناریو شما را راهاندازی میکند و برونداد آزمایش را جمعآوری میکند.
مثالها
فرض کنید میخواهید تأیید کنید که بازیتان حداقل ۶۰ فریم در ثانیه را در دستگاههای فیزیکی مختلف حفظ میکند. میتوانید سناریو 1 را در کد بازیتان پیادهسازی کنید تا پیچیدهترین سطح بازیتان ازنظر بصری بار شود و به بازیکن هوش مصنوعی یا اسکریپت خودکار اجازه دهید بهمدت دو دقیقه آن را بازی کند.
وقتی Test Lab سناریو 1 را راهاندازی میکند، بازی شما بازی آزمایشی هوش مصنوعی را شروع میکند،
زمانهای پرداز زدن قاب و استفاده از حافظه را پایش میکند، آن سنجهها را به
فایل گزارش برونداد سفارشی (logFile) جاریسازی میکند، و پساز تکمیل، finish() را فراخوانی میکند.
سپس Test Lab فایل گزارش را ضبط میکند و آن را در Cloud Storage و کنسول Firebase دردسترس شما قرار میدهد.
موارد استفاده
بسته به موتور بازیتان، میتوانید آزمایشها را با یک یا چند حلقه پیادهسازی کنید. حلقه عبارت است از اجرای کامل یا جزئی آزمایش شما در برنامه بازیتان. از حلقههای بازی میتوان برای موارد زیر استفاده کرد:
- مرحلهای از بازیتان را به همان روشی که کاربر نهایی بازی میکند اجرا کنید. میتوانید ورودی کاربر را اسکریپتنویسی کنید، کاربر را در حالت غیرفعال قرار دهید، یا اگر در بازی شما منطقی است، کاربر را با هوش مصنوعی جایگزین کنید (برای مثال، اگر برنامه بازی ماشین مسابقه دارید و قبلاً هوش مصنوعی را پیادهسازی کردهاید، میتوانید یک راننده هوش مصنوعی را مسئول ورودی کاربر قرار دهید).
- بازیتان را با بالاترین تنظیم کیفیت اجرا کنید تا ببینید دستگاهها از آن پشتیبانی میکنند یا نه.
- آزمایش فنی اجرا کنید (چندین سایهزن را کامپایل کنید، آنها را اجرا کنید، بررسی کنید که خروجی مطابق انتظار باشد، و غیره).
میتوانید آزمایش «حلقه بازی» را در یک دستگاه آزمایشی، مجموعهای از دستگاههای آزمایشی، یا در Test Lab اجرا کنید. اما توصیه نمیکنیم آزمایشهای Game Loop را در دستگاههای مجازی اجرا کنید زیرا نرخ فریم گرافیکی آنها کمتر از دستگاههای فیزیکی است.
قبل از شروع
برای اجرای آزمایش، ابتدا باید برنامهتان را برای آزمایشهای «حلقه بازی» پیکربندی کنید.
در مانیفست برنامهتان، فیلتر هدف جدیدی به فعالیت خود اضافه کنید:
<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();
این کار باعث میشود وقتی آزمایش «حلقه بازی» تکمیل شد، برنامهتان بسته شود. آزمایش برای شروع حلقه بعدی به چارچوب واسط کاربر برنامهتان متکی است و بستن برنامه به آن میگوید که آزمایش تمام شده است.
ایجاد و اجرای آزمایش «حلقه بازی»
پساز پیکربندی برنامهتان برای آزمایشهای «حلقه بازی»، میتوانید فوراً آزمایشی ایجاد کنید و آن را در برنامه بازیتان اجرا کنید. میتوانید انتخاب کنید که آزمایشی را در Test Lab بااستفاده از کنسول Firebase یا میانای خط فرمان (CLI) gcloud یا در دستگاه محلی بااستفاده از «مدیر حلقه آزمایش» اجرا کنید.
اجرا در دستگاه محلی
مدیر حلقه آزمایش Test Lab برنامهای متنباز است که به شما کمک میکند آزمایشهای «حلقه بازی» را ادغام کنید و آنها را در دستگاههای محلیتان اجرا کنید. همچنین به تیم «تضمین کیفیت» شما اجازه میدهد همان حلقههای بازی را در دستگاههایشان اجرا کنند.
برای اجرای آزمایش در دستگاه محلی بااستفاده از «مدیر حلقه آزمایش»:
- مدیر حلقه آزمایش را در تلفن یا رایانه لوحی بارگیری کنید و آن را با اجرای دستور زیر نصب کنید:
adb install testloopmanager.apk
- در دستگاهتان، برنامه برنامههای حلقه آزمایشی را در تلفن یا رایانه لوحی باز کنید. برنامه فهرستی از برنامههای موجود در دستگاهتان را که میتوانند با حلقههای بازی اجرا شوند نمایش میدهد. اگر برنامه بازیتان را در اینجا نمیبینید، مطمئن شوید فیلتر قصد شما با فیلتر شرحدادهشده در اولین مرحله بخش «پیشاز شروع» مطابقت داشته باشد.
- برنامه بازیتان را انتخاب کنید، سپس تعداد حلقههایی را که میخواهید اجرا شود انتخاب کنید. توجه: در این مرحله، میتوانید بهجای یک حلقه، زیرمجموعهای از حلقهها را برای اجرا انتخاب کنید. برای اطلاعات بیشتر درباره اجرای همزمان چند حلقه، به ویژگیهای اختیاری مراجعه کنید.
- روی اجرای آزمایش کلیک کنید. آزمایش شما بلافاصله شروع به اجرا میکند.
اجرا در Test Lab
میتوانید بااستفاده از کنسول Firebase یا gcloud CLI، آزمایش «حلقه بازی» را در Test Lab اجرا کنید. قبلاز شروع، اگر قبلاً این کار را نکردهاید، کنسول Firebase را باز کنید و پروژهای ایجاد کنید.
استفاده از کنسول Firebase
- در کنسول Firebase، روی Test Lab در پانل سمت راست کلیک کنید.
- روی اجرای اولین آزمایش (یا اجرای آزمایش اگر پروژهتان قبلاً آزمایشی را اجرا کرده است) کلیک کنید.
- حلقه بازی را بهعنوان نوع آزمایش انتخاب کنید، سپس روی ادامه کلیک کنید.
- روی مرور کلیک کنید، و سپس به فایل
.apkبرنامهتان بروید. توجه: در این مرحله، میتوانید بهجای یک حلقه، زیرمجموعهای از حلقهها را برای اجرا انتخاب کنید. برای اطلاعات بیشتر درباره اجرای همزمان چند حلقه، ویژگیهای اختیاری را ببینید. - روی ادامه کلیک کنید.
- دستگاههای فیزیکی را برای استفاده در آزمایش برنامهتان انتخاب کنید.
- روی شروع آزمایشها کلیک کنید.
برای اطلاعات بیشتر درباره شروع به کار با کنسول Firebase، به شروع آزمایش با کنسول Firebase مراجعه کنید.
استفاده از خط فرمان gcloud (میانای خط فرمان)
اگر قبلاً این کار را نکردهاید، Google Cloud SDK را بارگیری و نصب کنید
بااستفاده از «حساب Google» خود به سیستم gcloud CLI وارد شوید:
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
برای اطلاعات بیشتر درباره شروع کار با gcloud CLI، به شروع آزمایش از خط فرمان gcloud مراجعه کنید.
ویژگیهای اختیاری
Test Lab چندین ویژگی اختیاری ارائه میدهد که به شما امکان میدهد آزمایشهایتان را بیشتر سفارشیسازی کنید، ازجمله توانایی نوشتن دادههای خروجی، پشتیبانی از چندین حلقه بازی، و برچسبهایی برای حلقههای مرتبط.
نوشتن دادههای برونداد
وقتی Test Lab بازی شما را راهاندازی میکند، نشانی وبی را مشخص میکند که به فایل نتیجه محلی در دستگاه آزمایشی اشاره میکند و بااستفاده از 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); }
نمونه فایل خروجی
اگرچه Test Lab قالب خاصی برای logFile شما نیاز ندارد،
ساختاردهی خروجی شما بهعنوان JSON مطابق با طرحواره زیر به
کنسول Firebase (https://console.firebase.google.com/project/_/testlab) اجازه میدهد تا سنجههای خلاصه را برای آزمایش حلقه بازی شما تجزیه و نمایش دهد.
جزئیات کلیدی درباره این مثال:
- چه کسی دادهها را ارائه میدهد: شما (توسعهدهنده آزمایشی) مسئول محاسبه و نوشتن همه سنجهها در این فایل از کد بازیتان هستید. Test Lab این نقاط داده را بهطور خودکار برای شما جمعآوری یا تولید نمیکند.
- افزودن فیلدهای سفارشی: نواحی علامتگذاریشده با
/.../نشاندهنده جایی است که میتوانید جفتهای کلید-مقدار سفارشی دلخواه (برای مثال،"rendered_vertices": 12000یا"ai_error_count": 0) را اضافه کنید. هنگام نوشتن فایل از برنامهتان، میتوانید هر ویژگی JSON معتبری را به خروجیتان اضافه کنید، بهشرطی که نام فیلدها با فیلدهای طرحواره مانندnameیاstart_timestampتداخل نداشته باشد. - کجا میتوانید فایل خروجی را پیدا کنید: پساز تکمیل آزمایش، فایل خروجی خام شما
در سطل نتایج Cloud Storage (
GCS) پروژه شما ذخیره میشود و قابلبارگیری است درون دایرکتوری مصنوع اجرای آزمایش. همچنین میتوانید خروجی تجزیهشده را در صفحه 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
}
چندین حلقه بازی
ممکن است اجرای چندین حلقه بازی در برنامهتان برایتان مفید باشد. حلقه عبارت است از اجرای کامل برنامه بازی از ابتدا تا انتها. برای مثال، اگر بازیتان چند سطح دارد، شاید بخواهید برای راهاندازی هر سطح یک حلقه بازی داشته باشید، بهجای اینکه یک حلقه داشته باشید که همه سطوح را تکرار کند. به این ترتیب، اگر برنامهتان در سطح ۳۲ ازکار بیفتد، میتوانید مستقیماً آن حلقه بازی را راهاندازی کنید تا ازکارافتادگی را بازتولید کنید و رفع اشکالها را آزمایش کنید.
برای فعال کردن برنامهتان برای اجرای همزمان چند حلقه:
اگر درحال اجرای آزمایشی با «مدیر حلقه آزمایش» هستید:
خط زیر را به مانیفست برنامهتان، داخل عنصر
<application>اضافه کنید:<meta-data android:name="com.google.test.loops" android:value="5" />
این هدف راهاندازی حاوی حلقه هدف بهعنوان پارامتر عدد صحیح است. در فیلد
android:value، میتوانید عدد صحیحی از ۱ تا ۱۰۲۴ (حداکثر تعداد حلقههای مجاز برای یک آزمایش) مشخص کنید. توجه داشته باشید که نمایهسازی حلقهها از ۱ شروع میشود، نه ۰.در برنامه «مدیر حلقه آزمایش»، صفحه انتخابی ظاهر میشود که به شما امکان میدهد حلقه(های) موردنظرتان را برای اجرا انتخاب کنید. اگر چند حلقه را انتخاب کنید، هر حلقه بهترتیب پساز تکمیل حلقه قبلی راهاندازی میشود.
اگر آزمایشی را با کنسول Firebase اجرا میکنید، فهرستی یا محدودهای از شمارههای حلقه را در فیلد سناریوها وارد کنید.
اگر آزمایشی را با gcloud CLI اجرا میکنید، بااستفاده از پرچم
--scenario-numbers، فهرستی از شمارههای حلقه را مشخص کنید. برای مثال،--scenario-numbers=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: برای حلقههایی که برای بازتولید تجربه کاربر واقعی هنگام بازی کردن استفاده میشود. هدف از آزمایش با این حلقهها پیدا کردن مشکلاتی است که کاربر واقعی هنگام بازی کردن با آنها مواجه میشود.com.google.test.loops.gpu_compatibility: برای حلقههایی که برای آزمایش مشکلات مربوط به GPU استفاده میشود. هدف از آزمایش با این حلقهها، اجرای کد GPU است که ممکن است در تولید بهدرستی اجرا نشود، تا مشکلات سختافزار و درایورها آشکار شود.-
com.google.test.loops.compatibility: حلقههای For که برای آزمایش طیف گستردهای از مشکلات سازگاری، ازجمله مشکلات I/O و مشکلات 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، میتوانید محدودهای یا مجموعهای از اعداد صحیح از ۱ تا ۱۰۲۴ (حداکثر تعداد حلقههای مجاز برای یک آزمایش) را مشخص کنید که نشاندهنده حلقههایی است که میخواهید برچسبگذاری کنید. توجه داشته باشید که نمایهسازی حلقهها از ۱ شروع میشود، نه از ۰. برای مثال،android:value="1,3-5"LABEL_NAME برای حلقههای ۱، ۳، ۴، و ۵ اعمال میشود.در برنامه «مدیر حلقه آزمایش»، یک یا چند برچسب را در فیلد برچسبها وارد کنید.
اگر آزمایشی را با کنسول Firebase اجرا میکنید، یک یا چند برچسب در فیلد برچسبها وارد کنید.
اگر آزمایشی را با gcloud CLI اجرا میکنید، یک یا چند برچسب سناریو را بااستفاده از پرچم
--scenario-labels(مثلاً--scenario-labels=performance,gpu) مشخص کنید.
پشتیبانی صدور پروانه برنامه
Test Lab از برنامههایی که از سرویس صدور پروانه برنامه ارائهشده توسط Google Play استفاده میکنند پشتیبانی میکند. برای بررسی موفقیتآمیز پروانه هنگام آزمایش برنامهتان با Test Lab، باید برنامهتان را در کانال تولید در «فروشگاه Play» منتشر کنید. برای آزمایش کردن برنامهتان در کانال آلفا یا بتا بااستفاده از Test Lab، قبلاز بارگذاری برنامهتان در Test Lab، بررسی پروانه را بردارید.
مشکلات شناخته شده
آزمایشهای «حلقه بازی» در Test Lab مشکلات شناختهشده زیر را دارد:
- برخیاز خرابیها از ردیابی پشته پشتیبانی نمیکنند. برای مثال، برخیاز ساختهای نسخه پخش ممکن است
خروجی فرایند
debuggerdرا بااستفاده ازprctl(PR_SET_DUMPABLE, 0)سرکوب کنند. برای کسب اطلاعات بیشتر،debuggerdرا ببینید. - درحالحاضر، سطح میانای برنامهسازی کاربردی ۱۹ بهدلیل خطاهای اجازه فایل پشتیبانی نمیشود.