وقتی برنامههای بازی براساس چارچوبهای مختلف رابط کاربری ساخته میشوند، خودکارسازی آزمایش بازی میتواند دشوار باشد. آزمایشهای «حلقه بازی» به شما امکان میدهد آزمایشهای بومیتان را با Test Lab ادغام کنید و بهراحتی آنها را در دستگاههای انتخابیتان اجرا کنید. آزمایش «حلقه بازی» آزمایش شما را ازطریق برنامه بازیتان اجرا میکند و کنشهای یک بازیکن واقعی را شبیهسازی میکند. این راهنما نحوه اجرای آزمایش «حلقه بازی» و سپس مشاهده و مدیریت نتایج آزمایش در کنسول Firebase را به شما نشان میدهد.
آزمایش حلقه بازی چیست؟
ازآنجاییکه برنامههای بازی در چارچوبها و موتورهای مختلف میانای کاربری مثل کد Unity، Unreal، یا OpenGL/Vulkan C++ پردازش میشوند، ابزارهای خودکارسازی استاندارد نمیتوانند عناصر میانای کاربری را بازرسی کنند یا با آنها تعامل داشته باشند. آزمایش حلقه بازی به شما امکان میدهد آزمایشهای موتور بومی خود را با Test Lab ادغام کنید. این کار با راهاندازی بازیتان با هدفی که حاوی شماره سناریو خاصی است انجام میشود. این شماره سناریو برنامه شما را ترغیب میکند تا منطق پیشنوشتهشده، شبیهسازیهای هوش مصنوعی، یا بررسیهای عملکرد را مستقیماً در موتور بازیتان اجرا کند.
پساز راهاندازی، Test Lab دیگر با واسط کاربر بازی شما تعامل ندارد. درعوض، Test Lab بهعنوان محیط و انتقال آزمایش عمل میکند: سناریو خاص را راهاندازی میکند، خرابیها و زمانهای اتمام را پایش میکند، و وقتی برنامه شما اجرای حلقه را تمام میکند، گزارشهای نتیجه سفارشی را جمعآوری میکند.
تفاوت حلقههای بازی با آزمایشهای ابزار دقیق
- آزمایشهای ابزار دقیق (مثل Espresso یا UI Automator) برای هدایت تعاملات میانای کاربر، کلیک کردن روی دکمهها، و ادعای وضعیت برنامه در سلسلهمراتب «نمای Android» از خارج از برنامه شما، به چارچوبهای خارجی متکی هستند.
- آزمایشهای حلقه بازی منطق آزمایش را به برنامهتان واگذار میکند. برنامه شما حلقه آزمایش داخلی یا شبیهسازی خود را بدون تعامل با میانای کاربر خارجی اجرا میکند، درحالیکه Test Lab سناریو شما را راهاندازی میکند و برونداد آزمایش را جمعآوری میکند.
مثالها
فرض کنید میخواهید تأیید کنید که بازی شما در دستگاههای فیزیکی مختلف حداقل ۶۰ فریم در ثانیه را حفظ میکند. میتوانید سناریو 1 را در کد بازیتان پیادهسازی کنید تا پیچیدهترین سطح بصریتان را بار کند و به یک بازیکن هوش مصنوعی یا یک دستورگان خودکار اجازه دهد آن را بهمدت دو دقیقه بازی کند.
وقتی Test Lab سناریو � را راهاندازی میکند، بازی شما پخش هوش مصنوعی را شروع میکند،
زمانهای پرداز قاب و استفاده از حافظه را پایش میکند، این معیارها را به
فایل گزارش برونداد سفارشی (logFile) جاریسازی میکند، و پساز تکمیل، finish() را فرا میخواند.1
سپس Test Lab فایل گزارش را ضبط میکند و آن را در Cloud
Storage و کنسول Firebase دردسترس شما قرار میدهد.
موارد استفاده
بسته به موتور بازی، میتوانید آزمایشها را با یک یا چند حلقه پیادهسازی کنید. حلقه یک اجرای کامل یا جزئی از آزمایش شما در برنامه بازیتان است. از حلقههای بازی میتوان برای موارد زیر استفاده کرد:
- سطحی از بازیتان را به همان روشی که کاربر نهایی بازی میکند اجرا کنید. میتوانید ورودی کاربر را برنامهریزی کنید، کاربر را در حالت بیکار قرار دهید، یا اگر در بازیتان منطقی باشد، کاربر را با هوش مصنوعی جایگزین کنید (برای مثال، اگر برنامه بازی ماشینسواری دارید و ازقبل هوش مصنوعی را پیادهسازی کردهاید، میتوانید راننده هوش مصنوعی را مسئول ورودی کاربر کنید).
- بازی را با بالاترین تنظیم کیفیت اجرا کنید تا ببینید دستگاهها از آن پشتیبانی میکنند یا نه.
- آزمایش فنی اجرا کنید (چندین سایهزن را گردآوری کنید، آنها را اجرا کنید، بررسی کنید که برونداد همانطور که انتظار میرود باشد، و غیره).
میتوانید آزمایش «حلقه بازی» را روی یک دستگاه آزمایش، مجموعهای از دستگاههای آزمایش، یا روی Test Lab اجرا کنید. بااینحال، توصیه نمیکنیم آزمایشهای «حلقه بازی» را در دستگاههای مجازی اجرا کنید زیرا نرخ فریم گرافیکی آنها نسبتبه دستگاههای فیزیکی پایینتر است.
قبل از شروع
برای پیادهسازی آزمایش، ابتدا باید برنامهتان را برای آزمایشهای «حلقه بازی» پیکربندی کنید.
در مانیفست برنامه، فیلتر هدف جدیدی به فعالیت خود اضافه کنید:
<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 کنسول یا میانای خط فرمان gcloud (CLI)، یا در دستگاه محلی بااستفاده از «مدیر حلقه آزمایش» اجرا کنید.
اجرا در دستگاه محلی
Test Labمدیر حلقه آزمایش برنامهای متنباز است که به شما کمک میکند آزمایشهای «حلقه بازی» را یکپارچه کنید و آنها را در دستگاههای محلیتان اجرا کنید. همچنین به تیم «تضمین کیفیت» شما امکان میدهد تا حلقههای بازی یکسانی را در دستگاههایشان اجرا کنند.
برای اجرای آزمایش در دستگاه محلی بااستفاده از «مدیر حلقه آزمایش»:
- Test Loop Manager را در تلفن یا رایانه لوحی بارگیری کنید و با اجرای این دستور آن را نصب کنید:
adb install testloopmanager.apk
- در دستگاهتان، برنامه برنامههای حلقه آزمایش را در تلفن یا رایانه لوحی باز کنید. برنامه فهرستی از برنامههای موجود در دستگاهتان را که میتوانند با حلقههای بازی اجرا شوند نمایش میدهد. اگر برنامه بازیتان را در اینجا نمیبینید، مطمئن شوید فیلتر هدف شما با فیلتر شرحدادهشده در اولین مرحله بخش «قبلاز شروع» مطابقت داشته باشد.
- برنامه بازی خود را انتخاب کنید، سپس تعداد حلقههایی را که میخواهید اجرا کنید انتخاب کنید. توجه: در این مرحله، میتوانید بهجای فقط یک حلقه، زیرمجموعهای از حلقهها را اجرا کنید. برای اطلاعات بیشتر درباره اجرای همزمان چند حلقه، ویژگیهای اختیاری را ببینید.
- روی اجرای آزمایش کلیک کنید. آزمایش شما بلافاصله شروع میشود.
اجرا در Test Lab
میتوانید آزمون «حلقه بازی» را در Test Lab بااستفاده از کنسول Firebase یا gcloud CLI اجرا کنید. قبلاز شروع، اگر قبلاً این کار را نکردهاید، کنسول Firebase را باز کنید و پروژهای ایجاد کنید.
استفاده از کنسول Firebase
- در کنسول Firebase، از پانل سمت راست روی Test Lab کلیک کنید.
- روی اجرای اولین آزمایش (یا اجرای آزمایش اگر پروژه شما قبلاً آزمایشی را اجرا کرده است) کلیک کنید.
- حلقه بازی را بهعنوان نوع آزمایش انتخاب کنید، و سپس روی ادامه دادن کلیک کنید.
- روی مرور کلیک کنید، و سپس به فایل
.apkبرنامه خود مرور کنید. توجه: در این مرحله، میتوانید بهجای فقط یک حلقه، زیرمجموعهای از حلقهها را اجرا کنید. برای اطلاعات بیشتر درباره اجرای همزمان چند حلقه، ویژگیهای اختیاری را ببینید. - روی ادامه کلیک کنید.
- دستگاههای فیزیکی را برای استفاده در آزمایش برنامه انتخاب کنید.
- روی شروع آزمایشها کلیک کنید.
برای اطلاعات بیشتر درباره شروع کار با کنسول Firebase، به شروع آزمایش با کنسول Firebase مراجعه کنید.
استفاده از خط فرمان gcloud (CLI)
اگر قبلاً این کار را نکردهاید، 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: برای حلقههایی که برای آزمایش طیف وسیعی از مشکلات سازگاری، ازجمله مشکلات ورودی/خروجی و مشکلات OpenSSL استفاده میشوند. com.google.test.loops.performance: حلقههای «برای» که برای آزمایش عملکرد دستگاه استفاده میشود. برای مثال، یک بازی ممکن است با پیچیدهترین تنظیمات گرافیکی اجرا شود تا نحوه عملکرد دستگاه جدید را ببیند.
برای فعال کردن برنامه خود برای اجرای حلقهها با برچسب یکسان:
اگر درحال اجرای آزمایشی با «مدیر حلقه آزمایش» هستید:
در مانیفست برنامه، خط فراداده زیر را اضافه کنید و 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مراجعه کنید. - درحالحاضر از «سطح میانای برنامهسازی کاربردی ۱۹» بهدلیل خطاهای اجازه فایل پشتیبانی نمیشود.