بدء استخدام اختبارات Game Loop

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

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

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

يمكنك إجراء اختبار Game Loop على جهاز اختبار واحد أو مجموعة من أجهزة الاختبار. في Test Lab. مع ذلك، لا ننصح بإجراء اختبارات حلقة الألعاب على الأجهزة الافتراضية الأجهزة لأنها تحتوي على معدلات عرض إطارات للرسومات أقل من الأجهزة الفعلية.

قبل البدء

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

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

  1. تنزيل Test Loop Manager على هاتف أو جهاز لوحي وتثبيته من خلال تشغيل:
    adb install testloopmanager.apk
  2. على جهازك، افتح تطبيق Test Loop Apps على هاتفك أو جهازك اللوحي. يعرض التطبيق قائمة بالتطبيقات على جهازك التي يمكن تشغيلها باستخدام حلقات الألعاب. إذا لم يظهر لك لعبتك على الأجهزة الجوّالة هنا، يُرجى التأكّد من يتطابق فلتر الأهداف مع الفلتر الموضّح في الخطوة الأولى من قسم "قبل البدء":
  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

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

يتّبع Test Lab أفضل الممارسات لمشاركة ملف بين التطبيقات الموضّحة في مشاركة ملف في طريقة 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. في تطبيق "مدير حلقة الاختبار"، تظهر شاشة اختيار تسمح لك باختيار الحلقات التي تريد تشغيلها. في حال اختيار عدة خيارات التكرار الحلقي، يتم تشغيل كل تكرار في تسلسل بعد التكرار الحلقي السابق تكتمل.

  • إذا كنت بصدد إجراء اختبار باستخدام وحدة تحكّم 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: دوائر For الحلقية المستخدَمة لاختبار مجموعة واسعة من مشاكل التوافق، بما في ذلك مشاكل I/O وOpenSSL
  • com.google.test.loops.performance: حلقات For المستخدَمة لاختبار أداء الجهاز على سبيل المثال، قد يتم تشغيل لعبة باستخدام إعدادات الرسومات الأكثر تعقيدًا لتحديد أداء جهاز جديد.

لتفعيل تطبيقك لتشغيل الحلقات باستخدام التصنيف نفسه:

  • في حال إجراء اختبار باستخدام 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 (الحد الأقصى لعدد الحلقات المسموح به لاختبار واحد) التي representتمثل الحلقات التي تريد تصنيفها. ملاحظة: تتم فهرسة التكرارات الحلقية بدءًا من من 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 من واجهة برمجة التطبيقات بسبب أخطاء في أذونات الملفات.