Comience con las pruebas de Game Loop

Puede resultar difícil automatizar las pruebas de juegos cuando las aplicaciones de juegos se crean en diferentes marcos de interfaz de usuario. Las pruebas de Game Loop te permiten integrar tus pruebas nativas con Test Lab y ejecutarlas fácilmente en los dispositivos que selecciones. Una prueba de Game Loop ejecuta tu prueba a través de tu aplicación de juegos mientras simula las acciones de un jugador real. Esta guía le muestra cómo ejecutar una prueba de Game Loop y luego ver y administrar los resultados de su prueba en Firebase console.

Dependiendo del motor de tu juego, puedes implementar pruebas con bucles únicos o múltiples. Un bucle es una ejecución total o parcial de su prueba en su aplicación de juegos. Los bucles de juego se pueden utilizar para:

  • Ejecute un nivel de su juego de la misma manera que lo jugaría un usuario final. Puedes programar la entrada del usuario, dejar que el usuario esté inactivo o reemplazarlo con una IA si tiene sentido en tu juego (por ejemplo, digamos que tienes una aplicación de juegos de autos de carreras y ya tienes una IA implementada). poner fácilmente un controlador de IA a cargo de la entrada del usuario).
  • Ejecute su juego con la configuración de calidad más alta para ver si los dispositivos lo admiten.
  • Ejecute una prueba técnica (compila varios sombreadores, ejecútalos, comprueba que el resultado sea el esperado, etc.).

Puedes ejecutar una prueba de Game Loop en un solo dispositivo de prueba, en un conjunto de dispositivos de prueba o en Test Lab. Sin embargo, no recomendamos ejecutar pruebas de Game Loop en dispositivos virtuales porque tienen velocidades de cuadro de gráficos más bajas que los dispositivos físicos.

Antes de que empieces

Para implementar una prueba, primero debes configurar tu aplicación para las pruebas de Game Loop.

  1. En el manifiesto de tu aplicación, agrega un nuevo filtro de intención a tu actividad :

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

    Esto permite que Test Lab inicie su juego activándolo con una intención específica.

  2. En su código (recomendamos dentro de la declaración del método onCreate ), agregue lo siguiente:

    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
    }

    Esto permite que su actividad verifique la intención que la inicia. También puedes agregar este código más tarde si lo prefieres (por ejemplo, después de cargar inicialmente el motor del juego).

  3. Recomendado: Al final de la prueba, agregue:

    Kotlin+KTX

    yourActivity.finish()

    Java

    yourActivity.finish();

    Esto cierra tu aplicación cuando se completa la prueba de Game Loop. La prueba se basa en el marco de la interfaz de usuario de su aplicación para iniciar el siguiente ciclo, y cerrar la aplicación le indica que la prueba ha finalizado.

Crear y ejecutar una prueba de Game Loop

Después de configurar su aplicación para las pruebas de Game Loop, puede crear inmediatamente una prueba y ejecutarla en su aplicación de juegos. Puedes elegir ejecutar una prueba en Test Lab usando Firebase console o la interfaz de línea de comandos (CLI) de gcloud , o en un dispositivo local usando Test Loop Manager .

Ejecutar en un dispositivo local

Test Loop Manager de Test Lab es una aplicación de código abierto que te ayuda a integrar las pruebas de Game Loop y ejecutarlas en tus dispositivos locales. También permite que su equipo de Control de Calidad ejecute los mismos bucles de juego en sus dispositivos.

Para ejecutar una prueba en un dispositivo local utilizando Test Loop Manager:

  1. Descargue Test Loop Manager en un teléfono o tableta e instálelo ejecutando:
    adb install testloopmanager.apk
  2. En su dispositivo, abra la aplicación Test Loop Apps en su teléfono o tableta. La aplicación muestra una lista de aplicaciones en su dispositivo que se pueden ejecutar con bucles de juego. Si no ve su aplicación de juegos aquí, asegúrese de que su filtro de intención coincida con el descrito en el primer paso de la sección Antes de comenzar .
  3. Seleccione su aplicación de juegos, luego seleccione la cantidad de bucles que desea ejecutar. Nota: En este paso, puede optar por ejecutar un subconjunto de bucles en lugar de solo un bucle. Para obtener más información sobre cómo ejecutar varios bucles a la vez, consulte Funciones opcionales .
  4. Haga clic en Ejecutar prueba . Su prueba comienza a ejecutarse inmediatamente.

Ejecutar en el laboratorio de pruebas

Puedes ejecutar una prueba de Game Loop en Test Lab usando Firebase console o gcloud CLI. Antes de comenzar, si aún no lo has hecho, abre Firebase console y crea un proyecto.

Usa la consola de Firebase

  1. En Firebase console, haz clic en Test Lab en el panel izquierdo.
  2. Haga clic en Ejecutar su primera prueba (o Ejecutar una prueba si su proyecto ya ejecutó una prueba anteriormente).
  3. Seleccione Game Loop como tipo de prueba y luego haga clic en Continuar .
  4. Haga clic en Explorar y luego busque el archivo .apk de su aplicación. Nota: En este paso, puede optar por ejecutar un subconjunto de bucles en lugar de solo un bucle. Para obtener más información sobre cómo ejecutar varios bucles a la vez, consulte Funciones opcionales .
  5. Haga clic en Continuar .
  6. Seleccione los dispositivos físicos que usará para probar su aplicación.
  7. Haga clic en Iniciar pruebas .

Para obtener más información sobre cómo comenzar con Firebase console, consulta Comenzar a probar con Firebase console.

Utilice la línea de comandos de gcloud (CLI)

  1. Si aún no lo has hecho, descarga e instala el SDK de Google Cloud

  2. Inicia sesión en la CLI de gcloud con tu cuenta de Google:

    gcloud auth login

  3. Configura tu proyecto de Firebase en gcloud, donde PROJECT_ID es el ID de tu proyecto de Firebase:

    gcloud config set project PROJECT_ID
    
  4. Ejecute su primera prueba:

    gcloud firebase test android run \
     --type=game-loop --app=<var>path-to-apk</var> \
     --device model=herolte,version=23
    

Para obtener más información sobre cómo comenzar con la CLI de gcloud, consulta Comenzar a probar desde la línea de comandos de gcloud.

Características opcionales

Test Lab ofrece varias funciones opcionales que le permiten personalizar aún más sus pruebas, incluida la capacidad de escribir datos de salida, compatibilidad con múltiples bucles de juego y etiquetas para bucles relacionados.

Escribir datos de salida

Su prueba de Game Loop puede escribir la salida en un archivo especificado en el método launchIntent.getData() . Después de ejecutar una prueba, puedes acceder a estos datos de salida en la sección Laboratorio de pruebas de Firebase console (consulta el ejemplo del archivo de salida de prueba de Game Loop ).

Test Lab sigue las mejores prácticas para compartir un archivo entre aplicaciones descritas en Compartir un archivo . En el método onCreate() de su actividad, donde se encuentra su intención, puede verificar su archivo de salida de datos ejecutando el siguiente código:

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());
    // ...
}

Si deseas escribir en el archivo desde el lado C++ de tu aplicación de juego, puedes pasar el descriptor del archivo en lugar de la ruta del archivo:

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

Ejemplo de archivo de salida

Puedes usar archivos de datos de salida (formateados como en el ejemplo siguiente) para mostrar los resultados de las pruebas de bucle del juego en la sección Laboratorio de pruebas de Firebase console. Las áreas que se muestran como /.../ pueden contener cualquier campo personalizado que necesite, siempre que no entren en conflicto con los nombres de otros campos utilizados en este archivo:

{
  "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
}

Múltiples bucles de juego

Puede que te resulte útil ejecutar varios bucles de juego en tu aplicación. Un bucle es un recorrido completo de la aplicación de tu juego de principio a fin. Por ejemplo, si tienes varios niveles en tu juego, es posible que desees tener un bucle de juego para iniciar cada nivel en lugar de tener un bucle que los recorra todos. De esa manera, si tu aplicación falla en el nivel 32, puedes iniciar directamente ese bucle del juego para reproducir el fallo y probar las correcciones de errores.

Para permitir que su aplicación ejecute múltiples bucles a la vez:

  • Si está ejecutando una prueba con Test Loop Manager:

    1. Agregue la siguiente línea al manifiesto de su aplicación, dentro del elemento <application> :

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

      Esta intención de lanzamiento contiene el bucle de destino como un parámetro entero. En el campo android:value , puede especificar un número entero de 1 a 1024 (el número máximo de bucles permitidos para una sola prueba). Tenga en cuenta que los bucles se indexan a partir de 1, no de 0.

    2. En la aplicación Test Loop Manager, aparece una pantalla de selección que le permite seleccionar qué bucle desea ejecutar. Si selecciona varios bucles, cada bucle se inicia en secuencia una vez que se completa el bucle anterior.

  • Si estás ejecutando una prueba con Firebase console, ingresa una lista o un rango de números de bucle en el campo Escenarios .

  • Si estás ejecutando una prueba con la CLI de gcloud, especifica una lista de números de bucle mediante la marca --scenario-numbers . Por ejemplo, --scenario-numbers=1,3,5 ejecuta los bucles 1, 3 y 5.

  • Si estás escribiendo C++ y quieres cambiar el comportamiento de tu bucle, pasa el siguiente extra a tu código C++ nativo:

    Kotlin+KTX

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

    Java

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

    Ahora puede cambiar el comportamiento de su bucle según el valor int resultante.

Bucles de juego de etiquetas

Cuando etiqueta sus bucles de juego con una o más etiquetas de escenario, usted y su equipo de control de calidad pueden iniciar fácilmente un conjunto de bucles de juego relacionados (por ejemplo, "bucles de juego con todas las compatibilidades") y probarlos en una única matriz. Puede crear sus propias etiquetas o utilizar las etiquetas predefinidas que ofrece Test Lab:

  • com.google.test.loops.player_experience : bucles For utilizados para reproducir la experiencia de un usuario real al jugar. El objetivo de las pruebas con estos bucles es encontrar problemas que un usuario real enfrentaría mientras juega.
  • com.google.test.loops.gpu_compatibility : bucles For utilizados para probar problemas relacionados con la GPU. El objetivo de las pruebas con estos bucles es ejecutar código de GPU que podría no ejecutarse correctamente en producción, para exponer problemas con el hardware y los controladores.
  • com.google.test.loops.compatibility : bucles For utilizados para probar una amplia gama de problemas de compatibilidad, incluidos problemas de E/S y problemas de OpenSSL.
  • com.google.test.loops.performance : bucles For utilizados para probar el rendimiento del dispositivo. Por ejemplo, un juego podría ejecutarse con la configuración de gráficos más compleja para ver cómo se comporta un nuevo dispositivo.

Para permitir que su aplicación ejecute bucles con la misma etiqueta:

  • Si está ejecutando una prueba con Test Loop Manager:

    1. En el manifiesto de tu aplicación, agrega la siguiente línea de metadatos y reemplaza LABEL_NAME con una etiqueta de tu elección:

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

      En el campo android:value , puede especificar un rango o un conjunto de números enteros del 1 al 1024 (el número máximo de bucles permitidos para una sola prueba) que represente los bucles que desea etiquetar. Tenga en cuenta que los bucles se indexan a partir de 1, no de 0. Por ejemplo, android:value="1,3-5" aplica LABEL_NAME a los bucles 1, 3, 4 y 5.

    2. En la aplicación Test Loop Manager, ingrese una o más etiquetas en el campo Etiquetas .

  • Si estás ejecutando una prueba con Firebase console, ingresa una o más etiquetas en el campo Etiquetas .

  • Si estás ejecutando una prueba con la CLI de gcloud, especifica una o más etiquetas de escenario usando la marca --scenario-labels (p. ej., --scenario-labels=performance,gpu ).

Soporte de licencias de aplicaciones

Test Lab admite aplicaciones que utilizan el servicio App Licensing ofrecido por Google Play. Para verificar correctamente la licencia al probar su aplicación con Test Lab, debe publicar su aplicación en el canal de producción en Play Store. Para probar su aplicación en el canal alfa o beta usando Test Lab, elimine la verificación de licencia antes de cargar su aplicación en Test Lab.

Problemas conocidos

Las pruebas de Game Loop en Test Lab tienen los siguientes problemas conocidos:

  • Algunas fallas no admiten rastreos hacia atrás. Por ejemplo, algunas versiones de lanzamiento pueden suprimir la salida del proceso debuggerd usando prctl(PR_SET_DUMPABLE, 0) . Para obtener más información, consulte debuggerd .
  • Actualmente, el nivel de API 19 no es compatible debido a errores de permisos de archivos.