Série 1 – Test unitaire : corrigé
Introduction
Le code du corrigé est disponible sous la forme d'une archive Zip, qui contient également le code de l'énoncé. Les solutions aux différents exercices sont brièvement discutées ci-dessous.
Exercice 1
Notre version du test unitaire pour BoundedIntQueue
se trouve répartie dans deux classes :
-
TestBoundedIntQueue
- Cette classe contient la totalité des tests pour les méthodes de l'interface
BoundedIntQueue
. Etant donné que plusieurs mises en œuvre de cette interface doivent être testées,TestBoundedIntQueue
déclare la méthode abstraitenewBoundedIntQueue
pour créer une queue bornée. Ensuite, une sous-classe concrète de test existe pour chaque mises en œuvre à tester. Chacune de ces sous-classe ne contient rien d'autre qu'une version concrète de la méthodenewBoundedIntQueue
, qui fait appel au bon constructeur. -
TestBoundedIntQueueBuggy
- Cette classe contient justement la première de ces classe concrètes de test. Sa méthode
newBoundedIntQueue
appelle le constructeur deBoundedIntQueueBuggy
.
En exécutant les tests de TestBoundedIntQueueBuggy
, hérités de TestBoundedIntQueue
, on constate que tous sauf un échouent. A ce stade, il est difficile de dire exactement où se trouvent les erreurs, car une erreur dans une méthode fondamentale comme le constructeur ou la méthode addLast
rend impossible le test d'autres méthodes.
Ce problème est inhérent au test et n'a pas vraiment de solution. En pratique, lorsqu'un test échoue, on essaie de déterminer la cause de cet échec avant de corriger le code fautif et de relancer les tests jusqu'à ce qu'ils s'exécutent tous sans erreur. A ce stade de la série, sans avoir accès au code source de BoundedIntQueueBuggy
, cela n'est toutefois pas encore possible.
Exercice 2
Notre corrigé contient les deux mises en œuvre de BoundedIntQueue
proposées dans l'énoncé :
BoundedIntQueueSlow
s'assure que l'élément en début de queue se trouve toujours à la position 0 du tableau. Comme dit dans l'énoncé, cela rend la méthoderemoveFirst
coûteuse, car elle doit décaler tous les éléments de la queue après suppression. Toutefois, cette mise en œuvre est facile à comprendre.BoundedIntQueueFast
tolère quand à elle que l'élément en début de queue soit à un index quelconque du tableau. Sa position est mémorisée dans le champheadPos
. Cette technique de mise en œuvre revient à considérer que le tableau contenant les éléments (contents
dans notre code) est circulaire plutôt que linéaire.
A chacune de ces deux classes correspond une classe de test, nommées respectivement TestBoundedIntQueueSlow
et TestBoundedIntQueueFast
.
Il peut être utile de placer dans chacune des deux mises en œuvre des queues bornées des assertions vérifiant certaines de leurs propriétés. Une première propriété qui doit toujours être vraie est que la taille d'une queue bornée est comprise entre 0 et sa capacité. Dans la version rapide de la queue, on sait de plus que la position de l'élément contenant le début de la queue (headPos
) doit lui aussi toujours être dans le même intervalle.
Ces deux assertions doivent être vérifiées chaque fois qu'elles sont susceptibles de changer. Comme la capacité d'une queue ne peut changer, il faut les vérifier chaque fois que le champ size
(respectivement headPos
) change.
Exercice 3
Une fois l'une ou l'autre de ces mises en œuvre écrite et testée, on peut l'utiliser pour exécuter le programme contenu dans GetSecretURL.java
. Celui-ci affiche alors le message suivant :
Téléchargez le code source de BoundedIntQueueBuggy à cette adresse : http://cs108.epfl.ch/files/jp7hu3/BoundedIntQueueBuggy.java
Après téléchargement du fichier référencé, on peut constater (et corriger petit-à-petit) les erreurs suivantes :
- le constructeur alloue un tableau trop grand et initialise la taille à 1 plutôt qu'à 0,
addLast
etremoveFirst
vérifient trop tard si la pile est pleine ou vide, et lèvent la mauvaise exception.