Il s'agit d'une brève introduction au mappage des tests et d'une explication sur la façon de commencer à configurer les tests dans le projet Android Open Source (AOSP).
À propos du mappage des tests
Le test mapping est une approche basée sur Gerrit qui permet aux développeurs de créer des règles de test avant et après l'envoi directement dans l'arborescence source Android, et de laisser l'infrastructure de test décider des branches et des appareils à tester.
Les définitions de mappage de test sont des fichiers JSON nommés TEST_MAPPING
que vous pouvez placer dans n'importe quel répertoire source.
Atest peut utiliser les fichiers TEST_MAPPING
pour exécuter des tests avant envoi dans les répertoires associés. Le mappage de tests vous permet d'ajouter le même ensemble de tests aux vérifications avant envoi en apportant un minimum de modifications dans l'arborescence source Android.
Voici quelques exemples :
Ajouter des tests avant l'envoi à
TEST_MAPPING
pourservices.core
Ajouter des tests de pré-soumission à
TEST_MAPPING
pourtools/dexter
à l'aide d'importations
Le mappage des tests repose sur le framework de test Trade Federation (TF) pour l'exécution des tests et la création de rapports sur les résultats.
Définir des groupes de test
Testez les groupes de mappage avec un groupe de test. Le nom d'un groupe de test peut être n'importe quelle chaîne. Par exemple, presubmit peut être le nom d'un groupe de tests à exécuter lors de la validation des modifications. Les tests postsubmit peuvent être utilisés pour valider les builds une fois les modifications fusionnées.
Règles relatives aux scripts de compilation de packages
Pour que le banc d'essai Trade Federation exécute des modules de test pour une version donnée, ces modules doivent avoir un test_suites
défini pour Soong ou un LOCAL_COMPATIBILITY_SUITE
défini pour Make sur l'une des deux suites suivantes :
general-tests
est destiné aux tests qui ne dépendent pas de fonctionnalités spécifiques à l'appareil (comme le matériel spécifique au fournisseur dont la plupart des appareils ne sont pas équipés). La plupart des tests doivent se trouver dans la suitegeneral-tests
, même s'ils sont spécifiques à une ABI, à une architecture ou à des fonctionnalités matérielles comme HWASan (il existe une cibletest_suites
distincte pour chaque ABI), et même s'ils doivent s'exécuter sur un appareil.device-tests
est destiné aux tests qui dépendent des fonctionnalités spécifiques à l'appareil. Ces tests se trouvent généralement sousvendor/
. Spécifique à l'appareil ne fait référence qu'aux fonctionnalités propres à un appareil. Cela s'applique donc aux tests JUnit ainsi qu'aux tests GTest (qui doivent généralement être marqués commegeneral-tests
même s'ils sont spécifiques à l'ABI).
Exemples :
Android.bp: test_suites: ["general-tests"],
Android.mk: LOCAL_COMPATIBILITY_SUITE := general-tests
Configurer des tests à exécuter dans une suite de tests
Pour qu'un test s'exécute dans une suite de tests, il doit :
- Ne doit pas avoir de fournisseur de compilation.
- Doit effectuer un nettoyage une fois terminé, par exemple en supprimant les fichiers temporaires générés pendant le test.
- Vous devez rétablir les paramètres système sur leur valeur par défaut ou d'origine.
Ne partez pas du principe qu'un appareil est dans un certain état (par exemple, prêt pour le root). La plupart des tests ne nécessitent pas de droits racine pour s'exécuter. Si un test doit nécessiter un accès root, il doit le spécifier avec
RootTargetPreparer
dans sonAndroidTest.xml
, comme dans l'exemple suivant :<target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer"/>
Créer des fichiers de mappage de test
Pour le répertoire nécessitant une couverture de test, ajoutez un fichier JSON TEST_MAPPING
semblable à l'exemple. Ces règles garantissent que les tests s'exécutent dans les vérifications de pré-envoi lorsque des fichiers sont modifiés dans ce répertoire ou dans l'un de ses sous-répertoires.
Suivre un exemple
Voici un exemple de fichier TEST_MAPPING
(au format JSON, mais avec des commentaires acceptés) :
{
"presubmit": [
// JUnit test with options and file patterns.
{
"name": "CtsWindowManagerDeviceTestCases",
"options": [
{
"include-annotation": "android.platform.test.annotations.RequiresDevice"
}
],
"file_patterns": ["(/|^)Window[^/]*\\.java", "(/|^)Activity[^/]*\\.java"]
},
// Device-side GTest with options.
{
"name" : "hello_world_test",
"options": [
{
"native-test-flag": "\"servicename1 servicename2\""
},
{
"native-test-timeout": "6000"
}
]
}
// Host-side GTest.
{
"name" : "net_test_avrcp",
"host" : true
}
],
"postsubmit": [
{
"name": "CtsDeqpTestCases",
"options": [
{
// Use regex in include-filter which is supported in AndroidJUnitTest
"include-filter": "dEQP-EGL.functional.color_clears.*"
}
]
}
],
"imports": [
{
"path": "frameworks/base/services/core/java/com/android/server/am"
}
]
}
Définir des attributs
Dans l'exemple, presubmit
et postsubmit
sont les noms de chaque groupe de test. Pour en savoir plus sur les groupes de test, consultez Définir des groupes de test.
Vous pouvez définir le nom du module de test ou le nom du test d'intégration Trade Federation (chemin d'accès à la ressource du fichier XML de test, par exemple uiautomator/uiautomator-demo
) dans la valeur de l'attribut name
. Notez que le champ name
ne peut pas utiliser la classe name
ni la méthode de test name
. Pour limiter les tests à exécuter, utilisez des options telles que include-filter
. Consultez un exemple d'utilisation de include-filter
.
Le paramètre host
d'un test indique si le test est un test sans appareil exécuté sur l'hôte ou non. La valeur par défaut est false
, ce qui signifie que le test nécessite un appareil pour s'exécuter. Les types de tests compatibles sont HostGTest
pour les binaires GTest et HostTest
pour les tests JUnit.
L'attribut file_patterns
vous permet de définir une liste de chaînes d'expression régulière pour faire correspondre le chemin d'accès relatif de n'importe quel fichier de code source (par rapport au répertoire contenant le fichier TEST_MAPPING
). Dans l'exemple, le test CtsWindowManagerDeviceTestCases
s'exécute en pré-soumission uniquement lorsqu'un fichier Java commence par Window
ou Activity
, qui existe dans le même répertoire que le fichier TEST_MAPPING
ou l'un de ses sous-répertoires. Les barres obliques inverses (\) doivent être échappées, car elles se trouvent dans un fichier JSON.
L'attribut imports
vous permet d'inclure des tests dans d'autres fichiers TEST_MAPPING
sans copier le contenu. Les fichiers TEST_MAPPING
des répertoires parents du chemin importé sont également inclus. Le mappage de test autorise les importations imbriquées. Cela signifie que deux fichiers TEST_MAPPING
peuvent s'importer mutuellement, et que le mappage de test peut fusionner les tests inclus.
L'attribut options
contient des options de ligne de commande Tradefed supplémentaires.
Pour obtenir la liste complète des options disponibles pour un test donné, exécutez la commande suivante :
tradefed.sh run commandAndExit [test_module] --help
Pour en savoir plus sur le fonctionnement des options, consultez Gestion des options dans Tradefed.
Exécuter des tests avec Atest
Pour exécuter les règles de test de pré-commit localement :
- Accédez au répertoire contenant le fichier
TEST_MAPPING
. Exécutez la commande suivante :
atest
Tous les tests de pré-soumission configurés dans les fichiers TEST_MAPPING
du répertoire actuel et de ses répertoires parents sont exécutés. Atest localise et exécute deux tests pour la pré-soumission (A et B).
Il s'agit du moyen le plus simple d'exécuter des tests de pré-commit dans les fichiers TEST_MAPPING
du répertoire de travail actuel (CWD) et des répertoires parents. Atest localise et utilise le fichier TEST_MAPPING
dans le répertoire de travail actuel et dans tous ses répertoires parents.
Structurer le code source
Cet exemple montre comment configurer les fichiers TEST_MAPPING
dans l'arborescence source :
src
├── project_1
│ └── TEST_MAPPING
├── project_2
│ └── TEST_MAPPING
└── TEST_MAPPING
Contenu de src/TEST_MAPPING
:
{
"presubmit": [
{
"name": "A"
}
]
}
Contenu de src/project_1/TEST_MAPPING
:
{
"presubmit": [
{
"name": "B"
}
],
"postsubmit": [
{
"name": "C"
}
],
"other_group": [
{
"name": "X"
}
]}
Contenu de src/project_2/TEST_MAPPING
:
{
"presubmit": [
{
"name": "D"
}
],
"import": [
{
"path": "src/project_1"
}
]}
Spécifier les répertoires cibles
Vous pouvez spécifier un répertoire cible pour exécuter des tests dans les fichiers TEST_MAPPING
de ce répertoire. La commande suivante exécute deux tests (A et B) :
atest --test-mapping src/project_1
Exécuter des règles de test post-commit
Vous pouvez également utiliser cette commande pour exécuter les règles de test post-envoi définies dans TEST_MAPPING
dans src_path
(par défaut, CWD) et ses répertoires parents :
atest [--test-mapping] [src_path]:postsubmit
Exécuter uniquement les tests qui ne nécessitent aucun appareil
Vous pouvez utiliser l'option --host
pour Atest afin d'exécuter uniquement les tests configurés sur l'hôte qui ne nécessite aucun appareil. Sans cette option, Atest exécute les deux types de tests : ceux qui nécessitent un appareil et ceux qui s'exécutent sur un hôte sans appareil. Les tests sont exécutés dans deux suites distinctes :
atest [--test-mapping] --host
Identifier les groupes de test
Vous pouvez spécifier des groupes de tests dans la commande Atest. La commande suivante exécute tous les tests postsubmit
liés aux fichiers du répertoire src/project_1
, qui ne contient qu'un seul test (C).
Vous pouvez également utiliser :all
pour exécuter tous les tests, quel que soit le groupe. La commande suivante exécute quatre tests (A, B, C et X) :
atest --test-mapping src/project_1:all
Inclure les sous-répertoires
Par défaut, l'exécution de tests dans TEST_MAPPING
avec Atest n'exécute que les tests de pré-soumission configurés dans le fichier TEST_MAPPING
du répertoire de travail actuel (ou du répertoire donné) et de ses répertoires parents. Si vous souhaitez exécuter des tests dans tous les fichiers TEST_MAPPING
des sous-répertoires, utilisez l'option --include-subdir
pour forcer Atest à inclure également ces tests.
atest --include-subdir
Sans l'option --include-subdir
, Atest n'exécute que le test A. Avec l'option --include-subdir
, Atest exécute deux tests (A et B).
Commentaires au niveau des lignes acceptés
Vous pouvez ajouter un commentaire de format //
au niveau de la ligne pour étoffer le fichier TEST_MAPPING
avec une description du paramètre qui suit.
ATest et Trade Federation prétraitent TEST_MAPPING
dans un format JSON valide sans commentaires. Pour que le fichier JSON reste propre, seul le commentaire de format //
au niveau de la ligne est accepté.
Exemple :
{
// For presubmit test group.
"presubmit": [
{
// Run test on module A.
"name": "A"
}
]
}