Participer au site avec un Tip
Rechercher
 

Améliorations / Corrections

Vous avez des améliorations (ou des corrections) à proposer pour ce document : je vous remerçie par avance de m'en faire part, cela m'aide à améliorer le site.

Emplacement :

Description des améliorations :

Pourquoi développer des tests unitaires ?

Mise en oeuvre de Doclets JUnit 3.x



Accès rapide :
Pourquoi tester une application ?
Quels sont les différents types de tests ?
Quel est le SUT dans le cadre des tests unitaires ?
Quelques frameworks de tests unitaires
Le framework JUnit
Le framework Mockito
Le framework TestNG

Pourquoi tester une application ?

Au fur et à mesure des années, les applications développées sont de plus en plus conséquentes. Le volume de code à produire suit donc cette accélération. De plus, une application doit être maintenue pour corriger les bugs et surtout pour y ajouter de nouvelles fonctionnalités. Il en résulte que le code source de cette application doit être maintenable.

Pour répondre à ce besoin de maintenabilité, l'approche objet aide beaucoup, mais ce n'est pas suffisant. Effectivement, à chaque livraison d'une nouvelle version, il faut vérifier que les nouvelles fonctionnalités s'exécutent bien correctement. Mais il faut aussi vérifier que ce qui marchait bien précédemment (sur les versions précédentes), continue à bien fonctionner sur la version courante. Il ne faut pas, en cas de régression (de dysfonctionnement d'une fonctionnalité précédemment développée), que ce soit l'utilisateur qui constate le problème. Il est donc nécessaire, à chaque nouvelle livraison de l'application, de vérifier que l'intégralité des fonctionnalités précédentes continue à correctement s'exécuter. Il est nécessaire de pouvoir relancer ces tests : il faut donc que vous conserviez le code des tests entre les versions pour pouvoir les rejouer.

Le seul moyen de garantir la non régression passe par l'automatisation de l'exécution des procédures de tests (des scénarios de tests si vous préférez). Pour facilité ce point, vous pouvez opter pour l'utilisation d'un « Test Runner » (JUnit en est un).

Quels sont les différents types de tests ?

Si l'on rentre dans la théorie des tests, il existe différents niveaux de tests : chacun de ses niveaux est associé à une procédure de tests devant exécuter un grand nombre de tests. D'une procédure de tests à une autre, ce qui change c'est le SUT (System/Software Under Test), nous allons y revenir.

Traditionnellement, on identifie quatre strates de tests (quatre couches).

Outre cette classification des procédures de tests, on peut aussi classer les tests en fonction de leur nature.

Pour chacune des quatre de procédures de tests vu précédemment (tests unitaires, d'intégration, de validation et de qualification) on peut considérer avoir un ensemble de tests fonctionnels et d'autres plus techniques.

même au niveau d'un test unitaire, il peut être important de vérifier qu'un composant logiciel ne consomme pas toutes les ressources disponibles via des tests techniques (par exemple, le CPU). Ainsi, après intégration, on sera certains que tous les composants déployés pourront avoir suffisamment de ressources disponible. Par exemple, un test technique sur composant logiciel pourrait être : « vérifier que le composant ne consomme pas plus de 30% de CPU ». Un autre test pourrait être : « vérifier que le composant ne consomme pas plus de 200 Mo de mémoire ».

Notez encore qu'on peut classer les tests selon un autre axe :

Pour clore ces définitions, rappelez-vous qu'un test :

A partir de maintenant, nous n'allons nous intéresser uniquement qu'à la notion de tests unitaires. Les autres types de tests ne seront pas appréhendés dans ce tutoriel.

Quel est le SUT dans le cadre des tests unitaires ?

Contrairement à une idée reçue, un test unitaire ne porte pas systématiquement sur une classe (bien que cela puisse être le cas). Comme nous l'avons dit précédemment, l'unité en test est normalement un composant logiciel : en ingénierie logicielle, un composant logiciel est un élément constitutif d'un logiciel. Il est développé indépendamment des autres composants. Tous les composants sont ensuite intégrés ensemble pour constituer le logiciel.

En UML (Unified Modeling Language), un formalisme particulier est proposé pour définir un diagramme de composants. Un composant y est représenté par un rectangle complété par deux petits rectangles sur son côté gauche. Imaginons que nous cherchions à développer un site de vente en ligne : le diagramme de composants UML suivant montre comment nous pourrions architecturer le logiciel. On y constate que les composants sont couplés par interfaces (les ronds) qui constituent les différentes API (Application Programming Interface) de chaque composant.

Exemple de diagramme de composants en UML
les traits pleins entre un composant et une interface correspondent à une implémentation du contrat (de l'interface) par un composant. Les flèches en pointillées correspondent à des relations de dépendances sur une API (un composant à besoin d'un autre pour son fonctionnement).
il doit être clair qu'un composant n'est pas forcément une unique classe. En termes de Java, un composant serait plus proche de la notion de package : ce package pourrait contenir plusieurs classes et représenter plusieurs milliers de lignes de code. En termes de déploiement, un composant pourrait être associé à un JAR (une archive Java).

Ainsi, le composant de gestion des commandes (CommandComponent) a besoin du composant de sécurité et du composant de gestion du stock pour pouvoir fonctionner. Si l'on souhaite tester uniquement le composant de gestion de commandes, il faudrait donc simuler les autres composants : cela sera possible, car le couplage entre composants est réalisé par interface. On pourra donc aisément simuler un stock en implémentation un mock à partir de l'interface associée et en signalant, par exemple, que les articles d'une commande sont systématiquement disponibles (peut-être un simple return true; dans le code du mock).

le terme de mock est basé sur le mot anglais « mockery » qui peut être traduit en moquerie ou bien farce. On peut parler de métaphore : on fait une farce au composant logiciel en lui faisant croire qu'il s'exécute dans la vraie vie alors qu'il tourne en environnement simulé.

Dans un tel développement, il faudrait donc quatre jeux de tests unitaires : un jeu par composant. Pour un jeu de tests donné, le SUT serait donc le composant considéré. Si les quatre jeux de tests s'exécutent correctement pour chaque composant, on peut alors intégrer ces composants ensemble et procéder à l'exécution de la procédure de tests d'intégration puis poursuivre.

Quelques frameworks de tests unitaires

En Java, il existe plusieurs frameworks de test unitaires. Loin d'être exhaustif, voici quelques frameworks que vous pourrez rencontrer au gré des projets sur lesquels vous pourrez intervenir.

Le framework JUnit

JUnit est certainement le framework de test plus utilisé, ce qui explique que dans la suite de ce cours, nous allons l'utiliser. Historiquement parlant, il y a eut plusieurs versions de JUnit et nous retiendrons les versions JUnit 3.x, JUnit 4.x et JUnit 5.x. Entre ces trois versions, il y a eut rupture de compatibilité : la mise en oeuvre de tests unitaires se fait différemment en fonction de la version utilisée. Comme ces trois versions sont encore beaucoup utilisées au gré des divers projets existants, je vais vous présenter les trois approches dans les chapitres suivants.

bien entendu, si vous êtes nouveau venus dans l'univers Java et si vous n'avez pas d'antériorité en termes de version du JUnit utilisée, je vous propose de passer directement à l'étude de JUnit 5.x. Les autres versions sont présentés pour ceux qui sont obligés de travailler avec une version précédente du logiciel.
Le logiciel peut être téléchargé à l'adresse suivante : https://junit.org/. Mais la grande notoriété de JUnit fait qu'il est déployé, par défaut, dans tous les IDE Java majeurs. Par exemple, si vous utilisez Eclipse, vous n'avez pas besoin de le télécharger, il est déjà là prêt à être utilisé.

Le framework Mockito

Un autre framework de test orienté « Tests Unitaires ». Comme son nom le laisse suggérer, le logiciel propose des outils de génération de bouchons (de mocks).

Le logiciel peut être téléchargé à l'adresse suivante : https://site.mockito.org/.

Le framework TestNG

Le nom TestNG signifiant « Test Next Generation », il s'agit d'un autre « Test Runner » s'inspirant fortement de JUnit et de NUnit. Contrairement à JUnit, TestNG n'est pas orienté que « tests unitaires » et permet de plus facilement prendre en charge les autres types de tests (tests d'intégration, tests de validation et tests de qualification).
Le logiciel peut être téléchargé à l'adresse suivante : https://testng.org/.


Mise en oeuvre de Doclets JUnit 3.x