Écrire un exécuteur de test Tradefed

Cette page explique comment écrire un nouveau lanceur de test dans Tradefed.

Arrière-plan

Pour en savoir plus sur la place des exécuteurs de test dans l'architecture Tradefed, consultez la section Structure d'un exécuteur de test.

Il ne s'agit pas d'une condition préalable à l'écriture d'un nouveau lanceur de test. Les exécuteurs de test peuvent être écrits de manière isolée.

Au minimum: implémenter l'interface

Le minimum requis pour être qualifié de lanceur de test Tradefed consiste à implémenter l'interface IRemoteTest et plus précisément la méthode run(TestInformation testInfo, ITestInvocationListener listener).

Cette méthode est celle appelée par le harnais lorsque vous utilisez l'exécuteur de test, semblable à un Runnable Java.

Chaque partie de cette méthode est considérée comme faisant partie de l'exécution du lanceur de test.

Rapporter les résultats du lanceur de test

La méthode run de l'interface de base permet d'accéder à un objet d'écouteur de type ITestInvocationListener. Cet objet est essentiel pour générer des rapports sur les résultats structurés du testeur de test vers le harnais.

Lorsqu'il signale des résultats structurés, un lanceur de test possède les propriétés suivantes:

  • Fournissez une liste appropriée de tous les tests exécutés, de la durée de leur exécution et de leur état (réussite, échec ou autre).
  • Générez des rapports sur les métriques associées aux tests, le cas échéant (par exemple, celles concernant le temps d'installation).
  • S'adapter à la plupart des outils d'infrastructure, par exemple afficher des résultats et des métriques, etc.
  • Il est généralement plus facile à déboguer, car il existe une trace plus précise de l'exécution.

Cela dit, la création de rapports sur les résultats structurés est facultative. Un lanceur de test peut simplement vouloir évaluer l'état de l'exécution entière comme RÉUSSITE ou ÉCHEC sans aucun détail sur l'exécution réelle.

Les événements suivants peuvent être appelés sur l'écouteur pour informer le harnais de la progression actuelle des exécutions:

  • testRunStarted: informe du début d'un groupe de scénarios de test associés.
    • testStarted: informe du début d'un cas de test.
    • testFailed/testIgnored: signalez le changement d'état du cas de test en cours. Un cas de test sans changement d'état est considéré comme réussi.
    • testEnded: signale la fin du scénario de test.
  • testRunFailed: indique que l'état global de l'exécution du groupe de cas de test est un échec. Une exécution de test peut être une réussite ou un échec indépendamment des résultats des scénarios de test, en fonction de ce à quoi l'exécution s'attendait. Par exemple, un binaire exécutant plusieurs scénarios de test peut signaler tous les scénarios de test réussis, mais avec un code de sortie d'erreur (pour quelque raison que ce soit: fuite de fichiers, etc.).
  • testRunEnded: informe de la fin du groupe de scénarios de test.

Il incombe à l'implémentateur du lanceur de tests de gérer et de s'assurer de l'ordre correct des rappels, par exemple en veillant à ce que testRunEnded soit appelé en cas d'exception à l'aide d'une clause finally.

Les rappels des cas de test (testStarted, testEnded, etc.) sont facultatifs. Une exécution de test peut se produire sans scénario de test.

Vous remarquerez que cette structure d'événements s'inspire de la structure JUnit type. C'est intentionnel pour que les choses restent proches d'un élément de base que les développeurs connaissent généralement.

Enregistrer les journaux du lanceur de test

Si vous écrivez votre propre classe de test ou exécuteur Tradefed, vous allez implémenter IRemoteTest et obtenir un ITestInvocationListener via la méthode run(). Cet écouteur peut être utilisé pour consigner des fichiers comme suit:

    listener.testLog(String dataName, LogDataType type_of_data, InputStreamSource data);

Tester avec un appareil

L'interface minimale ci-dessus permet d'exécuter des tests très simples, isolés et ne nécessitant aucune ressource particulière, par exemple des tests unitaires Java.

Les rédacteurs de tests qui souhaitent passer à l'étape suivante des tests des appareils doivent disposer des interfaces suivantes:

  • IDeviceTest permet de recevoir l'objet ITestDevice qui représente l'appareil en cours de test et fournit l'API pour interagir avec lui.
  • IBuildReceiver permet au test d'obtenir l'objet IBuildInfo créé à l'étape du fournisseur de compilation contenant toutes les informations et tous les artefacts liés à la configuration du test.

Les exécuteurs de test s'intéressent généralement à ces interfaces afin d'obtenir les artefacts liés à l'exécution (par exemple, des fichiers supplémentaires) et d'obtenir l'appareil testé qui sera ciblé pendant l'exécution.

Tester avec plusieurs appareils

Tradefed permet d'exécuter des tests sur plusieurs appareils en même temps. Cela est utile lorsque vous testez des composants qui nécessitent une interaction externe, comme l'association d'un téléphone et d'une montre.

Pour écrire un outil d'exécution de test pouvant utiliser plusieurs appareils, vous devez implémenter IMultiDeviceTest, qui vous permettra de recevoir une carte de ITestDevice à IBuildInfo contenant la liste complète des représentations d'appareils et les informations de compilation associées.

Le setter de l'interface est toujours appelé avant la méthode run. Il est donc possible de supposer que la structure sera disponible lorsque run sera appelé.

Les tests connaissent leur configuration

Certaines implémentations de lanceur de test peuvent avoir besoin d'informations sur la configuration globale pour fonctionner correctement, par exemple des métadonnées sur l'appel, ou sur l'target_preparer exécutée précédemment, etc.

Pour ce faire, un exécuteur de test peut accéder à l'objet IConfiguration dont il fait partie et dans lequel il s'exécute. Pour en savoir plus, consultez la description de l'objet de configuration.

Pour l'implémentation du testeur, vous devez implémenter IConfigurationReceiver pour recevoir l'objet IConfiguration.

Exécuteur de test flexible

Les outils d'exécution de tests peuvent fournir un moyen flexible d'exécuter leurs tests s'ils ont un contrôle précis sur eux. Par exemple, un outil d'exécution de tests JUnit peut exécuter individuellement chaque test unitaire.

Cela permet au harnais et à l'infrastructure plus importants d'exploiter ce contrôle précis et aux utilisateurs d'exécuter partiellement le lanceur de test via le filtrage.

La prise en charge du filtrage est décrite dans l'interface ITestFilterReceiver, qui permet de recevoir des ensembles de filtres include et exclude pour les tests qui doivent ou ne doivent pas s'exécuter.

Selon notre convention, un test est exécuté IFF s'il correspond à un ou plusieurs filtres "Inclure" ET ne correspond à aucun des filtres d'exclusion. Si aucun filtre d'inclusion n'est fourni, tous les tests doivent être exécutés tant qu'ils ne correspondent à aucun des filtres d'exclusion.