TP 2
Complete Skyjo model implementation, familiarization with controller, writing tests, test coverage.
Meta
- Deadline: Mar 8th, 11:59 PM.
- Submission: GitLab, provided group repo,
mainbranch. - Teams: Triplets of students, same teams as previous TP.
- Late submission: Not possible. You will be graded by whatever code is on your
mainbranch at the deadline.
Avoid last-minute submissions
It is your responsibility to submit code in a timely manner. Do not wait until the last minute, GitLab may fail.
Learning goals
With this second TP you will obtain sound practice regarding:
- relying on standard IDE functionality, to complete your Skyjo
Modelimplementation, and exploring several controller methods. - writing quality code, i.e. also writing tests, matching code against coverage reports, respecting strict formatting conventions.
- rely on a build system configuration to enforce basic code quality requirements.
Step-by-step overview
- Corrections: Check your previous submission.
- Use the feedback returned to you on GitLab (see Mattermost post).
- Fix any issues, especially failing tests. Use the debugger.
- Checkstyle: Respect provided formatting rules.
- Configure your IDE to use the newly provided
google_checks.xmlformatting rules. - Format your existing code, using the IDE code-formatting key combo.
- Modify the
pom.xmlso maven detects checkstyle violations.
- Configure your IDE to use the newly provided
- New code: Complete your model implementation and start a controller implementation.
- Replace your launcher code.
- Implement all remaining
SkyjoModel(write access) methods. - Implement a new class
ControllerImplimplementing the providedControllerinterface.
- Tests and coverage: Build trust for your code.
- Extend the newly provided abstract test classes: model write access, rudimentary controller access.
- Implement your own additional unit tests.
- Boost model line coverage above 80%.
Detailed instructions
Details on each of the above steps:
Corrections
- Use IntelliJ to rerun your tests and fix any remaining issued.
- Use
mvn clean packageto verify all previously released tests pass. - Use the debugger to understand where and why tests fail.
If a test fails:- Set a breakpoint on the provided abstract test, i.e. a few lines before the failing assertion.
- Debug your code, understand the fail cause, i.e. why your method result differs from the expected result.
- Don't blame the test, fix the issue in your code. (Engineers don't blame the challenge, they provide solutions)
If you're having difficulties with the debugger,
see this screencast. It is from last session (not skyjo) but the procedure is identical.
Checkstyle
- The previous merge also provided a file
google-checks.xml- Do not modify the file or replace it with a different version. Use the one provided.
- Configure your IDE to automatically format code according to google code style rules, and manual checkstyle scans. * A video screencast of the setup steps is also available.
- Use the formatting shortcut (
Ctrl+Alt+L/Option+Command+L) to format all previously coded files.
Checkstyle with maven
- Maven can be configured to run checkstyle verifications, i.e. whenever you use
mvn clean packageyour code will be scanned for checkstyle violations. - Add this plugin to your
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>
New code
- First of all, update the maven dependency for provided interfaces to version
tp2-02: - Double-check your
SkyjoModelImplclass implements all provided read and write access methods from both interfaces.- Do not list both interfaces in the
implementsstatements, they are already hierarchical (SkyjoModelextendsSkyjoModelReadOnly. If your model implementsSkyjoModel, you implicitly implement both interfaces). - Don't worry about the game end methods for now, you can leave them as stubs.
- Do not list both interfaces in the
- Add a new
ControllerImplclass to yourcontrollerpackage, make sure it implements the providedControllerinterface. You don't need to implement a fully functional controller for now, it only needs to support:- Game initialization (see TP2 launcher code below).
- Creating the right commands for game start. At game start the first player can only do two things:
flowchart TD K(Start _) --> |"a) Reveal deck<br>card"| L(Card in buffer) K --> |"b) Replace<br>player card __<br>(trash)"| M(Card replaced _)
Use the command pattern
To keep you code clean, create two helper classes, one for each execution path:
a) RevealCommand implements Command: Objects of this class disclose a card from the pile. (1 command object)
b) ReplaceCommand implements Command: Objects of this class replace any of their cards with the top discard pile card. (12 command objects, one per player card)
So in total the controller generates an array with 13 command objects. Make sure the order is respected, a) is listed before all b)s (and b)'s are ordered top left to bottom right, line by line).
The provided maven dependencies already have a Command interface, just for this purpose.
Illustrations for expected output at end of this file.
Tests and Coverage
- For the TP1, you already implemented two test classes (in
src/test/java/...). Keep those files. No further changes are necessary to these files for now. - The new interfaces provided for the TP2, also come with additional tests, to guide your model write access and
controller implementation. To activate these tests, update the test dependency to version
tp2-01and extend the provided abstract test classes: - With the abstract test extensions from TP1 and the additional abstract test extensions for TP2 you
will already have a certain code coverage.
- However, for this TP2 you are required to reach an 80% coverage of your
Modelpackage (lines of code). - To reach 80%, you must add additional model unit tests yourself.
- However, for this TP2 you are required to reach an 80% coverage of your
Anticipate undisclosed tests
When writing your own tests, anticipate how test hacking could have been prevented. In contrast to the previous TP, not all test scenarios have been covered for the TP2. There is a set of undisclosed tests, which will be applied to your solution.
Where to put your tests
- Do not place your test methods in your already existing test classes (the ones extending the provided abstract test classes). Your methods might conflict with undisclosed existing tests written by the prof. Define new test classes instead, and place your own test methods on these new classes.
Stick to the JUnit version presented in class
Do not modify the JUnit version in the pom.xml and do not mix with JUnit annotation syntax of other versions. They are not compatible and you risk compiler issues.
Grading Tablea
| Item | Criteria | Max percentage |
|---|---|---|
| 1 | Provided tests pass | 40% |
| 2 | Hidden tests pass | 20% |
| 3 | Test coverage (lines) > 80% | 20% |
| 4 | Checkstyle: no errors/warnings | 15% |
| 5 | .gitignore defined and no clutter | 5% |
Recommendation
Simulate the grading process before submission: run mvn clean package and ensure your project can be built without warnings or errors, using the pom.xml extensions provided for this TP2.
Desk rejection
Here is a checklist of what to avoid at all costs. If at least one item of the checklist applies, your submission will lose all code-related points. There may be other criteria for desk rejection.
- Solution not provided in dedicated GitLab directory, or not on
mainbranch. - Solution is distributed across multiple branches.
- Repository contains zip file.
- Code does not compile with provided maven command.
pom.xmlhas other plugins or dependencies than allowed.- Provided classes do not implement provided interfaces.
- Implementation of abstract test classes is not provided in test package.
- Project structure has been altered / is not respected.
- Program attempts network communication at runtime.
- Program stalls at runtime.
Samples
TP2 Launcher code
Create a new class with this java code and add it to YOUR view package:
/**
* 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);
}
}
Don't forget to update your launchers
You also have to update the launcher class in your pom.xml:
exec-plugin=>main-classmaven-assembly-plugin=>main-class
Abstract controller test sample
To activate the provided abstract controller tests, you only need to subclass the provided abstract class:
/**
* 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.
}
}
Abstract model write access tests sample
- To activate the provided model write access tests, you can reuse your existing
SkyjoModelTestclass. - The newly provided
SkyjoModelTestAbstractclass is an extension ofSkyjoModelReadOnlyTestAbstract: by switching the class you extend, you automatically enable the abstract tests of both provided classes. - Concretely, just change the signature of your TP1
SkyjoModelTestto extendSkyjoModelTestAbstract.
The class signature should now be:
public class SkyjoModelTest extends SkyjoModelTestAbstract - With just this change you will instantly unlock provided test cases for write access.
Expected output and commands for default model
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)
Ignore the ': ---' spaceholders.
You can ignore the : --- spaceholders, these are only there to easy readability. Important is only that the commands count to 12 and that each index corresponds to the above sample.