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

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

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

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

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

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

برای پیاده‌سازی یک تست، ابتدا باید برنامه خود را برای تست‌های حلقه بازی پیکربندی کنید.

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

    <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 اجازه می‌دهد تا بازی شما را با هدف خاصی راه‌اندازی کند.

  2. در کد خود (توصیه می‌کنیم داخل تعریف متد 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
    }

    این به اکتیویتی شما اجازه می‌دهد تا intent ای که آن را اجرا می‌کند، بررسی کند. در صورت تمایل می‌توانید این کد را بعداً نیز اضافه کنید (مثلاً پس از بارگذاری اولیه موتور بازی خود).

  3. توصیه می‌شود: در پایان آزمون، موارد زیر را اضافه کنید:

    Kotlin

    yourActivity.finish()

    Java

    yourActivity.finish();

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

یک تست حلقه بازی ایجاد و اجرا کنید

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

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

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

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

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

اجرا در Test Lab

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

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

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

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

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

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

  2. با استفاده از حساب گوگل خود وارد رابط خط فرمان gcloud شوید:

    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 چندین ویژگی اختیاری ارائه می‌دهد که به شما امکان می‌دهد تست‌های خود را بیشتر سفارشی کنید، از جمله امکان نوشتن داده‌های خروجی، پشتیبانی از چندین حلقه بازی و برچسب‌گذاری برای حلقه‌های مرتبط.

نوشتن داده‌های خروجی

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

Test Lab از بهترین شیوه‌ها برای اشتراک‌گذاری فایل بین برنامه‌ها که در بخش «اشتراک‌گذاری فایل» توضیح داده شده است، پیروی می‌کند. در متد onCreate() مربوط به اکتیویتی خود، جایی که intent شما قرار دارد، می‌توانید فایل خروجی داده خود را با اجرای کد زیر بررسی کنید:

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

سی++

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

حلقه‌های بازی چندگانه

ممکن است اجرای چندین حلقه بازی در برنامه‌تان مفید باشد. یک حلقه، یک مرور کامل از برنامه بازی شما از ابتدا تا انتها است. به عنوان مثال، اگر چندین سطح در بازی خود دارید، ممکن است بخواهید به جای یک حلقه که همه آنها را تکرار می‌کند، یک حلقه بازی برای اجرای هر سطح داشته باشید. به این ترتیب، اگر برنامه شما در سطح ۳۲ از کار بیفتد، می‌توانید مستقیماً آن حلقه بازی را اجرا کنید تا از کار افتادن را دوباره ایجاد کرده و رفع اشکالات را آزمایش کنید.

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

  • اگر در حال اجرای تست با Test Loop Manager هستید:

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

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

      این هدف راه‌اندازی شامل حلقه هدف به عنوان یک پارامتر عدد صحیح است. در فیلد android:value ، می‌توانید یک عدد صحیح از ۱ تا ۱۰۲۴ (حداکثر تعداد حلقه‌های مجاز برای یک تست واحد) تعیین کنید. توجه داشته باشید که حلقه‌ها از ۱ شروع می‌شوند، نه ۰.

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

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

  • اگر در حال اجرای تست با رابط خط فرمان gcloud هستید، با استفاده از پرچم --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 : برای حلقه‌هایی که برای آزمایش عملکرد دستگاه استفاده می‌شوند. برای مثال، یک بازی ممکن است با پیچیده‌ترین تنظیمات گرافیکی اجرا شود تا نحوه رفتار یک دستگاه جدید بررسی شود.

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

  • اگر در حال اجرای تست با Test Loop Manager هستید:

    1. در مانیفست برنامه خود، خط متاداده زیر را اضافه کنید و 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 به حلقه‌های ۱، ۳، ۴ و ۵ اعمال می‌کند.

    2. در برنامه Test Loop Manager، یک یا چند برچسب را در فیلد برچسب‌ها وارد کنید.

  • اگر در حال اجرای تست با کنسول Firebase هستید، یک یا چند برچسب را در فیلد برچسب‌ها وارد کنید.

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

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

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

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

تست‌های حلقه بازی در Test Lab مشکلات شناخته‌شده‌ی زیر را دارند:

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