Il peut être difficile d'automatiser les tests de jeux lorsque les applications de jeu sont créées sur différents frameworks d'interface utilisateur. Les tests de boucle 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 via votre application de jeu tout en simulant les actions d'un vrai joueur. 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 console Firebase.
Qu'est-ce qu'un test de boucle de jeu ?
Étant donné que les applications de jeu s'affichent sur différents frameworks et moteurs d'interface utilisateur, tels que Unity, Unreal ou le code C++ OpenGL/Vulkan, les outils d'automatisation standards ne peuvent pas inspecter les éléments d'interface utilisateur ni interagir avec eux. Un test de boucle de jeu vous permet d'intégrer vos tests de moteur natif à Test Lab en lançant votre jeu avec un intent contenant un numéro de scénario spécifique. Ce numéro de scénario invite votre application à exécuter une logique pré-scénarisée, des simulations d'IA ou des vérifications de performances directement dans votre moteur de jeu.
Une fois lancé, Test Lab n'interagit plus avec l'UI de votre jeu. À la place, Test Lab agit comme un transport et un environnement de test : il lance le scénario spécifique, surveille les plantages et les délais d'expiration, et collecte les journaux de résultats personnalisés lorsque votre application a terminé d'exécuter la boucle.
Différences entre les boucles de jeu et les tests d'instrumentation
- Les tests d'instrumentation (comme Espresso ou UI Automator) s'appuient sur des frameworks externes pour piloter les interactions avec l'UI, cliquer sur des boutons et vérifier l'état de l'application dans la hiérarchie des vues Android depuis l'extérieur de votre application.
- Les tests de boucle de jeu délèguent la logique de test à votre application. Votre application exécute sa propre boucle de test interne ou simulation sans interaction externe avec l'UI, tandis que Test Lab déclenche votre scénario et collecte le résultat du test.
Exemples
Supposons que vous souhaitiez vérifier que votre jeu maintient au moins 60 images par seconde sur différents appareils physiques. Vous pouvez implémenter le scénario 1 dans le code de votre jeu pour charger le niveau le plus complexe visuellement et laisser un joueur IA ou un script automatisé y jouer pendant deux minutes.
Lorsque Test Lab déclenche le scénario 1, votre jeu lance la partie IA, surveille les délais d'affichage des images et l'utilisation de la mémoire, diffuse ces métriques dans un fichier journal de sortie personnalisé (logFile) et appelle finish() une fois l'opération terminée.
Test Lab capture ensuite le fichier journal et le met à votre disposition dans Cloud Storage et dans la console Firebase.
Cas d'utilisation
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écutez un niveau de votre jeu comme le ferait un utilisateur final. Vous pouvez soit scripter l'entrée de l'utilisateur, soit laisser l'utilisateur inactif, soit remplacer l'utilisateur par une IA si cela est pertinent 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 confier l'entrée de l'utilisateur à un pilote IA).
- Exécutez votre jeu avec le paramètre de qualité le plus élevé pour voir si les appareils le prennent en charge.
- Exécutez un test technique (compilez plusieurs nuanceurs, exécutez-les, vérifiez que le résultat est conforme aux attentes, etc.).
Vous pouvez exécuter un test de boucle de jeu sur un seul appareil de test, un ensemble d'appareils de test ou sur Test Lab. Cependant, nous vous déconseillons d'exécuter des tests de boucle de jeu sur des appareils virtuels, car leur fréquence d'images est inférieure à celle 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.
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.
Dans votre code (nous vous recommandons de le faire dans la déclaration de la méthode
onCreate), ajoutez ce qui suit :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 souhaitez (par exemple, après le chargement initial de votre moteur de jeu).
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'UI de votre application pour démarrer la boucle suivante. La fermeture de votre application indique que le test est terminé.
Créer et exécuter un test de boucle de jeu
Après avoir 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 console Firebase ou de l'interface de ligne de commande (CLI) gcloud, ou sur un appareil local à l'aide de Test Loop Manager.
Exécuter sur un appareil local
Le Test Loop Manager de Test Lab est une application Open Source qui vous aide à intégrer des tests de boucle de jeu et à les exécuter sur vos appareils locaux. Cela 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 de Test Loop Manager :
- Téléchargez Test Loop Manager sur un téléphone ou une tablette, puis installez-le en exécutant la commande suivante :
adb install testloopmanager.apk
- 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 à la première étape de la section Avant de commencer.
- 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 boucle. Pour en savoir plus sur l'exécution de plusieurs boucles à la fois, consultez Fonctionnalités facultatives.
- Cliquez sur Run test (Exécuter le test). Votre test commence immédiatement.
Exécuter dans Test Lab
Vous pouvez exécuter un test de boucle de jeu dans Test Lab à l'aide de la console Firebase ou de la gcloud CLI. Avant de commencer, si ce n'est pas déjà fait, ouvrez la console Firebase et créez un projet.
Utiliser la console Firebase
- Dans la console Firebase, cliquez sur Test Lab dans le panneau de gauche.
- Cliquez sur Exécuter votre premier test (ou sur Exécuter un test si votre projet a déjà exécuté un test).
- Sélectionnez Boucle de jeu comme type de test, puis cliquez sur Continuer.
- Cliquez sur Parcourir, puis accédez au fichier
.apkde votre application. Remarque : À cette étape, vous pouvez choisir d'exécuter un sous-ensemble de boucles au lieu d'une seule boucle. Pour en savoir plus sur l'exécution de plusieurs boucles à la fois, consultez Fonctionnalités facultatives. - Cliquez sur Continuer.
- Sélectionnez les appareils physiques à utiliser pour tester votre application.
- Cliquez sur Lancer les tests.
Pour en savoir plus sur la prise en main de la console Firebase, consultez Commencer à tester avec la console Firebase.
Utiliser la gcloud CLI
Si vous ne l'avez pas déjà fait, téléchargez et installez le SDK Google Cloud.
Connectez-vous à la gcloud CLI à l'aide de votre compte Google :
gcloud auth loginDéfinissez votre projet Firebase dans gcloud, où
PROJECT_IDest l'ID de votre projet Firebase :gcloud config set project PROJECT_ID
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 Commencer à tester à 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 les données de sortie
Lorsque Test Lab lance votre jeu, il spécifie une URL pointant vers un fichier de résultats local sur l'appareil de test, accessible à l'aide de launchIntent.getData(). Votre jeu peut écrire les résultats des tests, les métriques de performances et les journaux (logFile) directement à cet emplacement pendant l'exécution du test.
Vous pouvez écrire n'importe quel contenu dans le logFile, comme du texte brut, des données CSV, des délais d'affichage des images ou des rapports de diagnostic personnalisés. Il n'y a aucune restriction ni exigence de mise en forme pour le contenu que vous écrivez. Il capture le fichier à la fin de votre test et l'importe dans votre bucket Cloud Storage avec vos autres artefacts de test.
Test Lab suit les bonnes pratiques établies pour partager 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 récupérer et 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 depuis le 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
Bien que Test Lab ne nécessite pas de format spécifique pour votre logFile, la structuration de votre sortie au format JSON correspondant au schéma ci-dessous permet à la console Firebase (https://console.firebase.google.com/project/_/testlab) d'analyser et d'afficher des métriques récapitulatives pour votre test de boucle de jeu.
Détails importants concernant cet exemple :
- Qui fournit les données : vous (le développeur du test) êtes responsable du calcul et de l'écriture de toutes les métriques dans ce fichier à partir du code de votre jeu. Test Lab ne collecte ni ne génère automatiquement ces points de données pour vous.
- Ajout de champs personnalisés : les zones marquées par
/.../indiquent où vous pouvez ajouter des paires clé-valeur personnalisées arbitraires (par exemple,"rendered_vertices": 12000ou"ai_error_count": 0). Vous pouvez ajouter n'importe quelle propriété JSON valide à votre sortie lors de l'écriture du fichier à partir de votre application, à condition que les noms de champs n'entrent pas en conflit avec les champs de schéma tels quenameoustart_timestamp. - Où trouver le fichier de sortie : une fois le test terminé, votre fichier de sortie brut est stocké et téléchargeable dans le bucket de résultats Cloud Storage (
GCS) de votre projet, dans le répertoire d'artefacts de l'exécution du test. Vous pouvez également afficher et inspecter le résultat analysé sur la page Test Lab de la console Firebase.
Voici un exemple de fichier de sortie JSON structuré :
{
"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 utiliser une boucle de jeu pour lancer chaque niveau au lieu d'avoir une 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 Test Loop Manager :
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 (le nombre maximal de boucles autorisées pour un seul test). Notez que les boucles sont indexées à partir de 1, et non de 0.Dans l'application Test Loop Manager, un écran de sélection s'affiche pour vous permettre de sélectionner la ou les boucles que vous souhaitez exécuter. Si vous sélectionnez plusieurs boucles, chacune est lancée l'une après l'autre, une fois la boucle précédente terminée.
Si vous exécutez un test avec la console Firebase, saisissez une liste ou une plage de numéros de boucle dans le champ Scénarios.
Si vous exécutez un test avec la gcloud CLI, spécifiez une liste de numéros de boucle à l'aide de l'option
--scenario-numbers. Par exemple,--scenario-numbers=1,3,5exé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'extra 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
intobtenue.
Ajouter des libellés aux boucles de jeu
Lorsque vous ajoutez un ou plusieurs libellés de scénario à vos boucles de jeu, 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: boucles For utilisées pour reproduire l'expérience d'un utilisateur réel lorsqu'il joue au jeu. L'objectif de ces tests est d'identifier les problèmes qu'un utilisateur réel pourrait rencontrer en jouant au jeu.com.google.test.loops.gpu_compatibility: boucles For 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 d'exposer les problèmes liés au matériel et aux pilotes.com.google.test.loops.compatibility: boucles For utilisées pour tester un large éventail de problèmes de compatibilité, y compris les problèmes d'E/S et d'OpenSSL.com.google.test.loops.performance: boucles For 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 un nouvel appareil se comporte.
Pour permettre à votre application d'exécuter des boucles avec le même libellé :
Si vous exécutez un test avec Test Loop Manager :
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 (le nombre maximal de boucles autorisées pour un seul test) qui représentent les boucles que vous souhaitez étiqueter. 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.Dans l'application Test Loop Manager, saisissez un ou plusieurs libellés dans le champ Labels (Libellés).
Si vous exécutez un test avec la console Firebase, saisissez une ou plusieurs étiquettes dans le champ Étiquettes.
Si vous exécutez un test avec la gcloud CLI, spécifiez une ou plusieurs étiquettes de scénario à l'aide de l'option
--scenario-labels(par exemple,--scenario-labels=performance,gpu).
Assistance pour l'attribution de licences d'application
Test Lab est compatible avec les applications qui utilisent le service d'attribution de licences d'application proposé par Google Play. Pour vérifier correctement les licences lorsque vous testez votre application avec Test Lab, vous devez la publier sur le canal de production du Play Store. Pour tester votre application dans la version alpha ou bêta à l'aide de Test Lab, supprimez la vérification 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 de release peuvent supprimer la sortie du processus
debuggerdà l'aide deprctl(PR_SET_DUMPABLE, 0). Pour en savoir plus, consultezdebuggerd. - Le niveau d'API 19 n'est actuellement pas pris en charge en raison d'erreurs d'autorisation de fichiers.