NightWatchJS pour tester vos évènements Google Analytics
Chez MeilleursAgents, l’un des gros chantiers de l’année a été la mise en place de tests fonctionnels pour augmenter la qualité de nos produits mais également nous permettre d’accélérer notre vitesse d’innovation. Par ailleurs, nous avons beaucoup investi dans la mesure, à l’aide, notamment, de Google Analytics.
Vous pourrez apprendre en lisant cet article comment implémenter un environnement de test fonctionnels avec NightWatchJS. Docker nous servira pour contenir le serveur Selenium de test, ainsi l’utiliser facilement sans installer Java ni Selenium Server sur la machine. Le code complet de l’application est disponible sur Github.
Le site demo (présent dans le dossier testing-website
) qui sera testé est disponible ici.
Tout n’est pas détaillé sur cet article, n’hésitez à parcourir le code.
Pour le tutorial, l’application de démo se concentre uniquement de tester les envois à Google Analytics. Elle permet de valider en permanence que le plan de tagging est toujours fonctionnel, chose importante quand les décisions produit se basent sur ces chiffres.
Prérequis :
Le projet a été testé sous Mac OSX mais devrait fonctionner sur un Windows ou Linux.
Préparation des dépendances
npm install
NPM va installer 2 dépendances : nightwatch
et better-npm-run
. Cette dernière nous sert juste à injecter facilement les variables d’environnement dans l’application.
Selenium
Docker nous permet d’abstraire le serveur Selenium. La commande docker-compose -p selenium up -d
permet de démarrer le serveur. Vous pouvez le vérifier en lançant un navigateur sur l’URL http://localhost:4444/grid/console
.
L’image Docker contient deux instances de navigateur : Chrome et Firefox. Dans notre exemple, nous n’utiliserons que Chrome.
Pendant l’exécution des tests vous pouvez voir ce qu’il se passe en utilisant VNC (ou Partage d’écran sous Mac). Simplement avec un lien vnc://localhost:secret@localhost:5900, vous pourrez accéder à l’interface de la machine. Voici deux alias pratiques pour accédez aux 2 navigateurs:
selenium-chrome='open vnc://localhost:secret@localhost:5900'
selenium-firefox='open vnc://localhost:secret@localhost:5901'
Enfin, il ne reste plus qu’à lancer npm test
pour exécuter la suite de tests et voir la sortie suivante si tout va bien :
Vous pouvez aussi spécifier une suite et/ou un test avec la commande
npm test -- --test tests/HomeTest.js --testcase "'click on contact button'"
Travailler avec NightWatchJS
Configuration
Tout se passe dans le fichier nightwatch.config.js
. Je ne vais pas rentrer dans le détail ici, si vous voulez en savoir plus, le fichier du projet est assez commenté pour mieux comprendre le comportement de chaque option.
PageObjects
Une bonne pratique recommandée par les développeurs de Selenium est d’utiliser des PageObjects. Ce sont des objets qui vont décrire la page sur laquelle on veut interagir. Dans NighWatchJS, les pages sont automatiquement chargées dans l’application pour chaque fichier ajouté dans le dossier pages
(défini dans la configuration). Le nom du fichier servira au nom de la propriété de browser.page
dans le code.
Exemple dans l’application : pour un fichier pages/HomePage.js
le PageObject est instanciable via browser.page.HomePage().
Dans la page, j’ai spécifié 2 éléments internes à la page d’accueil : les 2 boutons sur lesquels je vais simuler des clics.
Pour simuler un clic sur le bouton ‘Purchase’ puis le bouton ‘Contact us’ :
const Home = browser.page.HomePage();
Home.click('@purchaseCta');
Home.click('@contacUsCta');
Note : Petit avertissement sur la méthode click
. Le clic sur un élément ne peut se faire que sur un élément réellement visible. Si l’élément est seulement présent dans le DOM, cela ne fonctionnera pas. Il vaut donc mieux vérifier qu’il l’est avant :
Home.waitForElementVisible('@purchaseCta', 5000, true);
Si vous testez en mobile et desktop, cela peut devenir un enfer selon la complexité de vos media queries. N’hésitez pas alors à créer des scénarios différents.
Le pattern PageObjects peut paraître complexe au départ mais cela permet de rendre le code des tests plus lisible et de maintenir un référentiel exhaustif des éléments testés à un seul endroit et donc de faciliter les éventuels changements.
Custom assertions et command
Une autre fonctionnalité de NightWatchJS qui simplifiera l’écriture de tests est la possibilité d’étendre l’API avec l’ajout de commandes et d’assertions personnalisées. Une commande permet de communiquer avec le navigateur, soit pour lui envoyer des instructions, soit pour récupérer des informations. Une assertion est la même notion que dans n’importe quel outil de test.
Comme pour les PageObjects, pour ajouter une commande ou assertion personnalisée, il suffit de créer un fichier dans le dossier approprié (et défini dans la configuration). Le nom du fichier servira donc à la création d’une propriété sur browser.assert
ou browser.verify
pour les assertions. Les commandes seront définies directement sur l’objet browser
.
Sa création est assez simple (exemple). Pour définir une commande, il faut exporter une méthode command
dans votre fichier :
- Toujours retourner
browser
pour permettre le chaînage. - Il est important de toujours appeler le callback au risque de faire quitter l’application de manière inattendue. C’est le cas d’utilisation de la fonction
noop
dans le cas où on ne veut rien faire (condition non respectée).
Une assertion est plus complexe mais le principe est le même. Il faut exporter une fonction assertion
qui doit implémenter 4 membres (exemple) :
expected
Représente la valeur attenduevalue
Fonction qui va retourner la valeur utilisée dans l’assertion à comparer avecexpected
pass
Fonction qui exécute le test de l’assertion, doit retourner un boolean.command
Commande qui va être exécutée pour récupérer la valeur à tester. Le callback de cette fonction sera utilisé en argument devalue
Vous pourrez trouver d’autres exemples d’assertions et commandes:
- https://github.com/mobify/nightwatch-commands/tree/develop/commands
- https://github.com/mobify/nightwatch-commands/tree/develop/assertions
- https://github.com/maxgalbu/nightwatch-custom-commands-assertions/
- https://github.com/yyx990803/nightwatch-helpers
Dans le projet, j’ai créé une assertion pour vérifier qu’un évènement Google Analytics est bien envoyé après une action quelconque. La commande de cette assertion va scruter le localStorage
pour trouver les entrées préalablement remplies par une action (un clic sur un bouton par ex.). L’assertion va de pair avec la commande qui va injecter un script dans la page pour remplacer la fonction ga()
par défaut de Google Analytics. C’est cette fonction qui va remplir le localStorage
avec tous les évènement envoyés.
Note : Vous remarquerez que l’assertion est vraie si on n’est pas sur Chrome. Nous testons notre plan de tagging sur Chrome uniquement, pour éviter un temps d’exécution total trop long.
Problèmes
Parmi les problèmes inhérents au développement sur plusieurs navigateurs, voici une liste de ceux les plus frustrants auxquels nous avons été confrontés :
- Remplir un champ texte déjà pré-rempli : Selon les navigateurs la méthode
browser.setValue()
ne remplit pas le champ. Dans Firefox par exemple, le texte va être ajouté au texte existant. - La méthode
browser.maximizeWindow()
ne fonctionne pas sous MacOS (sous BrowserStack)
Aller plus loin
- Il est assez simple de brancher BrowserStack avec NightWatchJS pour tester beaucoup plus de navigateurs.
- Pour de l’intégration continue avec Jenkins, un
Dockerfile
d’exemple est disponible dans l’app. - Test de non-regression visuelle avec ResembleJS (sera l’objet d’un prochain article)
NightWatchJS est donc un outil formidable pour implémenter vos tests fonctionnels. Mais la route est longue avant d’avoir un environnement de test complet et stable pour tous les navigateurs. Si vous avez déjà intégré des pages web compatibles pour tous les navigateurs, vous devinez que vous devrez faire face à des problèmes équivalents lors de l’écriture de tests fonctionnels. Certains navigateurs sont plus capricieux que d’autres, il y a toujours des petites surprises insoupçonnées.
Il vous faudra ensuite penser à la maintenabilité des scénarios testés ainsi qu’à leur temps d’exécution (notamment sur BrowserStack).
Vous souhaitez rejoindre une équipe qui met en place les meilleures pratiques de qualité de code, de tests et d’intégration continue ? Nous recrutons !