Catch up on everthing we announced at this year's Firebase Summit. Learn more

Начните с тестов Game Loop

Может быть сложно автоматизировать тестирование игр, когда игровые приложения построены на разных платформах пользовательского интерфейса. Тесты Game Loop позволяют интегрировать собственные тесты с Test Lab и легко запускать их на выбранных вами устройствах. Тест Game Loop запускает ваш тест через ваше игровое приложение, имитируя действия реального игрока. В этом руководстве показано, как запустить тест Game Loop, а затем просмотреть результаты теста и управлять ими в консоли Firebase.

В зависимости от вашего игрового движка, вы можете осуществить тесты с одним или несколькими контурами . Цикл - это полное или частичное выполнение теста в игровом приложении. Игровые циклы можно использовать для:

  • Запускайте уровень своей игры так же, как конечный пользователь. Вы можете создать сценарий ввода пользователя, позволить пользователю бездействовать или заменить пользователя ИИ, если это имеет смысл в вашей игре (например, скажем, у вас есть игровое приложение для гоночных автомобилей и уже реализован ИИ. Вы можете легко назначить драйвер AI, отвечающий за ввод данных пользователем).
  • Запустите игру с настройками высочайшего качества, чтобы узнать, поддерживают ли ее устройства.
  • Выполните технический тест (скомпилируйте несколько шейдеров, выполните их, убедитесь, что результат соответствует ожиданиям и т. Д.).

Вы можете запустить тест Game Loop на одном тестовом устройстве, на наборе тестовых устройств или в Test Lab. Однако мы не рекомендуем запускать тесты 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>
    

    Это позволяет Test Lab запускать вашу игру, вызывая ее с определенным намерением.

  2. В своем коде (мы рекомендуем внутри onCreate объявления методы), добавьте следующее:

    Джава

    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
    }

    Котлин + 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
    }

    Это позволяет вашей активности проверить намерение, которое ее запускает. Вы также можете добавить этот код позже, если хотите (например, после начальной загрузки вашего игрового движка).

  3. Рекомендуется: в конце теста добавить:

    Джава

    yourActivity.finish();

    Котлин + KTX

    yourActivity.finish()

    Это закроет ваше приложение по завершении теста Game Loop. Тест полагается на инфраструктуру пользовательского интерфейса вашего приложения для запуска следующего цикла, а закрытие вашего приложения сообщает ему, что тест завершен.

Создайте и запустите тест Game Loop

После настройки приложения для тестов Game Loop вы можете сразу создать тест и запустить его в своем игровом приложении. Вы можете запустить тест в лаборатории тестирования , используя либо консоль Firebase или интерфейс командной строки gcloud (CLI) , или на локальном устройстве с помощью теста Loop диспетчера .

Запуск на локальном устройстве

Test Loop Менеджер Test Lab , является приложением с открытым исходным кодом , который позволяет интегрировать испытания Game Loop и запустить их на локальных устройствах. Это также позволяет вашей команде по обеспечению качества запускать одни и те же игровые циклы на своих устройствах.

Чтобы запустить тест на локальном устройстве с помощью Test Loop Manager:

  1. Скачать Test Loop Диспетчер на телефоне или планшете и установить его командой:
    adb install testloopmanager.apk
  2. На устройстве, откройте приложение Test Loop Apps на телефоне или планшете. Приложение отображает список приложений на вашем устройстве, которые можно запускать с игровыми циклами. Если вы не видите ваше игровое приложения здесь, убедитесь , что ваши намерения фильтра соответствует описанному в первом шаге Перед началом раздела .
  3. Выберите свое игровое приложение, затем выберите количество циклов, которые вы хотите запустить. Примечание. На этом этапе вы можете выбрать запуск подмножества циклов вместо одного цикла. Для получения дополнительной информации о выполнении нескольких циклов одновременно, см Дополнительные функции.
  4. Нажмите кнопку Проверить. Ваш тест запускается немедленно.

Запустить в тестовой лаборатории

Вы можете запустить тест Game Loop в лаборатории тестирования с помощью либо Firebase консоли или CLI gcloud. Перед тем, как начать, если вы еще не сделали, откройте консоль Firebase и создать проект.

Используйте консоль Firebase

  1. В Firebase консоли выберите Test Lab из левой панели.
  2. Нажмите кнопку Выполнить свой первый тест (или запустить тест , если ваш проект ранее запустить тест).
  3. Выберите Game Loop в качестве испытания типа, а затем нажмите кнопку Продолжить.
  4. Нажмите кнопку Обзор, а затем перейдите к вашего приложения .apk файла. Примечание. На этом этапе вы можете выбрать запуск подмножества циклов вместо одного цикла. Для получения дополнительной информации о выполнении нескольких циклов одновременно, см Дополнительные функции.
  5. Нажмите кнопку Продолжить.
  6. Выберите физические устройства для тестирования вашего приложения.
  7. Нажмите кнопку Пуск тесты.

Для получения более подробной информации о начале работы с Firebase консоли см Начало тестирования с консоли Firebase.

Используйте командную строку gcloud (CLI)

  1. Если вы еще не сделали, загрузите и установите Google Cloud SDK.

  2. Войдите в интерфейс командной строки gcloud, используя свою учетную запись Google:

    gcloud auth login

  3. Установите проект Firebase в gcloud, где PROJECT_ID является 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
    

Для получения более подробной информации о начале работы с CLI gcloud см Начало тестирования из командной строки gcloud.

Дополнительные особенности

Test Lab предлагает несколько дополнительных функций, которые позволяют дополнительно настраивать тесты, включая возможность записи выходных данных, поддержку нескольких игровых циклов и меток для связанных циклов.

Запись выходных данных

Ваш тест Game Loop можно записать вывод в файл , указанный в launchIntent.getData() метод. После выполнения теста, вы можете получить доступ к этим выходным данным в разделе Test Lab консоли Firebase (см Game Loop выходного тестового примера файла ).

Лабораторные испытания следует лучшие практики для обмена файлов между приложениями , описанными в Sharing файла . В вашей деятельности в onCreate() метод, в котором находится ваша цель, вы можете проверить свой выходной файл данных, выполнив следующий код:

Джава

Intent launchIntent = getIntent();
Uri logFile = launchIntent.getData();
if (logFile != null) {
    Log.i(TAG, "Log file " + logFile.getEncodedPath());
    // ...
}

Котлин + KTX

val launchIntent = intent
val logFile = launchIntent.data
logFile?.let {
    Log.i(TAG, "Log file ${it.encodedPath}")
    // ...
}

Если вы хотите записать в файл со стороны C ++ вашего игрового приложения, вы можете передать дескриптор файла вместо пути к файлу:

Джава

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

Котлин + 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);

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 консоли, введите список или диапазон номеров циклов в области сценариев.

  • Если вы запускаете тест с CLI gcloud, указать список номеров цикла с помощью --scenario-numbers флага. Например, --scenario-numbers=1,3,5 проходит петлю 1, 3 и 5.

  • Если вы пишете на C ++ и хотите изменить поведение цикла, передайте в собственный код C ++ следующие дополнительные данные:

    Джава

    Intent launchIntent = getIntent();
    int scenario = launchIntent.getIntExtra("scenario", 0);

    Котлин + KTX

    val launchIntent = intent
    val scenario = launchIntent.getIntExtra("scenario", 0)

    Теперь Вы можете изменить поведение вашего цикла на основе полученного int значения.

Обозначьте игровые циклы

Когда вы помечаете свои игровые циклы одной или несколькими метками сценария, вы и ваша команда QA можете легко запустить набор связанных игровых циклов (например, «все игровые циклы совместимости») и протестировать их в единой матрице. Вы можете создавать свои собственные ярлыки или использовать предопределенные ярлыки, предлагаемые Test Lab:

  • com.google.test.loops.player_experience : Для петель , используемых для воспроизведения опыта реального пользователя, когда в игру. Цель тестирования этих циклов - найти проблемы, с которыми может столкнуться реальный пользователь во время игры.
  • com.google.test.loops.gpu_compatibility : Для петель , используемых для тестирования проблем 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 поля, можно указать диапазон или набор целых чисел от 1 до 1024 (максимальное количество петель , разрешенных для одного теста) , которые представляют собой петлю , которые вы хотите пометить. Обратите внимание , что петли индексируются начиная с 1, а не 0. Например, android:value="1,3-5" относится LABEL_NAME к петлям 1, 3, 4, и 5.

    2. В приложении Test Loop Manager , введите один или несколько меток в поле Ярлыки.

  • Если вы проводите тест с Firebase консоли, введите один или несколько меток в поле Ярлыки.

  • Если вы запускаете тест с CLI gcloud, указать одну или несколько меток сценария с помощью --scenario-labels флага (например, --scenario-labels=performance,gpu ).

Поддержка лицензирования приложений

Лабораторные испытания поддерживает приложения , которые используют Licensing App услуг , предлагаемых Google Play. Чтобы успешно проверить лицензирование при тестировании приложения с помощью Test Lab, вы должны опубликовать приложение в производственном канале в магазине Play. Чтобы протестировать свое приложение в альфа- или бета-канале с помощью Test Lab, снимите флажок лицензирования перед загрузкой приложения в Test Lab.

Известные вопросы

Тесты Game Loop в Test Lab имеют следующие известные проблемы:

  • Некоторые сбои не поддерживают обратную трассировку. Например, некоторые выпуски сборок могут подавлять вывод debuggerd процесса с использованием prctl(PR_SET_DUMPABLE, 0) . Чтобы узнать больше, см debuggerd .
  • Уровень API 19 в настоящее время не поддерживается из-за ошибок прав доступа к файлам.