TP 2
Implémentation complète du modèle Skyjo, familiarisation avec le contrôleur, rédaction de tests, couverture de tests.
Méta
- Date limite : 8 mars, 23 h 59.
- Remise : GitLab, dépôt de groupe fourni, branche
main. - Équipes : Groupes de trois étudiants, mêmes équipes que le TP précédent.
- Remise en retard : Impossible. Vous serez évalués selon le code présent sur votre branche
mainà la date limite.
Évitez les remises à la dernière minute
Il est de votre responsabilité de soumettre votre code en temps opportun. N’attendez pas à la dernière minute, GitLab pourrait échouer.
Objectifs d’apprentissage
Avec ce deuxième TP, vous acquerrez une expérience solide concernant :
- l’utilisation des fonctionnalités standard de l’IDE pour compléter votre implémentation du
Modelde Skyjo et explorer plusieurs méthodes du contrôleur. - l’écriture de code de qualité, c’est-à-dire également la rédaction de tests, la validation du code à l’aide de rapports de couverture, et le respect de conventions de formatage strictes.
- l’utilisation d’une configuration de système de build pour faire respecter des exigences de base en matière de qualité du code.
Aperçu étape par étape
- Corrections : Vérifiez votre remise précédente.
- Utilisez les commentaires qui vous ont été retournés sur GitLab (voir publication sur Mattermost).
- Corrigez tous les problèmes, en particulier les tests échoués. Utilisez le débogueur.
- Checkstyle : Respectez les règles de formatage fournies.
- Configurez votre IDE pour utiliser les règles de formatage
google_checks.xmlnouvellement fournies. - Formatez votre code existant à l’aide du raccourci de formatage de code de l’IDE.
- Modifiez le
pom.xmlafin que Maven détecte les violations de Checkstyle.
- Configurez votre IDE pour utiliser les règles de formatage
- Nouveau code : Complétez votre implémentation du modèle et commencez une implémentation du contrôleur.
- Remplacez votre code de lanceur.
- Implémentez toutes les méthodes restantes de
SkyjoModel(accès en écriture). - Implémentez une nouvelle classe
ControllerImplqui implémente l’interfaceControllerfournie.
- Tests et couverture : Renforcez la confiance dans votre code.
- Étendez les classes de tests abstraites nouvellement fournies : accès en écriture du modèle, accès rudimentaire au contrôleur.
- Implémentez vos propres tests unitaires supplémentaires.
- Augmentez la couverture de lignes du modèle au-delà de 80 %.
Instructions détaillées
Détails sur chacune des étapes ci-dessus :
Corrections
- Utilisez IntelliJ pour relancer vos tests et corriger les problèmes restants.
- Utilisez
mvn clean packagepour vérifier que tous les tests précédemment fournis réussissent. - Utilisez le débogueur pour comprendre où et pourquoi les tests échouent.
Si un test échoue :- Placez un point d’arrêt dans le test abstrait fourni, c’est-à-dire quelques lignes avant l’assertion qui échoue.
- Déboguez votre code et comprenez la cause de l’échec, c’est-à-dire pourquoi le résultat de votre méthode diffère du résultat attendu.
- Ne blâmez pas le test, corrigez le problème dans votre code. (Les ingénieurs ne blâment pas le défi, ils proposent des solutions.)
Si vous éprouvez des difficultés avec le débogueur,
consultez cette capture vidéo. Elle provient de la session précédente (pas Skyjo), mais la
procédure est identique.
Checkstyle
- La fusion précédente a également fourni un fichier
google-checks.xml- Ne modifiez pas ce fichier et ne le remplacez pas par une autre version. Utilisez celui qui est fourni.
- Configurez votre IDE pour formater automatiquement le code selon les règles de style Google, et pour effectuer des analyses Checkstyle manuelles.
- Une capsule vidéo présentant les étapes de configuration est également disponible.
- Utilisez le raccourci de formatage (
Ctrl+Alt+L/Option+Command+L) pour formater tous les fichiers déjà codés.
Checkstyle avec Maven
- Maven peut être configuré pour exécuter les vérifications Checkstyle, c’est-à-dire qu’à chaque exécution de
mvn clean package, votre code sera analysé afin de détecter les violations de Checkstyle. - Ajoutez ce plugin à votre
pom.xml:<!-- Plugin to scan for checkstyle violations--> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-checkstyle-plugin</artifactId> <version>3.6.0</version> <configuration> <configLocation>google_checks.xml</configLocation> <consoleOutput>true</consoleOutput> <violationSeverity>warning</violationSeverity> <failOnViolation>false</failOnViolation> <failsOnError>false</failsOnError> <linkXRef>false</linkXRef> <includeTestSourceDirectory>true</includeTestSourceDirectory> </configuration> <executions> <execution> <id>validate</id> <phase>validate</phase> <goals> <goal>check</goal> </goals> </execution> </executions> </plugin>
Nouveau code
- Tout d’abord, mettez à jour la dépendance Maven pour les interfaces fournies à la version
tp2-02: - Vérifiez bien que votre classe
SkyjoModelImplimplémente toutes les méthodes d’accès en lecture et en écriture fournies par les deux interfaces.- Ne listez pas les deux interfaces dans la déclaration
implements, elles sont déjà hiérarchiques (SkyjoModelétendSkyjoModelReadOnly. Si votre modèle implémenteSkyjoModel, vous implémentez implicitement les deux interfaces). - Ne vous inquiétez pas pour les méthodes de fin de partie pour l’instant, vous pouvez les laisser comme stubs.
- Ne listez pas les deux interfaces dans la déclaration
- Ajoutez une nouvelle classe
ControllerImpldans votre packagecontroller, assurez-vous qu’elle implémente l’interfaceControllerfournie. Vous n’avez pas besoin d’implémenter un contrôleur entièrement fonctionnel pour l’instant, il doit seulement supporter :- L’initialisation du jeu (voir le code du lanceur TP2 ci-dessous).
- La création des commandes correctes pour le début de partie. Au début de la partie, le premier joueur ne peut
faire que deux choses :
flowchart TD K(Start _) --> |"a) Reveal deck<br>card"| L(Card in buffer) K --> |"b) Replace<br>player card __<br>(trash)"| M(Card replaced _)
Utilisez le patron de commande
Pour garder votre code propre, créez deux classes auxiliaires, une pour chaque chemin d’exécution :
a) RevealCommand implements Command : Les objets de cette classe révèlent une carte de la pile. (1 objet commande)
b) ReplaceCommand implements Command : Les objets de cette classe remplacent n’importe laquelle de leurs cartes par la carte du dessus de la pile de défausse. (12 objets commande, un par carte du joueur)
Ainsi, au total, le contrôleur génère un tableau avec 13 objets commande. Assurez-vous que l’ordre est respecté, a) est listé avant tous les b) et les b) sont ordonnés de haut gauche à bas droite, ligne par ligne.
Les dépendances Maven fournies contiennent déjà une interface Command, juste pour cet usage.
Illustrations pour la sortie attendue à la fin de ce fichier.
Tests et couverture
- Pour le TP1, vous avez déjà implémenté deux classes de test (dans
src/test/java/...). Conservez ces fichiers. Aucun changement supplémentaire n’est nécessaire pour l’instant. - Les nouvelles interfaces fournies pour le TP2 sont également accompagnées de tests supplémentaires, pour guider votre
implémentation du modèle en écriture et du contrôleur. Pour activer ces tests, mettez à jour la dépendance de test à
la version
tp2-01et étendez les classes de test abstraites fournies : - Avec les extensions de tests abstraits du TP1 et les extensions de tests abstraits supplémentaires pour le TP2, vous
aurez déjà une certaine couverture de code.
- Cependant, pour ce TP2, vous devez atteindre 80 % de couverture de votre package
Model(lignes de code). - Pour atteindre 80 %, vous devez ajouter vous-même des tests unitaires supplémentaires pour le modèle.
- Cependant, pour ce TP2, vous devez atteindre 80 % de couverture de votre package
Anticipez les tests non divulgués
Lorsque vous écrivez vos propres tests, anticipez comment le piratage de tests aurait pu être évité. Contrairement au TP précédent, tous les scénarios de test ne sont pas couverts pour le TP2. Il existe un ensemble de tests non divulgués, qui seront appliqués à votre solution.
Où placer vos tests
- Ne placez pas vos méthodes de test dans vos classes de test déjà existantes (celles qui étendent les classes de test abstraites fournies). Vos méthodes pourraient entrer en conflit avec des tests existants non divulgués écrits par le prof. Définissez plutôt de nouvelles classes de test, et placez vos propres méthodes de test dans ces nouvelles classes.
Respectez la version de JUnit présentée en cours
Ne modifiez pas la version de JUnit dans le pom.xml et ne mélangez pas avec la syntaxe d’annotation JUnit d’autres versions. Elles ne sont pas compatibles et vous risquez des problèmes de compilation.
Barème
| Élément | Critères | Pourcentage max |
|---|---|---|
| 1 | Tests fournis réussis | 40 % |
| 2 | Tests cachés réussis | 20 % |
| 3 | Couverture des tests (lignes) > 80 % | 20 % |
| 4 | Checkstyle : pas d’erreurs/avertissements | 15 % |
| 5 | .gitignore défini et pas de fichiers superflus | 5 % |
Recommandation
Simulez le processus de notation avant la remise : exécutez mvn clean package et assurez-vous que votre projet peut être compilé sans avertissements ni erreurs, en utilisant les extensions pom.xml fournies pour ce TP2.
Rejet de dossier
Voici une liste de contrôle de ce qu’il faut éviter à tout prix. Si au moins un élément de la liste s’applique, votre remise perdra tous les points liés au code. D’autres critères de rejet peuvent exister.
- Solution non fournie dans le répertoire GitLab dédié, ou pas sur la branche
main. - Solution distribuée sur plusieurs branches.
- Dépôt contenant un fichier zip.
- Le code ne compile pas avec la commande Maven fournie.
pom.xmlcontient d’autres plugins ou dépendances que ceux autorisés.- Les classes fournies n’implémentent pas les interfaces fournies.
- Implémentation des classes de test abstraites non fournie dans le package de test.
- Structure du projet modifiée / non respectée.
- Programme tentant une communication réseau à l’exécution.
- Programme bloqué à l’exécution.
Exemples
Code du lanceur TP2
Créez une nouvelle classe avec ce code Java et ajoutez-la à VOTRE package view :
/**
* Launcher for a textual / TTY session with all physical players sharing one keyboard / screen.
*
* @author Maximilian Schiedermeier
*/
public class LauncherTp2 {
/**
* Default constructor, as imposed by javadoc.
*/
public LauncherTp2() {
}
/**
* Replace command selector by robot players to obtain an automated game (also used for
* integration testing).
*/
private static CommandSelector commandSelector;
/**
* Starts game by creating a new controller (which in turn creates a new model). Then keeps
* prompting players for choices until game end is reached.
*
* @param args not used.
*/
public static void main(String[] args) {
// Register UI to automatically refresh on model updates
boolean useTtyColours = true;
// Create a model, using your model constructor.
// Make sure your model implements the provided model readonly interface
String[] playerNames = new String[] {"Max", "Ryan", "Maram", "Quentin"};
// Initialize a new game, using YOUR controller implementation.
Controller controller = new ControllerImpl();
// Register UI to automatically refresh on model updates
controller.initializeModel(ModelPreset.DEFAULT, playerNames, null);
controller.addModelObserver(new TextualVisualizer(controller.getModel(), useTtyColours));
// Print initial commands, as determined by YOUR controller implementation.
Command[] options = controller.getCurrentPlayerCommands();
TextualCommandSelector commandSelector = new TextualCommandSelector(useTtyColours, false);
commandSelector.visualizeCommands(options, false, useTtyColours);
}
}
N’oubliez pas de mettre à jour vos lanceurs
Vous devez également mettre à jour la classe lanceur dans votre pom.xml :
exec-plugin=>main-classmaven-assembly-plugin=>main-class
Exemple de test abstrait pour le contrôleur
Pour activer les tests abstraits fournis pour le contrôleur, vous devez seulement sous-classer la classe abstraite fournie :
/**
* Concrete controller test, provides access to controller instances, tied to implementation.
*/
public class ControllerDefaultInitialCommandsTest extends ControllerDefaultInitialCommandsTestAbstract {
@Override
public Controller getController() {
return null; // TODO: Implement... ne pas retourner null mais un vrai objet contrôleur, pour
// activer les tests définis dans ControllerTestAbstract.
}
}
Exemple de tests d’accès en écriture pour le modèle
- Pour activer les tests d’accès en écriture du modèle fournis, vous pouvez réutiliser votre classe
SkyjoModelTestexistante. - La nouvelle classe fournie
SkyjoModelTestAbstractest une extension deSkyjoModelReadOnlyTestAbstract: en changeant simplement la classe que vous étendez, vous activez automatiquement les tests abstraits des deux classes fournies. - Concrètement, modifiez simplement la signature de votre
SkyjoModelTestdu TP1 pour qu’elle étendeSkyjoModelTestAbstract.
La signature de la classe devrait maintenant être :
public class SkyjoModelTest extends SkyjoModelTestAbstract - Avec ce simple changement, vous débloquez instantanément les cas de test fournis pour l’accès en écriture.
Résultat attendu et commandes pour le modèle par défaut
Round: 1
Deck (101): [??]
Discard ( 1): [ 8]
Buffer: [--]
MAX (23) Ryan (21) Maram (19) Quentin (17)
[12] [??] [??] [??] [11] [??] [??] [??] [10] [??] [??] [??] [ 9] [??] [??] [??]
[??] [??] [??] [??] [??] [??] [??] [??] [??] [??] [??] [??] [??] [??] [??] [??]
[??] [??] [??] [11] [??] [??] [??] [10] [??] [??] [??] [ 9] [??] [??] [??] [ 8]
0: Reveal deck card : --- : --- : ---
1: Replace (0/0) 2: Replace (1/0) 3: Replace (2/0) 4: Replace (3/0)
5: Replace (0/1) 6: Replace (1/1) 7: Replace (2/1) 8: Replace (3/1)
9: Replace (0/2) 10: Replace (1/2) 11: Replace (2/2) 12: Replace (3/2)
Ignorez les espaces réservés ': ---'.
Vous pouvez ignorer les espaces réservés : ---, ils servent uniquement à faciliter la lisibilité. L’important est seulement que le nombre de commandes soit de 12 et que chaque index corresponde à l’exemple ci-dessus.