Chez Sipios, nous croyons que l’optimisation des tests des applications web est essentielle pour garantir la qualité et la fiabilité de notre code.
Les tests permettent de vérifier que chaque composant de votre application fonctionne comme prévu, répond correctement aux interactions des utilisateurs et reste robuste face aux modifications futures. De plus, des tests bien écrits peuvent servir de documentation, fournissant des indications sur le comportement attendu de l'application. Pour les développeurs utilisant Angular avec Jest, l'intégration d'Angular Testing Library (ATL) peut considérablement simplifier et améliorer le processus de test. Cette bibliothèque offre des outils et des méthodes plus intuitifs pour écrire des tests qui simulent les interactions réelles des utilisateurs.
Cet article vous guidera à travers la mise en œuvre d'Angular Testing Library dans un projet Angular existant utilisant Jest. Nous explorerons les fonctionnalités clés d'ATL, notamment render
, screen
, userEvent
et fireEvent
, et comment elles peuvent rendre nos tests plus simples et plus efficaces.
Cet article suppose que vous avez déjà un projet Angular existant que vous souhaitez tester avec Jest installé. Pour ceux qui commencent tout juste, je recommande de suivre le tutoriel officiel Angular Tour of Heroes. Ce tutoriel offre une excellente introduction à Angular et vous aidera à créer une application où vous pourrez ensuite appliquer les concepts abordés dans cet article.
Pour commencer, nous devons installer Angular Testing Library et ses dépendances dans notre projet Angular. Exécutons les commandes suivantes dans notre terminal :
Ensuite, assurons-nous que Jest est correctement configuré dans notre projet. Nous devrions avoir un fichier jest.config.js
à la racine de notre projet. Voici un exemple de configuration pour un projet Angular :
setup-jest.ts
Le fichier setup-jest.ts
est utilisé pour ajouter des configurations spécifiques à Jest avant l'exécution des tests. Dans ce cas, nous ajoutons des matchers supplémentaires fournis par Jest DOM pour faciliter les assertions sur le DOM.
Pour illustrer l'utilisation de l'Angular Testing Library, nous allons utiliser un composant du tutoriel officiel Angular Tour of Heroes. Prenons comme exemple le HeroDetailComponent
:
Angular Testing Library nous permet de rendre dynamiquement le composant que nous voulons tester et d'interagir avec lui. Il existe une fonction dédiée pour configurer le composant et personnaliser ses propriétés, imports et services injectés : render
Ici, nous utilisons un composant basique, ce qui rend l'utilisation de render
simple. Cependant, render
peut également être utilisé pour des composants plus complexes et permet une configuration similaire à celle de TestBed, couramment utilisé. Pour voir toute la puissance de cette fonction, je vous recommande de consulter la documentation d'Angular Testing Library.
Avertissement : Veuillez noter que get
, query
, find
et byRole
, byText
ne sont pas des méthodes en elles-mêmes. Dans la partie suivante, nous parlerons de ces différentes parties séparément afin de comprendre leur utilisation. Cependant, elles doivent toujours être associées ensemble pour une utilisation correcte. Par exemple, utiliser getByText
, queryByRole
ou findByText
sont des combinaisons fonctionnelles.
Angular Testing Library fournit plusieurs méthodes pour rechercher des éléments rendus à l'écran. Les principales méthodes sont get
, find
, et query
, chacune avec des variantes comme ByText
et ByRole
. Voici comment les utiliser et les différences entre elles :
null
si l'élément n'est pas trouvé.Dans tous les cas, ces méthodes lèvent une erreur si plusieurs éléments correspondants sont trouvés. Cependant, elles ont toutes des variantes (getAllBy
, queryAllBy
, findAllBy
).
Exemple de test avec différentes méthodes de recherche
Variantes
Il existe de nombreuses variantes à ajouter à nos trois préfixes (get, query, find) pour rechercher le DOM rendu. Voici deux des plus utiles :
Avantages des différentes méthodes
Ces méthodes de recherche rendent les tests plus intuitifs et alignés sur les interactions réelles des utilisateurs, améliorant la robustesse et la maintenabilité de vos tests.
Parfois, vous pouvez rencontrer des éléments inaccessibles via les méthodes getBy
, surtout s'ils ont des noms vides ou manquent d'attributs ARIA appropriés. Voici quelques stratégies pour gérer ces situations :
getByTestId
ou getByLabelText
pour cibler les éléments en fonction de leurs attributs.Pour tester si le bouton "Save" appelle correctement la méthode save
lorsqu'il est cliqué, nous utiliserons jest.spyOn
pour espionner la méthode et userEvent
pour simuler le clic.
Ici, nous simulons simplement un clic. Cependant, userEvent
permet de tester un éventail beaucoup plus large d'interactions utilisateur. Pour une liste complète, je vous invite à consulter la documentation d'Angular Testing Library liée. Vous trouverez juste en bas une liste des quelques avantages à utiliser userEvent
.
userEvent
Simulation réaliste des interactions utilisateur
Naturelle et complète : userEvent
permet une simulation plus complète des interactions utilisateur. Par exemple, un clic de souris n'est pas seulement un événement isolé mais une série d'actions (clic, relâchement, focus, etc.). userEvent.click
simule ces actions de manière réaliste, ce qui est essentiel pour tester des comportements complexes.
Délais simulés : Les actions simulées avec userEvent
incluent des délais réalistes entre les événements, ce qui peut révéler des problèmes de synchronisation ou des conditions de concurrence qui pourraient ne pas être détectés autrement.
Précision et robustesse des tests
Précision accrue : Les interactions simulées avec userEvent
sont plus proches des actions réelles des utilisateurs, rendant les tests plus précis et représentatifs des scénarios d'utilisation réels.
Robustesse : Les tests utilisant userEvent
sont moins susceptibles de passer à côté de bugs subtils liés aux événements utilisateur. En simulant des interactions complètes, ces tests peuvent détecter des erreurs qui n'apparaissent que dans des conditions d'utilisation spécifiques.
Clarté et maintenabilité du code
Lisibilité : Les tests écrits avec userEvent
sont faciles à lire et à comprendre. Les fonctions telles que userEvent.click
, userEvent.type
et userEvent.clear
décrivent explicitement les actions de l'utilisateur, rendant les tests plus intuitifs.
Maintenabilité : La clarté et la précision des tests écrits avec userEvent
améliorent la maintenabilité du code de test. Les développeurs peuvent facilement comprendre et mettre à jour les tests à mesure que les interactions utilisateur évoluent.
fireEvent
fireEvent
est une méthode fournie par Testing Library pour déclencher des événements DOM de manière programmatique. Bien pratique pour des cas simples, fireEvent
ne simule pas les interactions utilisateur avec le même réalisme que userEvent
. Contrairement à userEvent
, qui reproduit une séquence complète d'actions (y compris les délais naturels entre un "clic" et un "relâchement" de la souris), fireEvent
déclenche uniquement l'événement ciblé sans ces détails supplémentaires. Cela peut suffire pour des tests unitaires basiques, mais pour des tests d'interaction utilisateur plus réalistes et représentatifs, userEvent
est généralement préféré.
Bien que Angular Testing Library (ATL) propose des outils puissants pour les tests, elle est également relativement lourde et peut affecter les temps d'exécution de votre CI. Il est important d'utiliser ATL avec discernement pour éviter les problèmes de performances. Voici quelques conseils pour améliorer le temps d'exécution de vos tests :
Intégrer Angular Testing Library avec Jest dans un projet Angular existant peut considérablement améliorer votre flux de travail de test. Les outils et méthodes fournis par ATL sont conçus pour rendre vos tests plus simples, plus intuitifs et plus proches des interactions réelles avec les utilisateurs. En suivant les étapes et exemples décrits dans cet article, vous serez bien équipé pour écrire des tests robustes et faciles à entretenir pour vos applications Angular.