This shows you the differences between two versions of the page.
Both sides previous revision Previous revision Next revision | Previous revision | ||
2019_2020:s3:concprogobjet:td:td6 [2019/11/02 18:42] blay [Partie 1 : Tutoriel EasyMock (1h grand maximum)] |
2019_2020:s3:concprogobjet:td:td6 [2019/11/06 13:40] (current) blay [Partie 1 : Tutoriel EasyMock (1h grand maximum)] |
||
---|---|---|---|
Line 1: | Line 1: | ||
- | ====== Tests d'intégration et conception en autonomie ====== | + | ====== Tests d'intégration et conception ====== |
Ce TD vise | Ce TD vise | ||
- à vous apprendre à mettre en place des tests d'intégration | - à vous apprendre à mettre en place des tests d'intégration | ||
- à concevoir une petite application à plusieurs en prévoyant les tests d'intégration. | - à concevoir une petite application à plusieurs en prévoyant les tests d'intégration. | ||
+ | /* | ||
<note important>4h c'est à dire 2 séances seront consacrées à ce TD. | <note important>4h c'est à dire 2 séances seront consacrées à ce TD. | ||
Vous ne parviendrez peut etre pas à tout faire. | Vous ne parviendrez peut etre pas à tout faire. | ||
Line 9: | Line 10: | ||
- Ne trainez pas non plus ! | - Ne trainez pas non plus ! | ||
</note> | </note> | ||
+ | */ | ||
===== Partie 1 : Tutoriel EasyMock (1h grand maximum) ===== | ===== Partie 1 : Tutoriel EasyMock (1h grand maximum) ===== | ||
Line 15: | Line 17: | ||
- Voici le .jar dont vous avez besoin pour avoir accès à l'{{:2019_2020:s3:concprogobjet:td:easymock-4.0.2.jar|environnement EasyMock}}. | - Voici le .jar dont vous avez besoin pour avoir accès à l'{{:2019_2020:s3:concprogobjet:td:easymock-4.0.2.jar|environnement EasyMock}}. | ||
- | - Pour l'ajouter à votre classpath du projet : sur le nom du projet > Properties > Java Build Path > Puis ajouter le .jar ci-dessus.{{:2019_2020:s3:concprogobjet:td:capture_d_e_cran_2019-11-02_a_18.22.00.png?200|}} | + | - Créer un projet java |
- | - Voici l'interface dont dépendent vos codes, mais que vous ne devez pas implémenter. <code java> | + | - Ajouter à votre **classpath** du projet le .jar donné ci-dessus : sur le nom du projet > Properties > Java Build Path > Puis ajouter le .jar ci-dessus.{{:2019_2020:s3:concprogobjet:td:capture_d_e_cran_2019-11-02_a_18.22.00.png?200|}} |
+ | - Voici l'interface dont dépendent vos codes, mais que vous ne devez pas implémenter. Ajoutez la à votre projet. <code java> | ||
public interface Collaborator { | public interface Collaborator { | ||
Line 103: | Line 106: | ||
Unexpected method call Collaborator.documentRemoved("Does not exist"):... | Unexpected method call Collaborator.documentRemoved("Does not exist"):... | ||
</code> | </code> | ||
+ | - Ajoutez un test, cette fois-ci juste : | ||
+ | - On déclare le message que doit recevoir le mock (7.a) | ||
+ | - On enregistre (7.b) | ||
+ | - On lance le test sur notre code (7.c) | ||
+ | - On explicite la vérification (réalisée par défaut) (7.d) <code java> @Test | ||
+ | public void testRemoveNonExistingDocument2() { | ||
+ | mock.documentRemoved("Does not exist"); //7.a | ||
+ | replay(mock); //7.b | ||
+ | classUnderTest.removeDocument("Does not exist"); //7.c | ||
+ | verify(mock); //7.d | ||
+ | } | ||
+ | </code> | ||
+ | - Ajoutez un test, mais cette fois-ci nous explicitons la valeur de retour attendue et nous créons deux mocks pour nous assurer qu'il n'y a pas d'effets secondaires <code java> | ||
+ | @Test | ||
+ | public void testAddDocument() throws AlreadyAdded { | ||
+ | //Initialisation | ||
+ | Collaborator firstCollaborator = mock(Collaborator.class);//construction de mock | ||
+ | Collaborator secondCollaborator = mock(Collaborator.class);//construction de mock, il ne sera pas utilisé | ||
+ | classUnderTest.setListener(firstCollaborator); | ||
+ | | ||
+ | //// expect document addition | ||
+ | expect(firstCollaborator.documentAdded("New Document")).andReturn(true); //On attend que le mock réponde True ! | ||
+ | replayAll(); //on enregistre le comportement de tous les Mocks | ||
+ | classUnderTest.addDocument("New Document", "content"); | ||
+ | assertTrue(classUnderTest.isContained("New Document")); //on vérifie que NOS codes se comportent correctement | ||
+ | verifyAll(); //On vérifie le comportement de tous les mocks | ||
+ | } | ||
+ | </code> | ||
+ | - Ajoutez un test, mais cette fois-ci nous attendons pour valeur de retour false <code java> @Test | ||
+ | public void testFailingAddDocument() throws AlreadyAdded { | ||
+ | //Initialisation | ||
+ | Collaborator firstCollaborator = mock(Collaborator.class); | ||
+ | Collaborator secondCollaborator = mock(Collaborator.class); | ||
+ | classUnderTest.setListener(firstCollaborator); | ||
+ | | ||
+ | //// expect document addition | ||
+ | expect(firstCollaborator.documentAdded("New Document")).andReturn(false); | ||
+ | replayAll(); | ||
+ | classUnderTest.addDocument("New Document", "content"); | ||
+ | assertFalse(classUnderTest.isContained("New Document")); | ||
+ | verifyAll(); | ||
+ | } | ||
+ | </code> | ||
+ | - et enfin nous testons une levée d'exception <code java> @Test | ||
+ | public void testDuplicationWhenAddingDocument() throws AlreadyAdded { | ||
+ | //Initialisation | ||
+ | Collaborator firstCollaborator = mock(Collaborator.class); | ||
+ | Collaborator secondCollaborator = mock(Collaborator.class); | ||
+ | classUnderTest.setListener(firstCollaborator); | ||
+ | | ||
+ | //// expect document addition | ||
+ | expect(firstCollaborator.documentAdded("New Document")).andThrow(new AlreadyAdded()); | ||
+ | replayAll(); | ||
+ | classUnderTest.addDocument("New Document", "content"); | ||
+ | assertTrue(classUnderTest.isContained("New Document"+ClassTested.COPY)); | ||
+ | verifyAll(); | ||
+ | }</code> | ||
+ | |||
+ | Cela conclut la partie tutorielle. | ||
+ | A présent, vous devriez savoir créer vous même des tests d'intégration. | ||
+ | |||
+ | |||
===== Partie 2 : Un jeu de Quizz ===== | ===== Partie 2 : Un jeu de Quizz ===== | ||
- | Vous devez réaliser en groupe de 2 étudiants un jeu de quizz dont voici la spécification. | + | Vous devez réaliser en groupe de X étudiants un jeu de quizz dont voici la spécification. |
- | ==== Spécifications ==== | + | ==== Spécification ==== |
* **V0 : Version de base** | * **V0 : Version de base** | ||
- | - En tant que joueur, je veux répondre à une question du quizz <color /lightblue> TRES FORTE PRIORITE </color> | + | - En tant que joueur, je veux répondre à une question du quizz |
- Si j'ai la bonne réponse je gagne 1pt | - Si j'ai la bonne réponse je gagne 1pt | ||
- Si je n'ai pas la bonne réponse, la bonne réponse m'est donnée. | - Si je n'ai pas la bonne réponse, la bonne réponse m'est donnée. | ||
Line 118: | Line 184: | ||
- "Quelle est la capitale de l'Espagne", je réponds madrid ... j'ai gagné 1 pt | - "Quelle est la capitale de l'Espagne", je réponds madrid ... j'ai gagné 1 pt | ||
- "Quelle est la capitale de l'Érythrée", je réponds Assab, le jeu m'annonce que la bonne réponse est Asmara, je n'ai pas gagné de points | - "Quelle est la capitale de l'Érythrée", je réponds Assab, le jeu m'annonce que la bonne réponse est Asmara, je n'ai pas gagné de points | ||
- | - En tant que joueur, je veux jouer une partie de quizz, de façon à m'amuser en vérifiant mes connaissances. <color /lightblue> FORTE PRIORITE </color> | + | - En tant que joueur, je veux jouer une partie de quizz, de façon à m'amuser en vérifiant mes connaissances. |
+ | |||
+ | ==== Modélisation ==== | ||
+ | |||
+ | === Exigences === | ||
+ | Voici les interfaces qui vous sont données et que vous devez respecter. | ||
+ | <code java> | ||
+ | public interface GameInterface { | ||
+ | |||
+ | void startGame(); | ||
+ | |||
+ | boolean isNotOver(); | ||
+ | |||
+ | String nextQuestion(); | ||
+ | |||
+ | boolean setCurrentUserAnswer(String answer); | ||
+ | |||
+ | String getRightAnswer(); | ||
+ | |||
+ | int getPoints(); | ||
+ | |||
+ | } | ||
+ | </code> | ||
+ | <code java> | ||
+ | public interface QuizInterface { | ||
+ | |||
+ | public String getQuestion(int currentQuestionNumber) ; | ||
+ | |||
+ | public boolean isGoodAnswer(int currentQuestionNumber, String answer); | ||
+ | |||
+ | public String getAnswer(int currentQuestionNumber); | ||
+ | |||
+ | public int size(); | ||
+ | |||
+ | public void addQuestion(QuestionInterface q1); | ||
+ | |||
+ | } | ||
+ | </code> | ||
+ | <code java> | ||
+ | public interface QuestionInterface { | ||
+ | |||
+ | String getAnswer(); | ||
+ | |||
+ | String getQuestion(); | ||
+ | |||
+ | boolean isGoodAnswer(String answer); | ||
+ | |||
+ | } | ||
+ | </code> | ||
+ | |||
+ | **Voici un code pour tester un jeu.** | ||
+ | <code java> | ||
+ | package quizzPK; | ||
+ | |||
+ | import java.util.Scanner; | ||
+ | |||
+ | public class mainTestGame { | ||
+ | |||
+ | public static void main(String[] args) { | ||
+ | Scanner sc = new Scanner(System.in); | ||
+ | |||
+ | QuizInterface quiz = new Quiz(); | ||
+ | QuestionInterface q1 = new Question("Capitale de la France ?", "Paris"); | ||
+ | QuestionInterface q2 = new Question("Capitale de l'Allemagne ?", "Berlin"); | ||
+ | QuestionInterface q3 = new Question("Capitale de l'Italie", "Rome"); | ||
+ | |||
+ | quiz.addQuestion(q1); | ||
+ | quiz.addQuestion(q2); | ||
+ | quiz.addQuestion(q3); | ||
+ | GameInterface game = new Game(quiz); | ||
+ | |||
+ | game.startGame(); | ||
+ | |||
+ | while (game.isNotOver()) { | ||
+ | System.out.println(game.nextQuestion() + " : ") ; | ||
+ | String answer = sc.nextLine(); | ||
+ | boolean valid = game.setCurrentUserAnswer(answer); | ||
+ | if (!valid ) { | ||
+ | System.out.println("You failed, the correct answer is : " + game.getRightAnswer() ); | ||
+ | } | ||
+ | else | ||
+ | System.out.println("Well done ! "); | ||
+ | } | ||
+ | |||
+ | System.out.println("Score : " + game.getPoints()); | ||
+ | } | ||
+ | |||
+ | |||
+ | |||
+ | } | ||
+ | </code> | ||
+ | === A Faire === | ||
+ | - **Modélisez** par groupe de 2 ou 3 étudiants, le jeu | ||
+ | - En particulier, intéressez-vous aux interactions entre les classes. | ||
+ | - Une fois que vous êtes d'accord, vous passez à la suite | ||
+ | - **Développez** séparément | ||
+ | - Etudiant 1 : Développez la classe ''Game'' sans développer la classe ''Quiz''. | ||
+ | - Tester votre classe ''Game'' en utilisant des Mocks. | ||
+ | - Etudiant 2 : Développez la classe ''Quizz'' sans développer la classe ''Question''. | ||
+ | - Tester votre classe ''Quizz'' en utilisant des Mocks | ||
+ | - Intégrez vos codes. | ||
+ | |||
+ | L'essentiel n'est pas d'atteindre cette ultime étape. Mais davantage d'apprendre à écrire des tests d'intégration. | ||
+ | |||
+ | |||
+ | /* | ||
+ | === Headline === | ||
+ | |||
- 10 questions sont posées au joueur | - 10 questions sont posées au joueur | ||
- Seules des questions auxquelles le joueur n'a jamais répondu juste lui sont posées. | - Seules des questions auxquelles le joueur n'a jamais répondu juste lui sont posées. | ||
Line 150: | Line 324: | ||
* V1C : Des difficultés de questions. | * V1C : Des difficultés de questions. | ||
* V1D : Persistance : les questions sont stockées dans un fichier, de même pour les parties. | * V1D : Persistance : les questions sont stockées dans un fichier, de même pour les parties. | ||
- | + | */ | |
- | ==== A faire ==== | + | /* ==== A faire ==== |
- Conception : V0 (Environ 1/2 heure intense) | - Conception : V0 (Environ 1/2 heure intense) | ||
Line 175: | Line 349: | ||
- 8-O reprendre la question précédente. | - 8-O reprendre la question précédente. | ||
- Si vous êtes ici et que vous en avez envie ajoutez une autre extension. | - Si vous êtes ici et que vous en avez envie ajoutez une autre extension. | ||
+ | */ | ||
+ | |||
+ | /* | ||
Line 189: | Line 366: | ||
</code> | </code> | ||
+ | */ | ||
+ | /* | ||
==== A RENDRE ==== | ==== A RENDRE ==== | ||
- Document | - Document | ||
Line 200: | Line 379: | ||
Voici le document qui sera utilisé pour l'évaluation (il peut encore changer) : https://goo.gl/forms/PmNPOPcurIKJLlo32 | Voici le document qui sera utilisé pour l'évaluation (il peut encore changer) : https://goo.gl/forms/PmNPOPcurIKJLlo32 | ||
+ | */ | ||