Test de logiciel – TD 2

Transcription

Test de logiciel – TD 2
Université d’Evry Val d’Essonne
M1 MIAGE
Test de logiciel – TD 2
L’objectif de cette séance de travaux dirigés est de réaliser un développement itératif dirigé par les tests en
utilisant les outils JUnit et Mockito. L’application que nous allons développer et tester est une application
ferroviaire où nous devons gérer le franchissement de passages à niveau par des trains.
Cette application contiendra des objets tels que de trains, des rails, des passages à niveaux et des
contrôleurs. La finalité est de réaliser le scénario suivant où 2 trains vont se croiser sur des voies parallèles
composées de rails (voir la configuration ci-dessous) :
1. Démarrer les trains 2 et 1 ;
2. Faites avancer le train 2 puis le train 1 successivement 10 fois ;
3. Le train 2 doit passer le passage à niveau avant le train 1 ;
4. A la fin les 2 trains doivent être arrêtes et on vérifiera qu’ils ont bien parcourus 10 tronçons de rails ;
5. On vérifiera aussi que la barrière des passages à niveau s’est bien baissée puis relevée lors du
passage des trains.
Il y aura un passage à niveau pour chacune des voies.
Ce scénario sera votre test de recette (donc un test système) permettant de valider votre implémentation.
Chaque exercice correspond globalement à l’exécution d’une itération. Tous les tests joués à une itération
doivent être rejoués à l’itération suivante pour assurer la non régression du code. Si jamais des tests ne
passent plus (compilation, échec ou erreur1), il faut en étudier les raisons et :
-
Modifier le code testé jusqu’à ce que le test repasse car le résultat attendu du test doit
toujours être conforme aux spécifications ;
Modifier le code du test car la syntaxe du code appelé a évolué, alors que la spécification
reste identique ;
Supprimer le test car il n’a plus de sens car la spécification a été remise en cause.
Remarque : Pour chaque exercice, on mettra les sources dans un package exN, avec N le numéro de l’exercice, et les tests
dans le package exN.test.
Exercice 1
Lors de la première itération de notre développement, nous avons la responsabilité de développer le
composant correspondant au train. Ce composant respecte la description qui suit.
Un train dispose des opérations publiques (en plus du (ou des) constructeur(s)) suivantes : démarrer,
avancer, arrêter, distanceParcourue, getRail et vérifie les spécifications données ci-dessous :
1 Un test est en échec lorsque le résultat n’est pas conforme à la prédiction de l’oracle ; un test est en erreur
quand son exécution s’arrête pour une raison non prévue par le développeur.
Université d’Evry Val d’Essonne
M1 MIAGE
1. A la création d’un train, une instance de rail lui est injectée2 ;
2. Pour simplifier le problème la longueur d’un train est
supposée inférieure à celle d’un rail et sa
progression se fait de manière discrète : à un instant le train est sur un rail, à l’instant suivant il est
sur le rail d’après ; il n’est jamais sur 2 rails à la fois.
3. Le train stocke le nombre de rails parcourus depuis le dernier démarrage ;
4. Un appel à l’opération démarrer est nécessaire avant de vouloir faire avancer le train ;
5. Si l’on appelle avancer sans avoir démarré le train, une exception de type RuntimeException est
propagée ;
6. Lorsque l’on fait avancer le train il se déplace du rail courant vers le rail suivant (qui devient alors le
rail courant pour le train) ;
7. On ne peut pas démarrer un train sans l’avoir arrêté au préalable.
8. lorsque l’on arrête le train, il n’est alors plus possible de refaire avancer le train sans avoir au
préalable rappelé l’opération démarrer (une exception RuntimeException levée);
9. L’arrêt n’est pas immédiat, il lui faut deux rails pour s’arrêter. Dans le cas où le train n’a pas assez de
rails devant lui pour s’arrêter, une exception de type RuntimeException est propagée. De même si
un de ces 2 rails est occupé, l’exception est levée ;
10. Si jamais au moment où le train avance, le rail suivant est occupé une exception de type
RuntimeException est propagée. Dans pareil cas, l’accident est inévitable, te train ayant besoin de
deux rails pour s’arrêter ;
Le train collaborant/utilisant des objets de type Rail, il est nécessaire de connaître la spécification de la
classe Rail qui est la suivante :
-
1.
2.
3.
4.
La classe Rail dispose de l’opération suivant() qui retourne un rail si un rail suivant existe, sinon une
exception de type RuntimeException est propagée. L’opération setSuivant(…) met à jour le rail
suivant.
Elle dispose aussi d’une opération estOccupé() qui indique si un train est sur ce rail (true) ou non
(false) et d’une opération setOccupé(Boolean b) qui permet d’indiquer au rail qu’il est occupé ou
non.
Définissez les interfaces que le train et le rail devront vérifier. Appelez les respectivement ITrain et IRail. Ces interfaces
sont primordiales pour bien travailler avec les doublures (mocks).
Ecrivez le squelette de la classe concrète Train vide où les opérations ne font rien. La classe Train implémentera l’interface
ITrain. Le constructeur du train prendra un rail en paramètre.
Ecrivez la classe de test JUnit qui servira à tester le comportement de la classe Train par rapport aux spécifications données
ci-dessus.
a. Attention, vous devez effectuer ces tests sans avoir le code de la classe Rail. Il vous faut donc créer une doublure
de rail qui vérifiera la spécification indiquée. Utilisez pour cela la bibliothèque Mockito ;
b. Afin de réaliser vos tests, créez dans la méthode setUp de votre classe de test un train et un circuit composé de
doublures de rails.
Lancez vos tests puis complétez le code de la classe Train jusqu’à ce qu’ils passent tous avec succès. Attention vos
tests doivent permettre de valider l’ensemble des 10 points données dans la spécification
informelle.
Exercice 2
Nous avons maintenant à coder la classe Rail.
1.
2.
Codez et testez la classe Rail de manière unitaire (comme effectué à l’exercice 1 pour la classe Train).
Mettez à jour votre classe de test de la classe Train qui testera l’utilisation de vrais rails par la classe Train à la place des
doublures.
2 En d’autres termes, une instance de rail est passée en argument du constructeur de la
classe Train. Cette instance sera le rail sur lequel sera « posé » le train à sa création.
Université d’Evry Val d’Essonne
M1 MIAGE
Exercice 3
Nous prenons maintenant en compte les passages à niveaux pour gérer le croisement entre les voies de
chemins de fer et des routes. Ceci va nécessiter l’introduction de nouvelles classes.
Tout d’abord, de nouvelles classes PassageANiveaux et Controleur vont être ajoutées et différents types
de rails vont être distingués : des rails normaux, des rails de passage à niveaux (au croisement avec les
routes) et des rails d’avant passage à niveaux. Ces dernières signalent au train qu’ils se trouvent à une
certaine distance du passage à niveau.
Ceci nous donne les spécifications suivantes pour les différents éléments :
- La classe Contrôleur
o Elle déclenche la fermeture et l’ouverture de plusieurs passages à niveaux ;
o Si on lui demande d’ouvrir ou fermer un passage à niveaux dont elle n’est pas
responsable, une exception de type RuntimeException est propagée ;
o Elle connaît un ensemble de passage à niveaux.
-
La classe PassageANiveaux fournit une opération de fermeture et d’ouverture de la barrière (pour
les voitures).
o Elle connaît le contrôleur associé ;
o Lorsque l’on crée un passage à niveau, celui s’ajoute directement dans la liste des
passages à niveaux contrôlés par le contrôleur associé ;
o L’ouverture et la fermeture sont instantanées.
-
La classe RailPassageANiveaux correspond à la portion de rails où est situé le passage à niveau
o Quand un train est sur un tel rail, le passage à niveau correspondant doit être fermé, s’il
est ouvert un message d’alerte est émis (sortie texte) ;
o Quant le train quitte ce rail, il prévient le contrôleur pour lui demander l’ouverture du
passage à niveau.
La classe RailAvantPassageANiveaux permet d’indiquer au contrôleur qu’un train va arriver à un
passage à niveau :
o Quand un train quitte un rail avant passage à niveau, il demande au contrôleur la
fermeture du passage à niveau correspondant ;
o On dispose toujours de 2 rails normaux entre un rail avant passage à niveau et un rail de
passage à niveau. En effet, même si le train s’arrête après le rail avant passage à niveau,
son arrêt nécessitant 2 rails, il arrivera nécessairement sur le passage à niveau.
Pour un passage à niveau donné, on doit donc avoir 2 rails d’écart entre un rail d’avant PAN et le
rail PAN.
-
-
Université d’Evry Val d’Essonne
M1 MIAGE
Vous devez développer l’ensemble de ces nouvelles classes sans avoir connaissance de la classe
Train,
Pour réaliser vos tests unitaires, vous utiliserez donc des doublures de trains.
Notez que la classe Rail a disparu au profit d’une classe abstraite et de 3 classes concrètes. Continuez à vérifiez vos tests pour ces
différentes classes.
Exercice 4
Maintenant intégrez l’ensemble de vos développements et réalisez le scénario donné en préambule.
Ajoutez le à vos suites de test.

Documents pareils