بدء استخدام اختبارات "حلقة الألعاب"

قد يكون من الصعب إجراء اختبار الألعاب بشكل تلقائي عندما تكون تطبيقات الألعاب مبنية على إطارات عمل مختلفة لواجهة المستخدم. تسمح لك اختبارات "حلقة الألعاب" بدمج اختباراتك الأصلية مع Test Lab وتنفيذها بسهولة على الأجهزة التي تختارها. ويُجري اختبار "حلقة الألعاب" اختبارك عبر تطبيق الألعاب مع محاكاة إجراءات لاعب حقيقي. يوضِّح لك هذا الدليل كيفية إجراء اختبار "حلقة الألعاب"، ثم عرض نتائج الاختبار وإدارتها في وحدة تحكُّم Firebase.

اعتمادًا على محرّك اللعبة، يمكنك إجراء الاختبارات باستخدام حلقات واحدة أو أكثر. التكرار الحلقي هو تنفيذ كامل أو جزئي للاختبار على تطبيق الألعاب الخاص بك. ويمكن استخدام حلقات الألعاب لإجراء ما يلي:

  • يمكنك تشغيل مستوى من لعبتك بالطريقة نفسها التي سيشغِّلها المستخدم. يمكنك استخدام نصوص برمجية لإدخال المستخدم، أو السماح للمستخدم بعدم النشاط، أو استبدال المستخدم بذكاء اصطناعي إذا كان ذلك مناسبًا في لعبتك (على سبيل المثال، لنفترض أنّ لديك تطبيق ألعاب لسيارات السباق وقد سبق له تنفيذ الذكاء الاصطناعي). يمكنك بسهولة وضع سائق الذكاء الاصطناعي مسؤولًا عن إدخال المستخدم).
  • شغِّل لعبتك بأعلى جودة لمعرفة ما إذا كانت الأجهزة متوافقة معها.
  • إجراء اختبار فني (تجميع العديد من أدوات التظليل، وتنفيذها، والتحقق من أن الإخراج كما هو متوقع، وما إلى ذلك).

يمكنك إجراء اختبار "حلقة الألعاب" على جهاز اختبار واحد أو مجموعة من أجهزة الاختبار أو في مركز الاختبار الافتراضي. مع ذلك، لا ننصح بإجراء اختبارات 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>
    

    يسمح ذلك لتطبيق Test Lab بإطلاق لعبتك من خلال تشغيلها لغرض محدّد.

    .
  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، يمكنك إنشاء اختبار وتنفيذه على الفور في ألعاب الفيديو. ويمكنك اختيار إجراء اختبار في Test Lab إما من خلال وحدة تحكم Firebase أو واجهة سطر الأوامر (CLI) في gcloud أو على جهاز محلي باستخدام "مدير حلقة الاختبار".

التشغيل على جهاز محلي

إنّ Test Loop Manager من Test Lab هو تطبيق مفتوح المصدر يساعدك في دمج اختبارات حلقة الألعاب وتشغيلها على أجهزتك المحلية. كما يتيح لفريق ضمان الجودة تشغيل حلقات الألعاب نفسها على أجهزتهم.

لإجراء اختبار على جهاز محلي باستخدام "أداة إدارة حلقة الاختبار":

  1. يمكنك تنزيل Test Loop Manager على هاتف أو جهاز لوحي وثبِّته من خلال تشغيل ما يلي:
    adb install testloopmanager.apk
  2. على جهازك، افتح تطبيق Test Loop Apps على هاتفك أو جهازك اللوحي. يعرض التطبيق قائمة بالتطبيقات التي يمكن تشغيلها باستخدام حلقات الألعاب على جهازك. إذا لم يظهر لك تطبيق الألعاب هنا، تأكّد من أنّ فلتر الأهداف يتطابق مع الفلتر الموضّح في الخطوة الأولى من قسم "قبل البدء".
  3. اختَر تطبيق الألعاب الذي تريد تشغيله، ثم اختَر عدد التكرارات التي تريد تشغيلها. ملاحظة: في هذه الخطوة، يمكنك اختيار تشغيل مجموعة فرعية من التكرارات الحلقية بدلاً من تكرار حلقي واحد. لمزيد من المعلومات حول تشغيل تكرارات متعددة في وقت واحد، راجع الميزات الاختيارية.
  4. انقر على تشغيل اختبار. سيبدأ تشغيل الاختبار على الفور.

التشغيل في مركز الاختبار الافتراضي

يمكنك إجراء اختبار حلقة الألعاب في Test Lab إما باستخدام وحدة تحكُّم Firebase أو gcloud CLI. قبل البدء، افتح وحدة تحكُّم Firebase وأنشئ مشروعًا، إذا لم يسبق لك إجراء ذلك.

استخدام "وحدة تحكُّم Firebase"

  1. في وحدة تحكُّم Firebase، انقر على Test Lab من اللوحة اليمنى.
  2. انقر على إجراء الاختبار الأول (أو إجراء اختبار إذا كان مشروعك قد سبق له إجراء اختبار).
  3. اختَر حلقة الألعاب كنوع الاختبار، ثم انقر على متابعة.
  4. انقر على تصفّح، ثم تصفَّح للوصول إلى ملف .apk الخاص بتطبيقك. ملاحظة: في هذه الخطوة، يمكنك اختيار تشغيل مجموعة فرعية من التكرارات الحلقية بدلاً من تكرار حلقي واحد. لمزيد من المعلومات حول تشغيل تكرارات متعددة في وقت واحد، يُرجى الاطّلاع على الميزات الاختيارية.
  5. انقر على متابعة.
  6. اختَر الأجهزة المادية التي تريد استخدامها في اختبار تطبيقك.
  7. انقر على بدء الاختبارات.

للحصول على مزيد من المعلومات حول بدء استخدام "وحدة تحكُّم Firebase"، اطّلِع على المقالة بدء الاختبار باستخدام "وحدة تحكُّم Firebase".

استخدام سطر أوامر gcloud (CLI)

  1. نزِّل حزمة تطوير البرامج (SDK) في Google Cloud وثبِّتها، إذا لم يسبق لك إجراء ذلك.

  2. سجِّل الدخول إلى gcloud CLI باستخدام حسابك على Google:

    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(). بعد إجراء اختبار، يمكنك الوصول إلى بيانات المخرجات هذه في قسم مركز الاختبار الافتراضي ضمن وحدة تحكُّم 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);
}

مثال على ملف الإخراج

يمكنك استخدام ملفات بيانات المخرجات (بتنسيق مثالي أدناه) لعرض نتائج اختبار حلقة الألعاب في قسم مركز الاختبار الافتراضي ضمن وحدة تحكُّم 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، يمكنك تشغيل حلقة اللعبة مباشرةً لإعادة إنتاج الأعطال واختبار إصلاحات الأخطاء.

لتمكين تطبيقك من تشغيل تكرارات متعددة في وقت واحد:

  • في حال إجراء اختبار باستخدام "مدير حلقة الاختبار":

    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 الناتجة.

تصنيف حلقات الألعاب

عند تصنيف حلقات الألعاب باستخدام تصنيف واحد أو أكثر من السيناريوهات، يمكنك أنت وفريق ضمان الجودة إطلاق مجموعة من حلقات الألعاب ذات الصلة بسهولة (مثل "جميع حلقات ألعاب التوافق") واختبارها في مصفوفة واحدة. يمكنك إنشاء التسميات الخاصة بك أو استخدام التسميات المحددة مسبقًا التي تقدمها Test Lab:

  • com.google.test.loops.player_experience: بالنسبة إلى التكرارات الحلقية التي تعيد تقديم تجربة المستخدم الحقيقية عند تشغيل اللعبة. الهدف من الاختبار باستخدام هذه الحلقات هو العثور على المشكلات التي قد يواجهها المستخدم الحقيقي أثناء اللعب.
  • com.google.test.loops.gpu_compatibility: للحلقات المستخدَمة لاختبار المشاكل المتعلقة بوحدة معالجة الرسومات الهدف من الاختبار باستخدام هذه الحلقات هو تنفيذ رمز وحدة معالجة الرسومات التي قد لا يتم تشغيلها بشكل صحيح في مرحلة الإنتاج، ما يؤدي إلى كشف المشاكل المتعلّقة بالأجهزة وبرامج التشغيل.
  • com.google.test.loops.compatibility: للتكرارات المستخدمة لاختبار مجموعة واسعة من مشاكل التوافق، بما في ذلك مشاكل وحدات الإدخال والإخراج ومشاكل OpenSSL.
  • com.google.test.loops.performance: بالنسبة إلى الحلقات المستخدَمة لاختبار أداء الجهاز. على سبيل المثال، قد تعمل اللعبة في إعدادات الرسومات الأكثر تعقيدًا لمعرفة سلوك جهاز جديد.

لتمكين تطبيقك من تشغيل التكرارات الحلقية بنفس التصنيف:

  • في حال إجراء اختبار باستخدام "مدير حلقة الاختبار":

    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. في تطبيق "مدير حلقة الاختبار"، أدخِل تصنيفًا واحدًا أو أكثر في حقل التصنيفات.

  • إذا كنت تجري اختبارًا باستخدام "وحدة تحكُّم 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.
  • المستوى 19 من واجهة برمجة التطبيقات غير متاح حاليًا بسبب أخطاء في أذونات الملفات.