Tester le mappage

Il s'agit d'une brève introduction au mappage des tests et d'une explication sur la façon de commencer à configurer des tests dans le projet Android Open Source Project (AOSP).

À propos du mappage des tests

Le mappage de test 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 les décisions concernant les branches et les appareils à tester à l'infrastructure de test. 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 l'envoi dans les répertoires associés. Avec le mappage de test, vous pouvez ajouter le même ensemble de tests aux vérifications préalables à l'envoi avec un changement minimal dans l'arborescence source Android.

Voici quelques exemples:

Le mappage des tests s'appuie sur le harnais de test de la 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 après la fusion des modifications.

Règles du script de compilation de package

Pour que le bouquet de tests de la Trade Federation exécute des modules de test pour une compilation donnée, ces modules doivent avoir un test_suites défini pour Soong ou un LOCAL_COMPATIBILITY_SUITE défini pour Make dans l'une de ces deux suites:

  • general-tests est destiné aux tests qui ne dépendent pas des fonctionnalités spécifiques à l'appareil (comme le matériel spécifique au fournisseur que la plupart des appareils ne possèdent pas). La plupart des tests doivent faire partie de la suite general-tests, même s'ils sont spécifiques à une ABI ou une seule bitence ou à des fonctionnalités matérielles comme HWASan (il existe une cible test_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 de fonctionnalités spécifiques à l'appareil. En règle générale, ces tests se trouvent sous vendor/. 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 comme general-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 être nettoyé à la fin, par exemple en supprimant les fichiers temporaires générés pendant le test ;
  • Vous devez rétablir les valeurs par défaut ou d'origine des paramètres système.
  • Ne pas supposer qu'un appareil est dans un état donné, par exemple prêt à être root. La plupart des tests n'exigent pas de droits racine pour s'exécuter. Si un test doit nécessiter un accès racine, il doit le spécifier avec RootTargetPreparer dans son AndroidTest.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 préalables à l'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 la section Définir des groupes de test.

Vous pouvez définir le nom du module de test ou du test d'intégration de la fédération commerciale (chemin d'accès à la ressource vers le 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 affiner les tests à exécuter, utilisez des options telles que include-filter. Consultez l'exemple d'utilisation de include-filter.

Le paramètre host d'un test indique s'il s'agit d'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 cet exemple, le test CtsWindowManagerDeviceTestCases ne s'exécute en préenvoi que 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 d'accès importé sont également inclus. Le mappage de test autorise les importations imbriquées. Cela signifie que deux fichiers TEST_MAPPING peuvent s'importer l'un l'autre 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 la section Gestion des options dans Tradefed.

Exécuter des tests avec Atest

Pour exécuter les règles de test avant envoi localement:

  1. Accédez au répertoire contenant le fichier TEST_MAPPING.
  2. Exécutez la commande suivante:

    atest
    

Tous les tests de préenvoi configurés dans les fichiers TEST_MAPPING du répertoire actuel et de ses répertoires parents sont exécutés. Atest recherche 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ésoumission dans les fichiers TEST_MAPPING du répertoire de travail actuel (RPD) et des répertoires parents. Atest recherche et utilise le fichier TEST_MAPPING dans le répertoire de travail courant et tous ses répertoires parents.

Structurer le code source

Cet exemple montre comment configurer des 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, B):

atest --test-mapping src/project_1

Exécuter les règles de test post-envoi

Vous pouvez également utiliser cette commande pour exécuter les règles de test post-soumission 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 pour l'hôte qui ne nécessitent aucun appareil. Sans cette option, Atest exécute les deux tests, ceux qui nécessitent un appareil et ceux qui s'exécutent sur un hôte qui n'en nécessite pas. 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 test dans la commande Atest. La commande suivante exécute tous les tests postsubmit associé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, 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 dans le répertoire de travail courant (ou répertoire donné) et 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 de la ligne 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 la fédération commerciale 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"
    }
  ]
}