Skip to content

Blog


Un cadre pour le développement rapide et évolutif de tests d'interface utilisateur Android

19 août 2020

|

Nishant Soni

Le développement rapide de fonctionnalités et la productivité des ingénieurs mobiles ont longtemps été freinés par les tests d'interface utilisateur, un processus lent mais essentiel. Bien que les nouvelles technologies de test automatisé de l'interface utilisateur, telles que Automate de l'interface utilisateur ou Espresso ont aidé les développeurs à écrire des tests d'interface utilisateur, ces outils ne permettent pas de conserver un code propre, organisé et facile à lire. Cela nuit à la productivité et à l'évolutivité et continue de faire des tests d'interface utilisateur un goulot d'étranglement pour le développement.  Heureusement, les entreprises qui se débattent avec les tests d'interface utilisateur peuvent améliorer les outils d'automatisation des tests d'interface utilisateur en utilisant un logiciel de gestion des tests d'interface utilisateur. Modèle de conception fluide pour créer des tests faciles à lire et à gérer, rapides à mettre en œuvre et évolutifs.  At DoorDash, testing all the UI scenarios of a new build would take two full days for three developers and one QA, which slowed our development cycle to one release every two weeks. This process, while essential to catching harmful user bugs, hurt the team‚Äôs morale and productivity overall. To solve this problem we built a Fluent design pattern-based framework that enabled us to utilize UI automation tools by making tests easy to read and scalable.  Pour démontrer comment nous avons augmenté la vélocité de nos tests, nous allons d'abord passer en revue les problèmes liés à l'utilisation d'UI Automator et d'autres approches de test. Ensuite, nous présenterons les patrons de conception, les patrons de conception Fluent, et la façon dont nous les avons implémentés chez DoorDash. 

Les défis des tests d'interface utilisateur

Les tests rapides et évolutifs de l'interface utilisateur constituent un défi majeur pour garantir l'absence de bogues dans le développement d'applications mobiles, car les outils d'automatisation des tests ne produisent pas de tests faciles à lire et évolutifs, et les solutions de rechange sont tout aussi fastidieuses.  Alors que des outils comme UI Automator ou Espresso utilisant Android Studio ont permis aux ingénieurs de commencer plus facilement à écrire des tests sur Android pour simuler le comportement de l'utilisateur, les tests sont difficiles à comprendre et à gérer à l'échelle. Bien que les tests puissent convenir au début, l'augmentation du nombre de tests rend plus difficile la compréhension du code de test, ce qui pose un problème de maintenance à long terme.   Les outils d'automatisation des tests peuvent produire un code de test dans lequel chaque action est décrite en trois ou quatre lignes d'instructions, au lieu de lignes concises avec des descripteurs clairs, en utilisant le langage des affaires, comme le montre la figure 1 ci-dessous :
Les tests d'automatisation créés sans modèle de conception peuvent donner lieu à un code obscur qui n'énonce pas l'intention du test.
Figure 1: Automation tests created without a design pattern can result in obscure code that does not state the intent of the test.
L'alternative à l'utilisation de plates-formes de test automatisées consiste à faire appel à des testeurs manuels. Malheureusement, cette solution ne permet pas vraiment de gagner du temps, car les testeurs manuels ont besoin de transferts de connaissances et la gestion de la délégation prend presque autant de temps et d'efforts que si les développeurs effectuaient eux-mêmes les tests. En outre, les tests manuels ne sont pas aussi précis que les tests automatisés, car ils laissent place à davantage d'erreurs humaines, et ils ne sont pas rentables pour les régressions à haut volume.

Comment un modèle de conception peut aider à l'automatisation de l'interface utilisateur

Les problèmes liés aux tests manuels de l'interface utilisateur peuvent être résolus en choisissant un bon modèle de conception et le bon cadre pour les tests de l'interface utilisateur. Un bon cadre de test d'automatisation doit permettre aux ingénieurs d'écrire des tests qui sont.. :
  • Facile à comprendre et à lire
  • Rapidement rédigé
  • Maintenable
  • Évolutif
Plusieurs modèles de conception sont couramment utilisés pour les tests d'automatisation des sites web, le plus populaire étant le modèle Modèle d'objet de page décrit par Martin Fowler en 2013. En appliquant ce modèle de conception à l'exemple de la figure 1 ci-dessus, nous pouvons constater une nette amélioration de la lisibilité du code de test, comme le montre la figure 2 ci-dessous :
Un test d'automatisation utilisant le modèle Page Object produit un test mieux organisé et plus concis que dans notre exemple précédent.
Figure 2: An automation test using the Page Object pattern produces a better organized and more concise test than in our previous example.
Le code de la figure 2 est bien meilleur que celui avec lequel nous avons commencé :
  • Chaque action peut être effectuée en une seule ligne 
  • Les détails sont extraits à l'intérieur d'une fonction
  • Cette fonction peut être réutilisée chaque fois que cette action est à nouveau requise 
Cependant, l'adoption d'un tel modèle de conception pose encore quelques problèmes :
  • The test is still not clearly showing it‚Äôs intent; instead it looks more like coded instructions
  • Il y aura encore beaucoup de duplication de code, ce qui n'est pas idéal

Utilisation d'une interface fluide pour mettre en évidence la logique commerciale

Un modèle de conception Fluent nous offre le meilleur des deux mondes, car il démontre une intention claire en utilisant un langage spécifique au domaine. Une interface fluide est une API orientée objet dont la conception repose largement sur l'enchaînement de méthodes. L'objectif est d'améliorer la lisibilité du code en utilisant un langage spécifique au domaine, permettant de relayer le contexte d'instruction d'un appel ultérieur.

Comment un modèle de conception Fluent démontre une intention claire

Les modèles de conception doivent avoir une intention claire et utiliser un langage spécifique au domaine qui peut presque être lu comme un langage conversationnel. Une interface fluide répond à ces critères car elle nous permet d'utiliser des noms d'API fluides et un langage spécifique au domaine.   Les avantages de l'utilisation d'un modèle de conception Fluent sont les suivants :
  • Lorsque le code de test est facile à comprendre, il est facile à étendre et à réutiliser.
  • La facilité d'utilisation aidera les développeurs à travailler plus rapidement et à être plus confiants lors de la rédaction des tests. 
  • Le modèle de conception est indépendant des outils sous-jacents tels que UI Automator ou Espresso.

Utilisation d'un modèle de conception Fluent pour construire l'automatisation des tests de l'interface utilisateur de l'application Dasher

Ici, à Doordash, nous avons utilisé TestRail pour tester manuellement l'application avant chaque mise en production. Il fallait auparavant trois ingénieurs logiciels et un ingénieur chargé de l'assurance qualité pour passer en revue les tests TestRail et une demi-journée chacun pour les exécuter, ce qui prenait deux journées de travail complètes. Ce processus limitait le nombre de versions de l'application à toutes les deux semaines.  La mise en place d'un nouveau cadre d'automatisation de l'interface utilisateur pour Android a permis d'éliminer ces points douloureux pour les cycles de publication. Nous allons maintenant entrer un peu plus dans les détails pour expliquer l'approche et les outils que nous avons utilisés, l'architecture globale de haut niveau de la solution, et partager quelques bonnes pratiques.

Notre approche de l'utilisation des modèles de conception Fluent 

En général, chaque scénario de test de l'interface utilisateur implique des interactions avec des activités et des écrans ; sur chaque écran, l'utilisateur effectuera une action et attendra un comportement en conséquence. Nous utilisons alors assertions pour vérifier les résultats.  Pour réaliser ces tests, nous structurons le code de test de manière à ce que chaque écran encapsule les actions qui sont effectuées sur cet écran et puisse vérifier le comportement après avoir effectué ces actions. Toutes les interactions sont nommées dans un langage spécifique au domaine en utilisant l'interface du modèle de conception Fluent, comme le montre la figure 3 ci-dessous :
Dans notre cadre d'automatisation de l'interface utilisateur pour notre application Android Dasher, nous utilisons un modèle de conception Fluent pour nommer les interactions dans notre langage spécifique au domaine.
Figure 3: In our UI automation framework for our Android Dasher app, we use a Fluent design pattern to name interactions in our domain-specific language.

Suite de tests 

Le choix des outils joue un rôle important dans l'amélioration de la productivité des développeurs. Nous estimons que nos outils sont faciles à utiliser et qu'ils bénéficient d'une bonne assistance en ligne.  Outils de test de l'interface utilisateur : Avant d'élaborer nos procédures de test de l'interface utilisateur, nous avons examiné différents outils permettant de rédiger des tests de l'interface utilisateur, tels que Appium, a third-party tool. However, we found that Android‚Äôs native tools were easier to use and had better support. There are two UI testing tools supported by Google, which can be run separately or together, since they run under the same instrumentation test runner:
  • UI Automator - UI Automator est un cadre de test d'interface utilisateur adapté aux tests fonctionnels d'interface utilisateur inter-applications à travers le système et les applications installées.
  • Espresso - L'un des principaux avantages de l'utilisation d'Espresso est qu'il permet de synchroniser automatiquement les actions de test avec l'interface utilisateur de l'application testée. Espresso détecte lorsque le thread principal est inactif, ce qui lui permet d'exécuter les commandes de test au moment opportun, améliorant ainsi la fiabilité des tests.
IDE :
  • Studio Android: Pour les développeurs qui pensent que les tests d'interface utilisateur font partie intégrante du développement d'une application, Android Studio leur facilitera la vie. Il permet d'exécuter les tests unitaires, les tests de l'interface utilisateur Android et l'application elle-même dans le même environnement de développement. Il permet également de structurer les paquets de telle sorte que le code de l'application et les tests correspondants (tests unitaires et tests de l'interface utilisateur) peuvent résider dans le même référentiel, ce qui facilite la maintenance des versions du code de l'application et des tests correspondants.
Dispositifs d'essai ciblés :
  • Les tests d'interface utilisateur sont généralement exécutés sur un appareil réel ou sur un émulateur afin d'imiter le scénario de test. Pour la plupart de nos tests, nous utilisons des émulateurs pour les configurations et tailles d'appareils les plus courantes.
CI/CD :
  • Bitrise est l'un des outils CI/CD les plus populaires sur le cloud qui permet une mise à l'échelle et une facilité d'utilisation pour la mise en place d'environnements de test. En particulier pour les tests d'interface utilisateur, il permet l'intégration à la fois d'un parc d'appareils et d'appareils virtuels et est devenu un outil facile pour mettre en place un environnement de construction et de test pour les développeurs.

Processus de test

Nous écrivons des scénarios de test, illustrés dans la figure 3 ci-dessus, dans un langage spécifique au domaine, en suivant une approche axée sur le comportement. Ces tests utilisent l'API de configuration des tests pour créer l'environnement d'un test particulier et utilisent des objets d'écran qui interagissent avec les écrans et vérifient les actions. L'interaction et la vérification des écrans sont finalement réalisées par un outil d'automatisation des tests, tel que UI Automator, Espresso ou tout autre outil similaire.  To understand this process, let‚Äôs look at an example for the login flow of an app using a Fluent design pattern and our testing architecture described above. Test de connexion :
L'utilisation du modèle de conception Fluent dans nos tests d'automatisation permet d'obtenir un code simplifié et facile à lire.
Figure 4: Using the Fluent design pattern in our automation test results in easy to read, simplified code.
Le test de la figure 4 est écrit en utilisant le modèle de conception Fluent, et la classe de base qui permet ce modèle s'appelle Screen.kt. Le code de Screen.kt est présenté dans la figure 5 ci-dessous :
image10
Figure 5 : La classe de base Screen.kt permet d'appliquer le modèle de conception Fluent.
All the screen classes extend this class and follow the pattern of returning itself for each interaction/verification function, thereby passing the context along. The inline generic method “<reified T: Screen> on()” is used to switch context from one screen to another. An example of the “Screen” implementation is shown in Figure 6, below:
Figure 6 : Bien que la classe LoginScreen soit mise en œuvre avec UI Automator dans cet exemple, elle pourrait facilement être remplacée par un autre outil pour la même action, mais avec une approche différente.
Figure 6 : Bien que la classe LoginScreen soit mise en œuvre avec UI Automator dans cet exemple, elle pourrait facilement être remplacée par un autre outil pour la même action, mais avec une approche différente.
L'implémentation ci-dessus utilise l'outil sous-jacent, UI Automator, pour interagir avec l'écran. Bien que cet exemple utilise UI Automator, il peut être remplacé par Espresso ou tout autre outil similaire sans affecter la logique d'entreprise ou les attentes en matière de test.

Révision de la structure des dossiers

Pour les codeurs propres et les concepteurs de logiciels, la principale propriété d'un paquet est la possibilité d'avoir un nom significatif qui décrit son objectif et sa raison d'être. C'est pourquoi nous avons organisé nos paquets comme suit :
  1. test : Contient tous les tests pour différents scénarios
  2. écran : Contient tous les écrans de l'application et les interactions correspondantes.
  3. UI Automator/Espresso : contient des classes d'outils permettant d'effectuer des interactions à l'écran et de vérifier les comportements.
  4. utils : API commune permettant de configurer l'environnement pour l'exécution d'un test, par exemple la création et l'attribution d'ordres avant le démarrage de Dashing. Elle contient également d'autres fonctions utilitaires communes.
Nous organisons nos paquets de manière à ce qu'ils puissent être nommés de manière pertinente.
Figure 7: We organize our packages in a manner that allows for meaningful naming.

Bonnes pratiques pour l'utilisation de cette approche 

En écrivant ces tests, nous avons développé quelques bonnes pratiques qui nous ont aidés à garder notre code propre, lisible et extensible. En voici quelques-unes :
  • Convention de nommage : Même pour la classe UIAutomator, nous continuons à utiliser le modèle de conception Fluent, qui se lit comme un langage spécifique au domaine.
    • UiAutomator.kt : cette classe comportera essentiellement deux types de fonctions : toute action de l'utilisateur sur l'écran et la vérification du comportement.
      • Verification function name uses this pattern: hasViewBy<Class,Text,ContenDesc,ResourceId etc that identifies the view>
      • Action function name has this pattern: <click,swipe,scroll,set><Button/View>By<Button/View identifies>
    • L'écran : Il est très important d'utiliser ici le modèle de conception Fluent et de trouver un nom correct pour les fonctions afin qu'elles soient plus fluides lors de la lecture du test. 
      • Le nom de la classe d'écran correspond à la fonction de l'écran, par exemple PickUpItemScreen().
      • Le nom de la fonction de vérification est rédigé dans un langage spécifique au domaine, par exemple verifyAmount(), verifySignatureStepComplete(), verifyCompleteStepsGetCxSignature(), etc.
      • Le nom de la fonction d'action est également dans un langage spécifique au domaine, par exemple clickStartCateringSetup(), slideBeforeCateringSetupComplete() etc.
  • Nous devrions toujours ajouter un journal dans chaque fonction de la classe d'écran, ce qui permet de dépanner plus rapidement les journaux CI/CD.
  • Toute boîte de dialogue/feuille de bas de page pertinente pour un écran est définie comme une classe imbriquée de l'écran parent.
  • Toutes les vérifications auraient dû faire l'objet d'une assertion accompagnée d'un message de journal indiquant clairement la raison de l'échec de l'assertion, comme le montre la figure 8 ci-dessous :
Figure 8 : L'inclusion d'un message d'échec dans les assertions facilite le dépannage des tests qui ont échoué.
Figure 8 : L'inclusion d'un message d'échec dans les assertions facilite le dépannage des tests qui ont échoué.

Les modèles de conception fluides augmentent la vitesse des développeurs

Une fois le cadre initial mis en place, nous avons terminé 70 % de nos tests de régression en deux mois. Voici quelques-uns des résultats :
  • La couverture de notre code est passée de 0 % à ~40 %.
  • Nos tests manuels ont été quatre fois plus rapides, passant de 16 à 4 heures.
  • Les cycles de publication sont passés d'une version toutes les deux semaines à des versions hebdomadaires, et nous pouvons effectuer des tests de régression à tout moment. 
  • L'équipe est plus productive car il suffit d'écrire les tests pour les nouvelles fonctionnalités ou de mettre à jour les fonctionnalités existantes, ce qui est beaucoup plus rapide à développer.

Conclusion

L'utilisation de l'interface fluide pour les tests d'interface utilisateur a libéré les ingénieurs des tâches répétitives et chronophages, ce qui leur a permis de consacrer plus de temps à la résolution de cas délicats. L'amélioration de la couverture du code et l'exécution des tests automatisés pour les tests de régression ont assuré la robustesse de notre application Android Dasher.  Comme la structure du code est indépendante de l'outil de test sous-jacent (UI Automator ou Espresso), nous pouvons facilement adopter tout outil plus performant publié à l'avenir.  

About the Author

Emplois connexes

Job ID: 2915998
Localisation
Sao Paulo, Brazil
Département
Ingénierie
Localisation
Sunnyvale, CA
Département
Ingénierie
Localisation
Pune, Inde
Département
Ingénierie
Localisation
São Paulo, Brésil
Département
Ingénierie
Localisation
San Francisco, CA; Tempe, AZ
Département
Ingénierie