با تست های Game Loop شروع کنید

زمانی که برنامه‌های بازی بر روی چارچوب‌های مختلف رابط کاربری ساخته می‌شوند، آزمایش خودکار بازی دشوار است. تست‌های حلقه بازی به شما این امکان را می‌دهند که تست‌های بومی خود را با Test Lab ادغام کنید و به راحتی آنها را روی دستگاه‌هایی که انتخاب می‌کنید اجرا کنید. تست Game Loop تست شما را از طریق برنامه بازی شما انجام می دهد و در عین حال اقدامات یک بازیکن واقعی را شبیه سازی می کند. این راهنما به شما نشان می دهد که چگونه یک تست Game Loop را اجرا کنید، سپس نتایج آزمایش خود را در کنسول Firebase مشاهده و مدیریت کنید.

بسته به موتور بازی خود، می توانید تست ها را با حلقه های تک یا چندگانه اجرا کنید. یک حلقه آزمایش کامل یا جزئی از آزمایش شما در برنامه بازی شما است. از حلقه های بازی می توان برای موارد زیر استفاده کرد:

  • یک سطح از بازی خود را به همان شیوه ای که کاربر نهایی آن را بازی می کند اجرا کنید. می‌توانید ورودی کاربر را اسکریپت کنید، اجازه دهید کاربر بی‌حرکت باشد، یا اگر در بازی شما منطقی است، کاربر را با یک هوش مصنوعی جایگزین کنید (مثلاً، بگویید که یک برنامه بازی ماشین مسابقه دارید و قبلاً یک هوش مصنوعی پیاده‌سازی کرده‌اید. می‌توانید به راحتی یک درایور هوش مصنوعی را مسئول ورودی کاربر قرار دهید).
  • بازی خود را با بالاترین کیفیت اجرا کنید تا ببینید آیا دستگاه‌ها از آن پشتیبانی می‌کنند یا خیر.
  • یک تست فنی را اجرا کنید (چند سایه زن را کامپایل کنید، آنها را اجرا کنید، بررسی کنید که خروجی مطابق انتظار است و غیره).

می‌توانید تست حلقه بازی را روی یک دستگاه آزمایشی، مجموعه‌ای از دستگاه‌های آزمایشی یا در آزمایشگاه آزمایشی اجرا کنید. با این حال، اجرای تست های Game Loop را در دستگاه های مجازی توصیه نمی کنیم زیرا نرخ فریم گرافیکی آنها نسبت به دستگاه های فیزیکی کمتر است.

قبل از اینکه شروع کنی

برای اجرای یک تست، ابتدا باید اپلیکیشن خود را برای تست های Game Loop پیکربندی کنید.

  1. در مانیفست برنامه خود، یک فیلتر قصد جدید به فعالیت خود اضافه کنید:

    <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>
    

    این به آزمایشگاه تست اجازه می دهد تا بازی شما را با راه اندازی آن با یک هدف خاص راه اندازی کند.

  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();

    هنگامی که تست حلقه بازی کامل شد، برنامه شما را می‌بندد. آزمایش برای شروع حلقه بعدی به چارچوب رابط کاربری برنامه شما متکی است و بستن برنامه به آن می گوید که آزمایش به پایان رسیده است.

یک تست Game Loop ایجاد و اجرا کنید

بعد از اینکه برنامه خود را برای تست های Game Loop پیکربندی کردید، می توانید بلافاصله یک آزمایش ایجاد کنید و آن را در برنامه بازی خود اجرا کنید. می‌توانید آزمایشی را در Test Lab با استفاده از کنسول Firebase یا رابط خط فرمان gcloud (CLI) یا روی یک دستگاه محلی با استفاده از Test Loop Manager اجرا کنید.

روی یک دستگاه محلی اجرا کنید

Test Lab's Test Loop Manager یک برنامه منبع باز است که به شما کمک می کند تست های Game Loop را ادغام کنید و آنها را در دستگاه های محلی خود اجرا کنید. همچنین به تیم تضمین کیفیت شما اجازه می‌دهد تا حلقه‌های بازی مشابهی را روی دستگاه‌های خود اجرا کند.

برای اجرای یک آزمایش بر روی یک دستگاه محلی با استفاده از Test Loop Manager:

  1. Test Loop Manager را روی تلفن یا رایانه لوحی دانلود کنید و با اجرای:
    adb install testloopmanager.apk
    آن را نصب کنید
  2. در دستگاه خود، برنامه Test Loop Apps را در تلفن یا رایانه لوحی خود باز کنید. این برنامه لیستی از برنامه های موجود در دستگاه شما را نشان می دهد که می توانند با حلقه های بازی اجرا شوند. اگر برنامه بازی خود را در اینجا نمی‌بینید، مطمئن شوید که فیلتر قصد شما با فیلتری که در مرحله اول بخش قبل از شروع توضیح داده شد مطابقت دارد.
  3. برنامه بازی خود را انتخاب کنید، سپس تعداد حلقه هایی را که می خواهید اجرا کنید انتخاب کنید. توجه: در این مرحله می‌توانید به جای یک حلقه، زیرمجموعه‌ای از حلقه‌ها را اجرا کنید. برای اطلاعات بیشتر در مورد اجرای چندین حلقه به طور همزمان، ویژگی های اختیاری را ببینید.
  4. روی Run test کلیک کنید. تست شما بلافاصله شروع به اجرا می کند.

در آزمایشگاه تست اجرا کنید

می‌توانید با استفاده از کنسول Firebase یا gcloud CLI یک تست Game Loop را در Test Lab اجرا کنید. قبل از شروع، اگر قبلاً این کار را نکرده اید، کنسول Firebase را باز کنید و یک پروژه ایجاد کنید.

از کنسول Firebase استفاده کنید

  1. در کنسول Firebase، روی Test Lab از پانل سمت چپ کلیک کنید.
  2. روی Run Your First Test (یا اجرای تست اگر پروژه شما قبلاً آزمایشی انجام داده است) کلیک کنید.
  3. Game Loop را به عنوان نوع تست انتخاب کنید و سپس روی Continue کلیک کنید.
  4. روی Browse کلیک کنید و سپس فایل .apk برنامه خود را مرور کنید. توجه: در این مرحله می‌توانید به جای یک حلقه، زیرمجموعه‌ای از حلقه‌ها را اجرا کنید. برای اطلاعات بیشتر در مورد اجرای چندین حلقه به طور همزمان، ویژگی های اختیاری را ببینید.
  5. روی Continue کلیک کنید.
  6. دستگاه های فیزیکی را برای آزمایش برنامه خود انتخاب کنید.
  7. روی Start Tests کلیک کنید.

برای اطلاعات بیشتر درباره شروع کار با کنسول Firebase، به شروع آزمایش با کنسول Firebase مراجعه کنید.

از خط فرمان gcloud (CLI) استفاده کنید

  1. اگر قبلاً این کار را نکرده‌اید، Google Cloud SDK را دانلود و نصب کنید

  2. با استفاده از حساب Google خود به gcloud CLI وارد شوید:

    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
    

برای اطلاعات بیشتر در مورد شروع کار با gcloud CLI، به شروع آزمایش از خط فرمان gcloud مراجعه کنید.

ویژگی های اختیاری

Test Lab چندین ویژگی اختیاری را ارائه می‌دهد که به شما امکان می‌دهد تست‌های خود را بیشتر سفارشی کنید، از جمله توانایی نوشتن داده‌های خروجی، پشتیبانی از حلقه‌های بازی متعدد و برچسب‌ها برای حلقه‌های مرتبط.

داده های خروجی را بنویسید

تست Game Loop شما می تواند خروجی را روی فایلی که در متد launchIntent.getData() مشخص شده است بنویسد. پس از اجرای یک آزمایش، می‌توانید به این داده‌های خروجی در بخش Test Lab کنسول Firebase دسترسی داشته باشید ( به مثال فایل خروجی تست حلقه بازی مراجعه کنید).

آزمایشگاه تست بهترین روش‌ها را برای اشتراک‌گذاری یک فایل بین برنامه‌های شرح داده شده در اشتراک‌گذاری فایل دنبال می‌کند. در متد 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 اجرا می کنید:

    1. در داخل عنصر <application> خط زیر را به مانیفست برنامه خود اضافه کنید:

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

      این هدف راه اندازی شامل حلقه هدف به عنوان یک پارامتر عدد صحیح است. در قسمت android:value می توانید یک عدد صحیح از 1 تا 1024 (حداکثر تعداد حلقه های مجاز برای یک تست) را مشخص کنید. توجه داشته باشید که حلقه ها از 1 و نه 0 شروع می شوند.

    2. در برنامه Test Loop Manager، یک صفحه انتخاب ظاهر می شود که به شما امکان می دهد حلقه(هایی) را که می خواهید اجرا کنید انتخاب کنید. اگر چندین حلقه را انتخاب کنید، هر حلقه به ترتیب پس از تکمیل حلقه قبلی راه اندازی می شود.

  • اگر آزمایشی را با کنسول Firebase انجام می دهید، یک لیست یا محدوده ای از اعداد حلقه را در قسمت سناریوها وارد کنید.

  • اگر آزمایشی را با gcloud CLI انجام می‌دهید، فهرستی از اعداد حلقه را با استفاده از پرچم --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 به دست آمده تغییر دهید.

حلقه های بازی را برچسب بزنید

هنگامی که حلقه‌های بازی خود را با یک یا چند برچسب سناریو برچسب‌گذاری می‌کنید، شما و تیم QA خود می‌توانید به راحتی مجموعه‌ای از حلقه‌های بازی مرتبط را راه‌اندازی کنید (مثلاً "همه حلقه‌های بازی سازگاری") و آنها را در یک ماتریس آزمایش کنید. می توانید برچسب های خود را ایجاد کنید یا از برچسب های از پیش تعریف شده ارائه شده توسط Test Lab استفاده کنید:

  • com.google.test.loops.player_experience : برای حلقه هایی که برای بازتولید تجربه واقعی کاربر در هنگام بازی استفاده می شود. هدف از آزمایش با این حلقه‌ها یافتن مشکلاتی است که یک کاربر واقعی در حین انجام بازی با آن مواجه می‌شود.
  • com.google.test.loops.gpu_compatibility : برای حلقه هایی که برای آزمایش مسائل مربوط به GPU استفاده می شوند. هدف از آزمایش با این حلقه‌ها اجرای کدهای GPU است که ممکن است به درستی در تولید اجرا نشود، تا مشکلات سخت‌افزار و درایورها را آشکار کند.
  • com.google.test.loops.compatibility : برای حلقه هایی که برای آزمایش طیف وسیعی از مشکلات سازگاری، از جمله مشکلات I/O و مسائل OpenSSL استفاده می شود.
  • com.google.test.loops.performance : برای حلقه هایی که برای آزمایش عملکرد دستگاه استفاده می شوند. برای مثال، یک بازی ممکن است در پیچیده ترین تنظیمات گرافیکی اجرا شود تا ببیند یک دستگاه جدید چگونه رفتار می کند.

برای فعال کردن برنامه خود برای اجرای حلقه هایی با همان برچسب:

  • اگر آزمایشی را با 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 انجام می‌دهید، یک یا چند برچسب را در قسمت Labels وارد کنید.

  • اگر آزمایشی را با gcloud CLI انجام می‌دهید، یک یا چند برچسب سناریو را با استفاده از پرچم --scenario-labels (مثلا --scenario-labels=performance,gpu ) مشخص کنید.

پشتیبانی از مجوز برنامه

Test Lab از برنامه هایی پشتیبانی می کند که از سرویس مجوز برنامه ارائه شده توسط Google Play استفاده می کنند. برای بررسی موفقیت آمیز مجوز هنگام آزمایش برنامه خود با Test Lab، باید برنامه خود را در کانال تولید در فروشگاه Play منتشر کنید. برای آزمایش برنامه خود در کانال آلفا یا بتا با استفاده از Test Lab، قبل از آپلود برنامه خود در Test Lab، بررسی مجوز را بردارید.

مشکلات شناخته شده

تست های حلقه بازی در آزمایشگاه تست دارای مشکلات شناخته شده زیر هستند:

  • برخی از خرابی ها از backtraces پشتیبانی نمی کنند. برای مثال، برخی از نسخه‌های انتشار ممکن است خروجی فرآیند debuggerd را با استفاده از prctl(PR_SET_DUMPABLE, 0) سرکوب کنند. برای کسب اطلاعات بیشتر، debuggerd ببینید.
  • API Level 19 به دلیل خطاهای مجوز فایل در حال حاضر پشتیبانی نمی شود.