package ch.zhaw.catan; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; import org.junit.jupiter.api.*; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; import java.awt.*; import java.util.*; import java.util.List; /*** * TODO Write your own tests in this class. * * Note: Have a look at {@link ch.zhaw.catan.games.ThreePlayerStandard}. It can be used * to get several different game states. * */ /** * @class SiedlerGameTest * * contains all of the test cases for SiedlerGame class. * The Test cases are categorized into * - Positive TestCases * Tests the methods of SiedlerGame with the intended values * * - Negative TestCases * Tests the methods of SiedlerGame with values, that results to errors and failure * * - SystemTestCases * Tests the coordination of all methods and simulates a game with all moves programmed * Checks if the methods are being executed and the values are set correctly */ public class SiedlerGameTest { private final static int DEFAULT_WINPOINTS = 5; private final static int DEFAULT_PLAYERAMOUNT = 4; /** * Property START_SETTLEMENT_POSITIONS * * Lists all positions of Settlement for every faction in the initialization phase. * Each faction is assigned to a list of specific settlements, which represents as a list of points */ private final static Map> START_SETTLEMENT_POSITIONS = Map.of( Config.Faction.BLUE, new ArrayList<>(List.of(new Point(4, 4), new Point(5, 7))), Config.Faction.RED, new ArrayList<>(List.of(new Point(10, 4), new Point(9, 7))), Config.Faction.GREEN, new ArrayList<>(List.of(new Point(4, 18), new Point(5, 15))), Config.Faction.YELLOW, new ArrayList<>(List.of(new Point(10, 18), new Point(9, 15))) ); /** * Property START_ROADS_POSITION * * Lists all endpoints of roads for every faction in the initialization phase. * Each faction is assigned to a specific Road, which represents as a tuple of 2 points */ private final static Map>> START_ROADS_POSITIONS = Map.of( Config.Faction.BLUE, new ArrayList<>(List.of( new Tuple<>(new Point(4, 4), new Point(4, 6)), new Tuple<>(new Point(4, 6), new Point(5, 7)))), Config.Faction.RED, new ArrayList<>(List.of( new Tuple<>(new Point(10, 4), new Point(10, 6)), new Tuple<>(new Point(10, 6), new Point(9, 7)))), Config.Faction.GREEN, new ArrayList<>(List.of( new Tuple<>(new Point(4, 18), new Point(4, 16)), new Tuple<>(new Point(4, 16), new Point(5, 15)))), Config.Faction.YELLOW, new ArrayList<>(List.of( new Tuple<>(new Point(10, 18), new Point(10, 16)), new Tuple<>(new Point(10, 16), new Point(9, 15)))) ); /** * This test class contains all positive test cases. */ @Nested @DisplayName("Positive test cases") class PositiveTestcases { /** * This test will check, if the game initializes with all 4 factions. * All factions should have no resources */ @ParameterizedTest(name = "Test with {arguments} players") @ValueSource(ints = {2, 3, 4}) @DisplayName("Game initializing with different amount of players within the domain (Players have no resources), expected ok") public void TestGameInitializationWithAllPlayercounts(int playerAmount) { SiedlerGame game = new SiedlerGame(DEFAULT_WINPOINTS, playerAmount); for (Config.Faction faction: game.getPlayerFactions()) { HashMap resources = game.getCurrentPlayerResource(); Assertions.assertEquals(0, resources.get(Config.Resource.BRICK)); Assertions.assertEquals(0, resources.get(Config.Resource.GRAIN)); Assertions.assertEquals(0, resources.get(Config.Resource.LUMBER)); Assertions.assertEquals(0, resources.get(Config.Resource.ORE)); Assertions.assertEquals(0, resources.get(Config.Resource.WOOL)); game.switchToNextPlayer(); } } /** * */ @Test @DisplayName("Test") public void TestHandle7() { SiedlerGame game = startGame(); } } /** * @Class NegAtiveTestcases * * contains all negative test cases */ @Nested @DisplayName("Negative test cases") class NegativeTestcases { /** * Tests if siedlergame will start with one or five players. * 1 Player is below the minimum * 5 Players are above the maximum */ @ParameterizedTest(name = "Test with {arguments} players") @ValueSource(ints = {1, 5}) @DisplayName("Starting Siedler game with one player or 5 players, expects fail") public void startSiedlerGameWithOnePlayerorMoreThanMaximum(int playerAmount) { Exception exc = assertThrows(IllegalArgumentException.class, () -> { new SiedlerGame(DEFAULT_WINPOINTS, playerAmount); }); Assertions.assertEquals(IllegalArgumentException.class, exc.getClass()); } /** * Tests if the game crashes when passing an amount of points, that is below the minimum amount */ @Test @DisplayName("Starting Siedler game with one player, expects fail") public void startSiedlerGameWithLowerThanMinimumWinPoints() { Exception exc = assertThrows(IllegalArgumentException.class, () -> { SiedlerGame game = new SiedlerGame(1, 4); }); Assertions.assertEquals(IllegalArgumentException.class, exc.getClass()); } /** * This testcase will test, if the methods placeInitialRoad and placeInitialSettlement are overwritting * already occupied positions if the same faction or any other faction are calling the method with the same positions * * Expected: Method placeInitialRoad placeInitialSettlement should return false, independent of the current faction playing */ @Test @DisplayName("Test placeInitialRoad and placeInitialSettlement with already occupied positions") public void testPlaceInitialStructuresInAlreadyOccupiedPositions() { SiedlerGame game = startGame(); Point settlementPoint = START_SETTLEMENT_POSITIONS.get(Config.Faction.BLUE).get(1); Assertions.assertTrue(game.placeInitialSettlement(settlementPoint, false)); Assertions.assertFalse(game.placeInitialSettlement(settlementPoint, false)); Tuple roadEndpoints = START_ROADS_POSITIONS.get(Config.Faction.BLUE).get(1); Assertions.assertTrue(game.placeInitialRoad(roadEndpoints.first, roadEndpoints.second)); Assertions.assertFalse(game.placeInitialRoad(roadEndpoints.first, roadEndpoints.second)); // Switch to other player to see if the occupied fields can be overwritten, when switched to the next player/faction game.switchToNextPlayer(); Assertions.assertFalse(game.placeInitialRoad(roadEndpoints.first, roadEndpoints.second)); Assertions.assertFalse(game.placeInitialSettlement(settlementPoint, false)); } /** * This testcase will test, if the methods buildRoad, buildCity buildSettlement are overwritting * already occupied positions if the same faction or any other faction are calling the method with the same positions * * Expected: Method placeInitialRoad placeInitialSettlement should return false, independent of the current faction playing */ @Test @DisplayName("Test buildRoad, buildCity and buildSettlement with already occupied positions") public void testBuildStructuresOnOccupiedFields() { } } /** * @Class SystemTestCases * * This class simulates a running game and tests multiple sequences of this game. */ @Nested @DisplayName("System test cases") class SystemTestcases { /** * TestS if the players can place initial settlements and roads */ @Test @DisplayName("2 Players initialize a settlement and position") public void TestGameInSetupPhase() { SiedlerGame game = startGame(); Assertions.assertTrue(game.placeInitialSettlement(START_SETTLEMENT_POSITIONS.get(game.getCurrentPlayerFaction()).get(0), false)); Tuple road1 = START_ROADS_POSITIONS.get(game.getCurrentPlayerFaction()).get(0); Assertions.assertTrue(game.placeInitialRoad(road1.first, road1.second)); game.switchToNextPlayer(); Assertions.assertTrue(game.placeInitialSettlement(START_SETTLEMENT_POSITIONS.get(game.getCurrentPlayerFaction()).get(1), false)); Tuple road2 = START_ROADS_POSITIONS.get(game.getCurrentPlayerFaction()).get(1); Assertions.assertTrue(game.placeInitialRoad(road2.first, road2.second)); } /** * tests, if the players can do all pf the actions in the building phase */ @Test public void TestGameAfterSetupPhase() { SiedlerGame game = gameAfterSetupPhase(); throwDiceSeveralTimes(game, 5, 5); throwDiceSeveralTimes(game, 5, 5); throwDiceSeveralTimes(game, 5, 5); throwDiceSeveralTimes(game, 5, 5); throwDiceSeveralTimes(game, 5, 5); game.switchToNextPlayer(); throwDiceSeveralTimes(game, 6, 5); //throwDiceSeveralTimes(game, 6, 5); //throwDiceSeveralTimes(game, 6, 5); //throwDiceSeveralTimes(game, 6, 5); //throwDiceSeveralTimes(game, 6, 5); soutDistribution(game); } /** * tests, if a player wins when reached the amount of points. */ @Test @DisplayName("End of Game test") public void TestGameEnd() { } //TEMPORARY METHOD, WILL BE REMOVED SOON private static void soutDistribution(SiedlerGame game) { System.out.println("\n\nVerteilung \n\n"); for (Config.Faction faction: game.getPlayerFactions()) { HashMap resources = game.getCurrentPlayerResource(); System.out.println(faction.toString() + "\n"); System.out.println(" BRICK " + resources.get(Config.Resource.BRICK).toString()); System.out.println(" GRAIN " + resources.get(Config.Resource.GRAIN)); System.out.println(" LUMBER " + resources.get(Config.Resource.LUMBER)); System.out.println(" ORE " + resources.get(Config.Resource.ORE)); System.out.println(" WOOL " + resources.get(Config.Resource.WOOL)); game.switchToNextPlayer(); } } } /** * Initializes a game with the default values of winning points and amount of player * * @return */ private static SiedlerGame startGame() { return new SiedlerGame(DEFAULT_WINPOINTS, DEFAULT_PLAYERAMOUNT); } /** * This method will set the game to the timeline after the setup. * Players have already set each 2 Settlements and 2 Roads. * * @return SiedlerGame The game after the setup phase */ private static SiedlerGame gameAfterSetupPhase() { SiedlerGame game = startGame(); for (int i = 0; i < game.getPlayerFactions().size(); i++) { Config.Faction f = game.getCurrentPlayerFaction(); game.placeInitialSettlement(START_SETTLEMENT_POSITIONS.get(f).get(0), false); Tuple firstRoad = START_ROADS_POSITIONS.get(f).get(0); game.placeInitialRoad(firstRoad.first, firstRoad.second); game.switchToNextPlayer(); } for (int i = 0; i < game.getPlayerFactions().size(); i++) { game.switchToPreviousPlayer(); Config.Faction f = game.getCurrentPlayerFaction(); game.placeInitialSettlement(START_SETTLEMENT_POSITIONS.get(f).get(1), false); Tuple secondRoad = START_ROADS_POSITIONS.get(f).get(1); game.placeInitialRoad(secondRoad.first, secondRoad.second); } return game; } /** * This method will call the method "throwDice" multiple times and passes the set value of the dice * * @param game Type SiedlerGame, the game itself in a running state * @param dice Type int, Set Value of dice * @param amountDiceThrows Type int, The amount of dice throws */ private static void throwDiceSeveralTimes(SiedlerGame game, int dice, int amountDiceThrows) { //System.out.println(game.getCurrentPlayerFaction().toString() + " got " + dice + " and throw " + amountDiceThrows + " times"); for (int i = 0; i < amountDiceThrows; i++) { game.throwDice(dice); } } /** * This method will setup a game to a state before a player has the points * for being able to win the game * * @return SiedlerGame which is near the */ private static SiedlerGame gameNearEnd() { SiedlerGame game = gameAfterSetupPhase(); return game; } }