Série 1 – Test unitaire

Introduction

Le but de cette série est de vous exercer à écrire des tests unitaires, en en écrivant pour une classe que nous vous fournissons et qui contient quelques erreurs.

Avant d'aller plus loin, créez un nouveau projet Java dans Eclipse pour cette série. Cela fait, créez un paquetage nommé ch.epfl.ppo dans lequel vous placerez toutes vos classes. Notez en particulier que les classes que nous mettons à votre disposition font partie de ce paquetage.

La classe que vous devrez tester — et corriger par la suite — met en œuvre une queue bornée d'entiers. Pour mémoire, une queue est une liste dans laquelle les éléments sont toujours ajoutés à une extrémité, et retirés de l'autre extrémité.

Une queue est dite bornée lorsque le nombre d'éléments qu'elle peut contenir est limité. On appelle le nombre maximum d'éléments qu'une queue bornée peut contenir sa capacité. Une queue qui ne contient aucun élément est dite vide, tandis qu'une queue (bornée) qui en contient autant que sa capacité le permet est dite pleine. Notez que, d'après ces définitions, une queue de capacité 0 est à la fois vide et pleine.

Pour illustrer ces notions au moyen d'un exemple, imaginons que l'on crée une queue bornée d'entiers d'une capacité de 5 éléments. Initialement, cette queue est vide, ce qu'on peut représenter ainsi, les points d'interrogation représentant la capacité non utilisée de la queue :

? ? ? ? ?

Ensuite, admettons que l'on ajoute l'entier 2015 à la queue. Elle ressemble alors à ceci — si l'on fait l'hypothèse que les éléments sont ajoutés depuis la droite et supprimés depuis la gauche :

2015 ? ? ? ?

Ajoutons ensuite l'entier 12. On obtient alors la queue suivante :

2015 12 ? ? ?

Finalement, ajoutons les entiers 1, 2 et 3, dans cet ordre. La queue est maintenant pleine, et ressemble à ceci :

2015 12 1 2 3

Si on retire maintenant un élément de cette queue, on retire celui qui se trouve à gauche. On obtient alors l'entier 2015, et la queue n'est maintenant plus pleine, puisqu'on pourrait lui ajouter un nouvel entier.

12 1 2 3 ?

Si l'on ajoute maintenant un dernier entier, disons 50, la queue ressemble à ceci :

12 1 2 3 50

Exercice 1

Les différentes mises en œuvre des queues d'entiers bornées avec lesquelles vous travaillerez pour cette série implémentent toutes l'interface BoundedIntQueue.java du paquetage ch.epfl.ppo que nous vous fournissons et que vous devez télécharger et intégrer à votre projet. Les commentaires JavaDoc attachés aux méthodes de cette interface spécifient leur comportement.

En plus de cette interface, nous vous fournissons une classe nommée BoundedIntQueueBuggy, toujours dans le paquetage ch.epfl.ppo, qui implémente BoundedIntQueue mais qui a quelques problèmes. Le but de ce premier exercice est de détecter ces problèmes au moyen de tests unitaires, sans regarder le code de la classe, ce qu'on appelle généralement test en boîte noire (black box testing en anglais). Pour cette raison, nous vous fournissons uniquement un fichier JAR, c-à-d une archive contenant la version compilée de la classe à tester. Pour l'ajouter à votre projet, procédez ainsi :

  1. téléchargez le fichier BoundedIntQueueBuggy.jar,
  2. ouvrez les propriétés de votre projet (menu Project puis Properties), et sélectionnez Java Build Path,
  3. activez l'onglet Libraries puis cliquez sur Add External JARs…,
  4. dans la fenêtre qui s'ouvre alors, choisissez le fichier JAR que vous venez de télécharger et confirmez,
  5. fermez les propriétés de votre projet en cliquant sur Ok.

Vous avez maintenant la possiblité d'utiliser la classe BoundedIntQueueBuggy sans pour autant pouvoir voir son code source.

Créez alors un nouveau test unitaire pour cette classe, en ouvrant le menu File, puis New et en sélectionnant JUnit Test Case. Prenez garde à placer la nouvelle classe de test dans le paquetage ch.epfl.ppo et à utiliser la version 4 de JUnit.

Après que vous ayez cliqué sur Finish, un squelette de test sera créé, auquel vous devrez ajouter des méthodes de test pour les différentes méthodes de la classe BoundedIntQueueBuggy. Notez que cette dernière possède un unique constructeur qui prend en argument la capacité de la queue, sous la forme d'un entier. Ce constructeur devrait lever l'exception IllegalArgumentException si la capacité est inférieure à zéro.

Pensez à écrire au minimum une méthode de test par méthode existant dans l'interface BoundedIntQueue, et à tester également que les exceptions qui devraient être levées le sont bien. Lisez attentivement les commentaires dans le fichier BoundedIntQueue.java pour vous guider.

Vos tests devraient vous permettre de détecter un certain nombre de problèmes dans notre classe, dont vous devez prendre note avant de continuer.

Exercice 2

Ecrivez maintenant une classe ch.epfl.ppo.BoundedIntQueueOk, qui implémente (correctement) l'interface BoundedIntQueue. Il va de soi que vous pouvez utiliser le test écrit lors de l'exercice précédent pour la tester.

Une manière simple (mais peu efficace) de mettre en œuvre une queue bornée consiste à stocker ses éléments dans un tableau de taille égale à la capacité de la queue, en s'assurant que l'élément en début de queue se trouve toujours à l'indice 0, exactement comme illustré plus haut.

Avec une telle représentation, l'opération removeFirst est chère à mettre en œuvre puisqu'elle implique la copie d'un nombre d'éléments égal à la taille de la queue après la suppression… Notez que cette copie peut se faire au moyen d'un simple appel à la méthode statique arraycopy de la classe System.

Une manière plus efficace, mais plus complexe, de mettre en œuvre une queue bornée consiste à autoriser l'élément en début de queue à se trouver n'importe où dans le tableau, et pas uniquement en position 0. Vous pouvez également essayer d'utiliser cette idée pour mettre en œuvre la queue bornée, mais attention, cela n'est pas facile ! Pour la petite histoire, cette technique est celle utilisée dans la mise en œuvre de la classe ArrayDeque de la biliothèque Java.

Quelle que soit la solution que vous choisissez, pensez à placer des assertions dans votre code, aux endroits où cela vous semble judicieux.

Exercice 3

Une fois votre classe BoundedIntQueueOk écrite et correcte, téléchargez le fichier GetSecretURL.java. Il contient un petit programme qui utilise une queue bornée pour calculer une valeur secrète.

Si vous exécutez ce programme sans le modifier, il utilise la version incorrecte de la queue bornée que nous vous avons fournie (BoundedIntQueueBuggy), et imprime alors le message suivant :

Téléchargez le code source à cette adresse :
http://cs108.epfl.ch/files/bdql72/BoundedIntQueueBuggy.java

Malheureusement, l'adresse fournie est invalide, justement parce qu'elle a été calculée avec une queue bornée incorrecte. Modifiez maintenant la méthode newBoundedIntQueue de la classe GetSecretURL pour qu'elle utilise votre mise en œuvre de la queue bornée, puis relancez le programme. Si votre mise en œuvre de la queue bornée est correcte, vous devriez voir une adresse différente, et en l'entrant dans un navigateur Web, vous devriez pouvoir télécharger le code source de notre classe BoundedIntQueueBuggy.

Si tel est le cas, importez cette classe dans votre projet puis essayez de trouver et de corriger toutes les erreurs qu'elle contient. Pour la tester, utilisez bien entendu votre classe de test ! Notez que cette classe utilise la mise en œuvre rapide, mais plus compliquée, mentionnée à la fin de l'exercice 2.