Pourquoi est-on passé de Selenium à Cypress ?
- Posted by LivingObjects
Pourquoi est-on passé de Selenium à Cypress ?
Les tests bout en bout représentent une étape essentielle de la validation d’une application. Le développeur consciencieux teste chaque fonctionnalité unitairement au fur et à mesure de leur implémentation. Mais rien ne vaut une approche bout en bout pour valider la cohérence fonctionnelle et le bon fonctionnement du logiciel. Cette typologie de tests permet de mettre en place une approche utilisateur, en réalisant des scénarii complets reflétant l’utilisation réelle du logiciel.
Mais qui dit complexe, dit long et/ou fastidieux, ce qui n’est pas forcément compatible avec une problématique de budget restreint ou de délais serrés. D’autre part, un VRAI utilisateur a en moyenne un niveau de patience inférieure à l’ère de Planck (qui est de 10-43 seconde, pour ceux qui ne le savent pas).
Heureusement, des outils existent pour simuler un utilisateur d’une patience infinie : Si le développeur souhaite réaliser un test sur une boite de dialogue comme par exemple « Clique sur le menu /// Sélectionne le 10ième élément de la liste /// Ferme la boite de dialogue », l’outil le fera 10 000 fois sans jamais se plaindre !
Selenium est probablement le plus connu d’entre eux. Récemment, Cypress a révolutionné l’approche en rendant l’écriture des tests plus simple et moins coûteuse en temps.
Commençons par Selenium
Selenium est un process externe qui communique en HTTP avec le navigateur. Tout est dit : Selenium ne sait pas ce qui se passe dans le navigateur.
Lorsqu’on réalise un script de test sur un élément du DOM, il faut attendre que l’élément soit chargé (apparu sur la page) pour passer à l’étape suivante (si on demande à l’outil d’appuyer sur un bouton qui n’existe pas encore, cela ne peut pas marcher).
Combien de temps attend-on avant de faire cliquer sur ce fameux bouton ? 100ms, 1s, 2s ? Telle est la question. Si on choisit une valeur trop basse, elle pourrait être dépassée uniquement parce que la réponse du serveur arrivera trop tard (ce qui ne constitue pas une erreur de bout en bout mais un problème de performance). Alors on met généralement des temps longs entre chaque action et on attend, on attend, on attend…
Ceux qui en ont assez d’attendre font du pooling régulier auprès du navigateur pour vérifier l’existence de l’élément, ce qui allonge encore l’écriture des tests.
Enfin, il est impossible d’arrêter et de visualiser les étapes intermédiaires d’un test, hormis les screenshots réalisés par l’outil sur demande, à certaines étapes du test.
Ces différents points illustrent quelques obstacles auxquels doit se confronter le développeur souhaitant réaliser des tests E2E avec Selenium.
Passons à Cypress
Cypress tourne directement dans le navigateur : accès à la console, aux évènements AJAX, à l’API du DOM… Ce qui est extrêmement intéressant.
Quelques exemples:
- Plus de délai prédéfini et d’attente inutile : Cypress a un accès direct aux éléments réseaux du navigateur. Cela signifie que lorsqu’une requête est émise, on peut l’intercepter grâce à la commande wait(‘requete’), traiter la réponse et passer à l’étape suivante.
- La vérification de l’état du state Angular, React ou VueJS se fait directement dans le code du test.
Et comme Cypress a été conçu avec le soucis du développeur en train de développer et de l’utilisateur en train d’utiliser, il y a plusieurs autres intérêts :
- Il est rapide à installer sans fastidieux travail de configuration (par exemple le choix de librairies d’assertion est déjà fait)
- Le développeur peut consulter l’état de l’application à chaque étape du test. Des messages d’erreur renvoyant vers la documentation Cypress sont générés lorsque les tests échouent.
- Cypress fait fonctionner l’application tel que l’utilisateur le ferait : il est par exemple impossible d’appuyer sur un bouton caché par un menu ou une popup (ce qui peut être le cas dans selenium).
- Il permet d’intercepter et de modifier les réponses émises par le serveur pour générer un scénario connu, ce qui est très utile quand on ne sait pas quelles données seront renvoyées et que l’on souhaite axer les tests sur le comportement de l’UI (si je reçois 2 éléments, je teste que ma liste affiche bien 2 éléments).
- Enfin, vu la facilité d’intégration de Cypress dans l’environnement de développement, il facilite l’approche TDD (Test Driven Development), consistant à écrire les tests avant le code applicatif. En effet, les tests exécutés par Cypress sont affichés dans Chrome, où tous les autres outils de développement sont également présents.
Quoi tester ?
La première stratégie est véritablement bout en bout : On vérifie à la fois la qualité des réponses du serveur en plus de la façon dont elles sont représentées dans le front. Cette stratégie impose évidemment que les données soient cohérentes au niveau du serveur. Par exemple, si on demande un graphe avec une granularité heure sur 10 jours, on s’attend à recevoir 240 points. La qualité du test dépendra donc non seulement de l’affichage au niveau du front mais également de l’intégrité des données au niveau serveur (c’est un vrai test bout en bout).
La deuxième stratégie est de simuler des réponses back pour plus rapidement isoler les problèmes front.
Ces deux stratégies sont complémentaires, et peuvent être réalisées dans un même jeu de tests pour augmenter le taux de couverture des tests.
Travaux pratiques
Voici trois exemples de tests courants réalisés à l’aide de Cypress.
Comment tester qu’un bouton est bien affiché ? Comment vérifier l’affichage d’un message après avoir cliqué sur le bouton ?
- .get() permet de sélectionner un élément du DOM. Sa syntaxe correspond au fonctionnement de $(…) dans jQuery.
- .should() permet de créer une assertion, par exemple « devrait être visible ».
- .click() déclenche un évènement « click » sur l’élément. Il est également possible de déclencher l’ensemble des évènements JavaScript avec la commande cy.trigger(« nom_évènement »).
- .contains() récupère l’élément du DOM contenant le texte souhaité.
Comment tester qu’une requête est bien terminée ?
- cy.server() lance un serveur afin d’écouter les requêtes.
- cy.route() permet de déclarer les différentes routes que l’on souhaite surveiller pendant nos tests. On peut y indiquer trois paramètres : la méthode (‘GET’, ‘POST’…), l’URL, et éventuellement la réponse forcée.
- .as() permet de créer un alias pour la route, afin de pouvoir y référer facilement au cours des tests.
- cy.wait() indique à Cypress qu’il est nécessaire d’attendre cette requête avant de passer à la suite des tests.
Comment remplir un formulaire ?
- .type() permet de renseigner un champ
- Si nous souhaitions effacer la valeur actuelle du champ, nous pourrions utiliser la commande .clear()
- Dans le cas d’un élément select, nous pourrions sélectionner une option grâce à la commande .select(option).
Quelques astuces
Comment créer des variables personnalisées ?
On peut ajouter ses propres variables dans le fichier de configuration cypress.json. Il suffit de les ajouter dans la partie « env ».
Ces variables sont ensuite accessibles dans les fichiers de tests via la commande Cypress.env(‘nom_de_la_variable’).
Comment retourner des « fausses données » (stubbing) sur une requête ?
Afin de maîtriser les données reçues dans l’application, il est possible de créer des « fixtures ». Ces fixtures contiennent les données que nous souhaitons recevoir pendant nos tests.
Pour cela, nous devons créer un fichier de données à placer dans le dossier /fixtures, par exemple une liste d’utilisateurs : « users.json ».
On peut ensuite faire appel à ces données lors de la déclaration de la route souhaitée.
Interface Cypress
L’interface de Cypress, illustrée ci-dessous, permet de consulter le déroulement de chaque test.
Il est possible de cliquer sur chaque action et consulter l’état de l’application à ce moment du test.
A bon testeur, salut
Références :
#Cypressio #E2E
https://www.cypress.io/how-it-works, pour une vue synthétique de l’architecture de cypress
https://docs.cypress.io/guides/getting-started/writing-your-first-test.html, un guide pour écrire son premier test.
Vidéo officielle de présentation : https://vimeo.com/237527670
Dossier GitHub contenant les exemples de cet article : https://github.com/estellepicq/cypress_samples
1 comments on Pourquoi est-on passé de Selenium à Cypress ?