Premiers pas avec les tests de boucles de jeu

Il peut être difficile d'automatiser les tests de jeux lorsque les applications de jeu sont conçues sur différents frameworks d'interface utilisateur. Les tests de boucles de jeu vous permettent d'intégrer vos tests natifs à Test Lab et de les exécuter facilement sur les appareils de votre choix. Un test de boucle de jeu exécute votre test dans votre application de jeu tout en simulant les actions d'un joueur réel. Ce guide vous explique comment exécuter un test de boucle de jeu, puis afficher et gérer les résultats de vos tests dans la Firebase console.

Selon votre moteur de jeu, vous pouvez implémenter des tests avec une ou plusieurs boucles. Une boucle est une exécution complète ou partielle de votre test sur votre application de jeu. Les boucles de jeu peuvent être utilisées pour :

  • exécuter un niveau de votre jeu de la même manière qu'un utilisateur final ; vous pouvez scripter l'entrée de l'utilisateur, le laisser inactif ou le remplacer par une IA si cela a du sens dans votre jeu (par exemple, si vous avez une application de jeu de course automobile et que vous avez déjà implémenté une IA) ; vous pouvez facilement confier la saisie de l'utilisateur à un pilote d'IA.
  • exécuter votre jeu avec le paramètre de qualité le plus élevé pour voir si les appareils le prennent en charge ;
  • exécuter un test technique (compiler plusieurs nuanceurs, les exécuter, vérifier que la sortie est conforme aux attentes, etc.).

Vous pouvez exécuter un test de boucle de jeu sur un seul appareil de test, sur un ensemble d'appareils de test ou sur Test Lab. Toutefois, nous vous déconseillons d'exécuter des tests de boucle de jeu sur des appareils virtuels, car ils ont des fréquences d'images graphiques inférieures à celles des appareils physiques.

Avant de commencer

Pour implémenter un test, vous devez d'abord configurer votre application pour les tests de boucle de jeu.

  1. Dans le fichier manifeste de votre application, ajoutez un filtre d'intent à votre activité :

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

    Cela permet à Test Lab de lancer votre jeu en le déclenchant avec un intent spécifique.

  2. Dans votre code (nous vous recommandons de le placer dans la déclaration de la méthode onCreate), ajoutez les éléments suivants :

    Kotlin

    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
    }

    Cela permet à votre activité de vérifier l'intent qui la lance. Vous pouvez également ajouter ce code ultérieurement si vous le préférez (par exemple, après le chargement initial de votre moteur de jeu).

  3. Recommandé : à la fin du test, ajoutez :

    Kotlin

    yourActivity.finish()

    Java

    yourActivity.finish();

    Cela ferme votre application une fois le test de boucle de jeu terminé. Le test s'appuie sur le framework d'interface utilisateur de votre application pour démarrer la boucle suivante. La fermeture de votre application lui indique que le test est terminé.

Créer et exécuter un test de boucle de jeu

Une fois que vous avez configuré votre application pour les tests de boucle de jeu, vous pouvez immédiatement créer un test et l'exécuter dans votre application de jeu. Vous pouvez choisir d'exécuter un test dans Test Lab à l'aide de la Firebase console ou de l'interface de ligne de commande (CLI) gcloud, ou sur un appareil local à l'aide du gestionnaire de boucles de test.

Exécuter sur un appareil local

Test LabLe gestionnaire de boucles de test de's est une application Open Source qui vous aide à intégrer des tests de boucle de jeu et à les exécuter sur vos appareils locaux. Il permet également à votre équipe d'assurance qualité d'exécuter les mêmes boucles de jeu sur ses appareils.

Pour exécuter un test sur un appareil local à l'aide du gestionnaire de boucles de test :

  1. Téléchargez le gestionnaire de boucles de test sur un téléphone ou une tablette, puis installez-le en exécutant :
    adb install testloopmanager.apk
  2. Sur votre appareil, ouvrez l'application Test Loop Apps sur votre téléphone ou votre tablette. L'application affiche la liste des applications de votre appareil qui peuvent être exécutées avec des boucles de jeu. Si votre application de jeu ne s'affiche pas ici, assurez-vous que votre filtre d'intent correspond à celui décrit dans la première étape de la section Avant de commencer.
  3. Sélectionnez votre application de jeu, puis le nombre de boucles que vous souhaitez exécuter. Remarque : À cette étape, vous pouvez choisir d'exécuter un sous-ensemble de boucles au lieu d'une seule. Pour en savoir plus sur l' exécution de plusieurs boucles à la fois, consultez la section Fonctionnalités facultatives.
  4. Cliquez sur Run test (Exécuter le test). Votre test commence à s'exécuter immédiatement.

Exécuter dans Test Lab

Vous pouvez exécuter un test de boucle de jeu dans Test Lab à l'aide de la Firebase console ou de la gcloud CLI. Avant de commencer, si ce n'est pas déjà fait, ouvrez la Firebase console et créez un projet.

Utiliser la Firebase console

  1. Dans la Firebase console, cliquez sur Test Lab dans le panneau de gauche.
  2. Cliquez sur Run Your First Test (Exécuter votre premier test) ou sur Run a Test (Exécuter un test) si votre projet a déjà exécuté un test.
  3. Sélectionnez Game Loop (Boucle de jeu) comme type de test, puis cliquez sur Continue (Continuer).
  4. Cliquez sur Browse (Parcourir), puis accédez au fichier .apk de votre application. Remarque : À cette étape, vous pouvez choisir d'exécuter un sous-ensemble de boucles au lieu d'une seule. Pour en savoir plus sur l' exécution de plusieurs boucles à la fois, consultez la section Fonctionnalités facultatives.
  5. Cliquez sur Continue (Continuer).
  6. Sélectionnez les appareils physiques à utiliser pour tester votre application.
  7. Cliquez sur Start Tests (Démarrer les tests).

Pour en savoir plus sur la prise en main de la Firebase console, consultez Démarrer les tests avec la Firebase console.

Utiliser la ligne de commande (CLI) gcloud

  1. Si ce n'est pas déjà fait, téléchargez et installez le SDK Google Cloud.

  2. Connectez-vous à la gcloud CLI à l'aide de votre compte Google :

    gcloud auth login

  3. Définissez votre projet Firebase dans gcloud, où PROJECT_ID correspond à l'ID de votre projet Firebase :

    gcloud config set project PROJECT_ID
    
  4. Exécutez votre premier test :

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

Pour en savoir plus sur la prise en main de la gcloud CLI, consultez Démarrer les tests à partir de la ligne de commande gcloud.

Fonctionnalités facultatives

Test Lab propose plusieurs fonctionnalités facultatives qui vous permettent de personnaliser davantage vos tests, y compris la possibilité d'écrire des données de sortie, la prise en charge de plusieurs boucles de jeu et des libellés pour les boucles associées.

Écrire des données de sortie

Votre test de boucle de jeu peut écrire la sortie dans un fichier spécifié dans la méthode launchIntent.getData(). Une fois le test exécuté, vous pouvez accéder à ces données de sortie dans la section Test Lab de la console Firebase (voir l'exemple de fichier de sortie de test de boucle de jeu).

Test Lab suit les bonnes pratiques pour le partage d'un fichier entre des applications décrites dans Partager un fichier. Dans la méthode onCreate() de votre activité, où se trouve votre intent, vous pouvez vérifier votre fichier de sortie de données en exécutant le code suivant :

Kotlin

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 vous souhaitez écrire dans le fichier à partir du côté C++ de votre application de jeu, vous pouvez transmettre le descripteur de fichier au lieu du chemin d'accès au fichier :

Kotlin

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

Exemple de fichier de sortie

Vous pouvez utiliser des fichiers de données de sortie (mis en forme comme dans l'exemple ci-dessous) pour afficher les résultats des tests de boucle de jeu dans la section Test Lab de la console Firebase. Les zones affichées sous la forme /.../ peuvent contenir tous les champs personnalisés dont vous avez besoin, à condition qu'ils n'entrent pas en conflit avec les noms des autres champs utilisés dans ce fichier :

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

Plusieurs boucles de jeu

Il peut être utile d'exécuter plusieurs boucles de jeu dans votre application. Une boucle est une exécution complète de votre application de jeu du début à la fin. Par exemple, si votre jeu comporte plusieurs niveaux, vous pouvez avoir une boucle de jeu pour lancer chaque niveau au lieu d'une seule boucle qui les parcourt tous. Ainsi, si votre application plante au niveau 32, vous pouvez lancer directement cette boucle de jeu pour reproduire le plantage et tester les corrections de bugs.

Pour permettre à votre application d'exécuter plusieurs boucles à la fois :

  • Si vous exécutez un test avec le gestionnaire de boucles de test :

    1. Ajoutez la ligne suivante au fichier manifeste de votre application, dans l'élément <application> :

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

      Cet intent de lancement contient la boucle cible en tant que paramètre entier. Dans le champ android:value, vous pouvez spécifier un entier compris entre 1 et 1 024 (nombre maximal de boucles autorisées pour un seul test). Notez que les boucles sont indexées à partir de 1, et non de 0.

    2. Dans l'application Gestionnaire de boucles de test, un écran de sélection s'affiche et vous permet de sélectionner la ou les boucles que vous souhaitez exécuter. Si vous sélectionnez plusieurs boucles, chaque boucle est lancée séquentiellement une fois la boucle précédente terminée.

  • Si vous exécutez un test avec la Firebase console, saisissez une liste ou une plage de numéros de boucle dans le champ Scenarios.

  • Si vous exécutez un test avec la gcloud CLI, spécifiez une liste de numéros de boucle à l'aide du flag --scenario-numbers. Par exemple, --scenario-numbers=1,3,5 exécute les boucles 1, 3 et 5.

  • Si vous écrivez du code C++ et que vous souhaitez modifier le comportement de votre boucle, transmettez l'élément supplémentaire suivant à votre code C++ natif :

    Kotlin

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

    Java

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

    Vous pouvez maintenant modifier le comportement de votre boucle en fonction de la valeur int résultante.

Libeller les boucles de jeu

Lorsque vous libellez vos boucles de jeu avec un ou plusieurs libellés de scénario, vous et votre équipe d'assurance qualité pouvez facilement lancer un ensemble de boucles de jeu associées (par exemple, "toutes les boucles de jeu de compatibilité") et les tester dans une seule matrice. Vous pouvez créer vos propres libellés ou utiliser les libellés prédéfinis proposés par Test Lab :

  • com.google.test.loops.player_experience: pour les boucles utilisées pour reproduire l'expérience d'un utilisateur réel lorsqu'il joue au jeu. L'objectif des tests avec ces boucles est de trouver les problèmes qu'un utilisateur réel rencontrerait en jouant au jeu.
  • com.google.test.loops.gpu_compatibility: pour les boucles utilisées pour tester les problèmes liés au GPU. L'objectif des tests avec ces boucles est d'exécuter du code GPU qui pourrait ne pas s'exécuter correctement en production, afin de détecter les problèmes liés au matériel et aux pilotes.
  • com.google.test.loops.compatibility: pour les boucles utilisées pour tester un large éventail de problèmes de compatibilité, y compris les problèmes d'E/S et les problèmes OpenSSL.
  • com.google.test.loops.performance: pour les boucles utilisées pour tester les performances de l'appareil. Par exemple, un jeu peut s'exécuter avec les paramètres graphiques les plus complexes pour voir comment se comporte un nouvel appareil.

Pour permettre à votre application d'exécuter des boucles avec le même libellé :

  • Si vous exécutez un test avec le gestionnaire de boucles de test :

    1. Dans le fichier manifeste de votre application, ajoutez la ligne de métadonnées suivante et remplacez LABEL_NAME par le libellé de votre choix :

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

      Dans le champ android:value, vous pouvez spécifier une plage ou un ensemble d'entiers compris entre 1 et 1 024 (nombre maximal de boucles autorisées pour un seul test) qui représentent les boucles que vous souhaitez libeller. Notez que les boucles sont indexées à partir de 1, et non de 0. Par exemple, android:value="1,3-5" applique LABEL_NAME aux boucles 1, 3, 4 et 5.

    2. Dans l'application Gestionnaire de boucles de test, saisissez un ou plusieurs libellés dans le champ Labels (Libellés).

  • Si vous exécutez un test avec la console Firebase, saisissez un ou plusieurs libellés dans le champ Labels.

  • Si vous exécutez un test avec la gcloud CLI, spécifiez un ou plusieurs libellés de scénario à l'aide du --scenario-labels (par exemple, --scenario-labels=performance,gpu).

Prise en charge de l'attribution de licences d'application

Test Lab est compatible avec les applications qui utilisent le service de gestion des licences d'application proposé par Google Play. Pour vérifier correctement la gestion des licences lorsque vous testez votre application avec Test Lab, vous devez publier votre application sur le canal de production dans le Play Store. Pour tester votre application dans le canal alpha ou bêta à l'aide de Test Lab, supprimez la vérification de la gestion des licences avant d'importer votre application dans Test Lab.

Problèmes connus

Les tests de boucle de jeu dans Test Lab présentent les problèmes connus suivants :

  • Certains plantages ne sont pas compatibles avec les backtraces. Par exemple, certaines versions peuvent supprimer la sortie du processus debuggerd à l'aide de prctl(PR_SET_DUMPABLE, 0). Pour en savoir plus, consultez debuggerd.
  • Le niveau d'API 19 n'est actuellement pas pris en charge en raison d'erreurs d'autorisation de fichier.