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

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

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

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

Вы можете запустить тест 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 Менеджер тестовой лаборатории является приложением с открытым исходным кодом , который позволяет интегрировать испытания 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);

С++

#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 в настоящее время не поддерживается из-за ошибок прав доступа к файлам.