Comment fonctionnent les tests Elixir ?
by Alexandre Dedourges, DevSec
Quand vous développez une application, des logiciels ou d’autres outils, il est nécessaire d’effectuer des tests. Les tests sont très utiles et pratiques pour s’assurer que votre application aura le fonctionnement attendu. Si certains cas de figure ou erreur ne sont pas géré, cela pourrait mener à des crashs, des bugs (bogues) ou encore à des attaques sur vos applications. Ce qui pourrait avoir d'énormes répercussions, voire des conséquences désastreuses. Les développeurs Elixir ne sont pas exempts de cette phase de test. Néanmoins certains outils Elixir facilitent la création et l’exécution de tests.
Les tests, une partie intégrante et importante du développement
Il est assez fréquent que les tests soient négligés. En effet, les phases de tests représentent pour les développeurs un coût en temps et donc un coût financier pour les entreprises. Dès lors, les équipes de développement seront alors tentées de favoriser le développement de leur produit, la quantité contre la qualité. Or les tests sont vraiment très importants quand l’on veut avoir l’application la plus qualitative possible. En effet, il est recommandé de consacrer environ 30 % du temps de développement aux testings des différentes fonctions de l’app. Ce qui n’est pas toujours le cas. C’est dans ce contexte que des fonctionnalités de testings ont été développées sur Elixir. Celles-ci ont pour but de faciliter et de favoriser la mise en place de test. Ceci afin d’aider les développeurs dans les phases de tests de leurs produits en leur fournissant de nombreux outils. La phase de tests qui s’avère bien souvent longue et fastidieuse devient alors plus agréable. Toutes ces fonctionnalités de testings sont implémentées dans le framework ExUnit d’Elixir. Celui-ci ne fait pas partie du cœur d’Elixir, mais est un outil supplémentaire fourni par le langage. Il ne nécessite donc aucune installation et permet de réaliser des tests unitaires.
Les tests unitaires, des tests parmi les tests.
Quand on vient à parler de tests, plusieurs types de tests différents peuvent être évoqués. Néanmoins quand il s’agit du développement d’une application, les types de test les plus communs et utilisés par les développeurs sont les tests unitaires. Les tests unitaires sont essentiels afin de s’assurer que les différentes parties/portions du code fonctionnent correctement. On peut par exemple imaginer tester une fonction en particulier (d’où le « unitaires »), etc.
De plus en plus de codes sont voués à évoluer au fur et à mesure des versions de langage, des mises à jour ou de l’ajout de fonctionnalités… Ces changements peuvent provoquer des comportements non désirés de la part de votre application. C’est pourquoi les tests unitaires sont très pratiques. En effet, ils vous permettront de vous rendre rapidement compte de potentiels problèmes, par exemple si une fonction ne remplit pas son rôle correctement.
D’autre part, les tests unitaires sont utiles pour suivre les bonnes pratiques de l'ingénierie logicielle comme le TDD (Test Driven Development). Le TDD consiste à créer un test. Dans un premier temps, celui-ci ne fonctionnera pas. Dans un second temps il faudra développer la fonctionnalité désirée jusqu’à ce que le test soit passé. Ce qui voudra dire que votre fonction a bien le résultat attendu. Ensuite, retravailler la fonction pour éviter un code trop lourd. Enfin, réécrire un test pour améliorer les fonctionnalités et recommencer les étapes précédentes jusqu’à ce que la fonctionnalité soit satisfaisante.
Les tests unitaires sont à la base de tous les autres tests. C’est pourquoi ils sont situés à la base de la pyramide des tests.
Les tests unitaires permettent donc de tester chaque fonctionnalité individuellement afin d’en assurer son bon fonctionnement et de s’assurer que les différents cas de figure qu’il pourrait être nécessaire de traiter seront bien pris en compte. C’est donc ce que va nous permettre de mettre en place le framework intégré à Elixir : ExUnit.
ExUnit, les tests unitaires version Elixir
ExUnit va vous permettre de tester les différentes parties de votre code. Bien que celui-ci ne soit pas intégré directement à Elixir, il est quand même utilisable sans aucune installation préalable. Le fait qu’il soit développé par les équipes d’Elixir est un gros plus, car cela en fait un outil abouti et parfaitement adapté aux tests unitaires en Elixir.
Voyons comment celui-ci fonctionne à travers un exemple. Nous allons créer une application Elixir, créer des fonctions et les tester. Si vous n’avez jamais utilisé Elixir, il est conseillé d’en apprendre les bases en utilisant par exemple la documentation en ligne.
Nous allons donc commencer par créer une application en utilisant la commande :
Puis nous allons ouvrir notre fichier « lib/my_test_app.ex » dans ce fichier vous devriez trouvez une fonction « hello » nous allons supprimer celle-ci et en créer trois nouvelles afin de comparer des valeurs. Une fonction « higher » qui va renvoyer « true » (vrai) si la valeur 1 est supérieure à la valeur 2 et « false » (faux) dans le cas contraire, une fonction « lower » qui va faire l’inverse et enfin une fonction « equal » (égale) qui va renvoyer vrai si les valeurs sont identiques ou faux dans le cas contraire.
Vous devriez alors avoir ce code :
Comme vous pouvez le voir, ces trois fonctions sont censées comparer deux valeurs, pourtant aucune de celles-ci n’est écrite de la même manière et elles sont toutes les trois correctes ! La dernière méthode est la meilleure façon de faire, car c’est celle qui requiert le moins de code et qui est la moins complexe.
Nous allons maintenant pouvoir passer au test de ces trois fonctions. Rendons-nous à l’emplacement suivant « test/my_test_app_test.exs ». C'est à partir de ce fichier que nous allons pouvoir tester les fonctions que nous avons écrites dans notre fichier « lib/my_test_app.ex ».
Un test est déjà présent dans ce fichier, mais ne fonctionnera pas car nous avons supprimé la fonction « hello ». Ce test est donc inutile et peut être supprimé.
Après avoir rédigé les tests les plus évidents, vous pourriez avoir quelque chose ressemblant à ceci :
Alors comment ça fonctionne ? C’est ce que nous allons expliquer dans la prochaine partie.
Le module de test en Elixir
Comme vous pouvez le voir, la première étape consiste à indiquer au module que l’on souhaite utiliser ExUnit.Case. Cette ligne de code va tout simplement servir à importer le framework de test ExUnit.
Ensuite il est recommandé d’importer le module contenant nos fonctions précédentes. Cela nous permettra d’appeler directement nos fonctions sans avoir à écrire <NomDuModule>.<Fonction>
.
On peut maintenant passer à la partie qui nous intéresse : les tests !
Comme vous pouvez le voir sur la copie d’écran précédente, il est nécessaire de d’abord déclarer le test en tapant tout simplement le mot « test » suivi d’une chaîne de caractères. Celle-ci va permettre de décrire le test. Il est bien souvent recommandé d’indiquer quelle fonction nous voulons tester, suivi d’une petite description du test que nous voulons effectuer. Dans la copie d’écran précédente, on comprend donc grâce aux descriptions quelle fonction nous voulons tester (higher, lower, equal) suivi de leurs arités. L’arité d’une fonction étant le nombre d’argument(s) qu’elle se verra passer en paramètre. En effet, préciser l’arité d’une fonction en Elixir est important. Une fonction peut avoir un comportement différent en fonction de son nombre d’arguments. De plus, ces descriptions nous renseignent sur le résultat attendu. On comprend donc que dans le premier test nous voulons vérifier que la fonction « higher » renvoie bien « true » quand la première valeur passée en paramètre est plus grande que la deuxième. Les deuxième et troisième tests doivent nous permettre de vérifier que la fonction « higher » renvoie « false ». En effet, la fonction doit renvoyer « false » lorsque le premier paramètre est plus petit (deuxième test) ou égale (troisième test) au deuxième paramètre. Les tests suivants fonctionnent sur le même principe mais avec des résultats attendus différents.
Nous venons donc de décrire le test que nous voulons effectuer. Voyons maintenant comment réaliser ce test. Pour cela il va falloir se placer entre en « do » et le « end » de notre test. La plupart du temps nous allons utiliser les assertions pour vérifier le comportement de notre code. Une assertion est ce que nous supposons qu’il va se passer. Pour écrire une assertion, il faudra alors commencer par utiliser la macro « assert », suivi de la fonction que nous voulons tester, d’un comparateur et du résultat attendu. Notre premier test ressemblera donc à ceci :
Ici on suppose que la fonction « higher » avec en paramètre une valeur 1 supérieure à la valeur 2 va renvoyer exactement « true ». Le même principe s’applique sur tous les autres tests. Bien que la macro « assert » soit la plus utilisée, d'autres macros peuvent être utilisées. Par exemple, la macro « refute » qui a le comportement inverse du « assert ». La liste peut être consultée sur la documentation officielle.
Le testing pour une application robuste
En d’autres termes, le testing est une partie importante du développement d’une application. Il permet d’avoir une application robuste, mais aussi plus optimisée. Le testing permet d’éviter les problèmes liés à des cas non prévus. Il permet aussi d’éviter les attaques sur le système en fermant les portes d’entrée à des individus malveillants. Ce sont pour ces raisons que le testing ne doit pas être négligé. ExUnit est donc un outil très intéressant d’Elixir puisqu’il permet de réaliser facilement et efficacement des tests unitaires. Ce qui permet de rendre cette expérience plus conviviale pour les utilisateurs ne désirant pas passer du temps dans des tests compliqués et difficiles à mettre en œuvre. Chez Cryptr nous passons du temps sur le testing de nos applications pour en garantir un fonctionnement optimal !
Alors prêt à en apprendre plus sur Elixir et les produits que nous avons développés avec celui-ci ? On vous en dit plus chez Cryptr.
Add enterprise SSO for free
Cryptr simplifies user management for your business: quick setup, guaranteed security, and multiple free features. With robust authentication and easy, fast configuration, we meet businesses' security needs hassle-free.