Parce qu’il est de plus en plus important d’assurer la qualité d’une application web, la mise en place de tests fonctionnels automatisés devient primordial. Nous tenterons d’établir une introduction à ces pratiques en montrant quelques exemples.
Pourquoi faire des tests fonctionnels ?
Qu’est-ce qu’un test fonctionnel ?
Un test fonctionnel permet de tester une fonctionnalité (la connexion d’un utilisateur par exemple). Il ne teste pas le rendu en tant que tel même si ces notions peuvent se croiser. Ces fonctionnalités sont testées via des parcours en simulant les actions de l’utilisateur (clics, saisies claviers, mouvement de souris, …).
Les tests fonctionnels sont faits tout au long de la vie du projet, et ce dès le développement de la première fonctionnalité.
Pourquoi en faire et pourquoi les automatiser ?
Les tests fonctionnels sont faits pour s’assurer que le service que l’on souhaite mettre à disposition de l’utilisateur fonctionnera quand celui-ci l’utilisera.
Les tests manuels sont chronophages, laborieux et répétitifs. Les automatiser fait gagner du temps aux testeurs qui délèguent l’exécution des tests principaux.
De plus on refait rarement tous les tests à chaque recette. Ce qui signifie que certaines fonctionnalités ne sont pas testées. Le risque de régression est ainsi augmenté. Les automatiser permet de garantir une couverture constante des fonctionnalités.
Quand les faire ?
Hormis sur des projets statiques, la nécessité de tests fonctionnels automatisés augmente exponentiellement avec la complexité du projet. Les tests automatisés ne font pas perdre de temps, au contraire ils en font gagner, car une fois écrits, les tests peuvent être rejoués à volonté sans prendre du temps supplémentaire aux testeurs, cela dépend de la solution mise en place (voir ci-dessous). Le rôle du testeur, en plus de l’écriture des tests, devient alors plus de comprendre d’où vient le bug / la régression rencontré(e) et de les retranscrire aux développeurs, plutôt que de les chercher. Le testeur doit alors avoir une meilleure compréhension du fonctionnel et de la technique de l’application afin d’accomplir sa mission.
Si vous avez un projet sans test, la première étape est de déterminer quels sont les parcours client les plus critiques du projet.
A partir de ces parcours, il faut déterminer quelles sont les fonctionnalités impactées. Deux approches complémentaires peuvent alors prendre place :
- Tester les parcours de bout en bout. Cela permettra de vérifier le parcours nominal de l’utilisateur sans sortir d’un cadre défini.
- Tester les fonctionnalités de façon isolée. Les différents cas des fonctionnalités sont alors testés mais les impacts possibles sur d’autres fonctionnalités (ex : ajout au panier d’un produit et checkout) ne sont pas testés ici.
L’approche « parcours » permet d’aller plus vite et de faire le lien entre les différentes fonctionnalités. Elle a par contre un niveau de détail moins approfondi.
Comment faire ?
Quand vous renseignez sur les tests automatisés, le mot qui revient le plus souvent est Selenium. Le problème est que ce mot veut dire beaucoup de choses. C’est à la fois un enregistreur / ‘player’ de tests sur Firefox, un serveur de test, un driver de navigateur, un pilote de serveur de test, …. Il devient difficile de s’y retrouver.
Avant de se plonger plus précisément dans certaines des méthodes de tests fonctionnels, voici les différents familles et éléments à comprendre :
- L’enregistreur de test : Il permet d’enregistrer les actions faites dans l’application. Il permet de créer des scénarios de tests rapidement, mais demande généralement d’être complété pour avoir une couverture satisfaisante.
- Les ‘players’ de test permettent de jouer les tests. Il existe deux grands types de ‘player’,
- Les locaux, ils tournent sur la machine de l’utilisateur et bloquent (au moins partiellement) l’utilisateur (Ex : Selenium IDE, TestComplete, Katalon, Ranorex).
- Les serveurs, ils tournent sur une machine liée ou non au projet. Ils sont plus performants, ne bloquent pas l’utilisateur et peuvent s’intégrer dans un workflow de développement (Ex : Selenium webdriver, IBM rational functional tester, …). Les actions sont les différentes commandes qui seront jouées dans un test. Cela va du clic, à la gestion de variable, à la vérification d’attribut.
- Les frameworks sont des outils d’écriture de tests. Il en existe dans de nombreux langages. Ils ont différentes approches, allant du très technique au plus littéraire (Ex : Nightwatch (JS), Behat (PHP), CodeCeption (PHP), jBehave (java), Specflow (c#))
- Les drivers sont les connecteurs entre le ‘player’ de test et les navigateurs. Sur les ‘players’ locaux, ils sont généralement intégrés, mais dans le cadre de Selenium webdriver (le serveur de tests le plus répandu) ils sont à installer indépendamment.
Où commencer ?
Les actions décrites dans ce tableau permettent d’ouvrir la page d’accueil française du site de Clever Age. Dans cette page, le test va vérifier le titre de la page, la présence du logo, des entêtes du menu, que la classe ‘menu-item_in-1’ soit bien présente sur le texte entre le menu et le pictogramme ‘cart’. Il va passer en variable le nom de la classe associée au bouton de recherche et créer une condition vérifiant le nom de la classe.
Ce test est une introduction aux possibilités de tests qu’offrent une solution simple comme Selenium IDE.
Les tests peuvent bien sûr aller plus loin et valider des parcours complexes. De plus ils peuvent être exportés pour être joués par Selenium Remote Control sur un serveur afin d’automatiser leur exécution.
Toutefois ces tests restent limités dans leurs capacités et peuvent pour certaines actions être compliqués à écrire. De plus, ils sont relativement longs à jouer comparés à d’autres solutions tel que Selenium Webdriver.
Comment industrialiser ?
Les tests fonctionnels sont le mieux utilisés lorsqu’ils font partie du workflow de développement. Dans ce cadre, ils sont joués pour valider le déploiement du code sur les différentes instances.
Exemple de workflow :
Pour ce faire, de nombreuses méthodes existent (Behat, jBehave, Specflow, ….) , dans cet article nous en survolerons 2 : Nightwatch et Codeception.
Nightwatch
Nightwatch est un framework de tests de bout en bout. Les tests sont écrits en JavaScript et jouer via node JS qui appelle le serveur Selenium webdriver.
Pour un test similaire à celui fait plus haut, voici le code nécessaire :
Les tests sont lancés par une commande node JS, soit automatiquement, car à un lanceur de tâches (Jenkins par exemple) soit manuellement en ligne de commande.
folder> ./node_modules/.bin/nightwatch -c node_modules/.bin/nightwatch.conf.js
À travers nightwatch et de nombreux autres framework il est possible de jouer les tests via des solutions externes (EX : BrowserStack, SauceLabs). Cela offre de nombreuses combinaisons navigateurs/OS et permet de jouer les tests sur mobile sans effort supplémentaire. De plus, cela retire l’entretien des OS, navigateurs, VMs sur lesquels sont joués les tests.
CodeCeption
Certains frameworks de tests tels que CodeCeption permettent de faire des choses différentes. Tels que de vérifier des données en base, d’appeler des APIs ou de faire des tests unitaires.
CodeCeption est toutefois un peu moins avancé sur des fonctionnalités de tests fonctionnels que Nightwatch par exemple.
Pour le même scénario de tests que plus haut voilà le code Nightwatch correspondant :
Pour lancer les tests, il faudra lancer la commande suivante (ou laisser Jenkins s’en charger).php .codecept.phar run --steps --env chrome
Conclusion
La complexité de la mise en place de tests fonctionnels automatisés est plus basée sur les éléments externes (intégration continue, contrôle des données, branchement à l’infrastructure, aux sources externes (API, BDD, …)) que les tests en eux même. De plus, malgré un coût d’entrée certain, ils permettent de faire gagner du temps et de la qualité dès les premières exécutions en s’assurant que les fonctionnalités clés de l’application (et les autres) sont fonctionnelles.