package de.tims.tictactoe; import static org.junit.jupiter.api.Assertions.assertArrayEquals; import static org.junit.jupiter.api.Assertions.assertEquals; import java.awt.Component; import java.util.stream.Stream; import javax.swing.JButton; import javax.swing.JComponent; import javax.swing.JPanel; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.TestInstance; import org.junit.jupiter.api.TestInstance.Lifecycle; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; @TestInstance(Lifecycle.PER_CLASS) class GameLogicTest { private final int SIZE = 3; private GameLogic game; @BeforeAll void setUpBeforeClass() throws Exception { this.game = new GameLogic(SIZE); } @Test void createGameLogicTest() { GameLogic expectedResult = this.game; GameLogic realResult = new GameLogic(SIZE); assertEquals(expectedResult.getClass(), realResult.getClass()); } @Test void getBoardTest() { char[][] expectedResult = new char[][]{{'-', '-', '-'}, {'-', '-', '-'}, {'-', '-', '-'}}; char[][] realResult = this.game.getBoard(); assertArrayEquals(expectedResult, realResult); } @Test void createGameLogicWithGivenBoardTest() { char[][] expectedResult = new char[][]{{'x', '-', '-'}, {'-', 'o', '-'}, {'x', '-', '-'}}; char[][] givenBoard = expectedResult; char[][] realResult = new GameLogic(givenBoard).getBoard(); assertArrayEquals(expectedResult, realResult); } @Test void generateGUITest() { JPanel expectedResult = new JPanel(); JPanel realResult = game.generateGUI(); assertEquals(expectedResult.getClass(), realResult.getClass()); } @Test void numberOfGUIFieldsTest() { int realResult = 0; int expectedResult = (int) Math.pow(SIZE, 2); JPanel gui = game.generateGUI(); Component[] components = gui.getComponents(); for (Component component : components) { if (component instanceof JButton) realResult++; } assertEquals(expectedResult, realResult); } @ParameterizedTest(name = "[{index}] {0} -> {2} fields") @MethodSource("testCasesForCountPlayfields") void fieldCountTest(String testName, int size, int expectedResult) { GameLogic game = new GameLogic(size); int realResult = game.countFields(); assertEquals(expectedResult, realResult); } @ParameterizedTest(name = "[{index}] {0}") @MethodSource("testCasesForSetField") void setFieldTest(String testName, int column, int row, char player, char[][] expectedResult) { this.game.setField(column, row, player); char[][] realResult = this.game.getBoard(); assertArrayEquals(expectedResult, realResult); } @ParameterizedTest(name = "[{index}] {0}") @MethodSource("testCasesForCheckEmptyField") void fieldIsEmptyTest(String testName, int columnToCheck, int rowToCheck, boolean expectedResult, char[][] board) { GameLogic game = new GameLogic(board); boolean realResult = game.fieldIsEmpty(columnToCheck, rowToCheck); assertEquals(expectedResult, realResult); } @ParameterizedTest(name = "[{index}] {0}: should be {2}") @MethodSource("testCasesForCheckForWin") void checkForWinTest(String testName, char player, boolean expectedResult, char[][] boardToCheck) { boolean realResult = new GameLogic(boardToCheck).checkForWin(player); assertEquals(expectedResult, realResult); } @ParameterizedTest(name = "[{index}] {0}: should be {1}") @MethodSource("testCasesForCheckEndOfGame") void checkEndOfGameTest(String testName, boolean expectedResult, char[][] boardToCheck) { boolean realResult = new GameLogic(boardToCheck).checkEndOfGame(); assertEquals(expectedResult, realResult); } private static Stream testCasesForCountPlayfields() { return Stream.of( Arguments.of("1x1 board with too few fields", 1, 9), Arguments.of("2x2 board with too few fields", 2, 9), Arguments.of("3x3 board with 9 playfields", 3, 9), Arguments.of("4x4 board with 16 playfields", 4, 16), Arguments.of("5x5 board with 25 playfields", 5,25) ); } private static Stream testCasesForSetField() { return Stream.of( Arguments.of("set field [0][0] for player 1", 0, 0, 'x', new char[][] {{'x', '-', '-'}, {'-', '-', '-'}, {'-', '-', '-'}}), Arguments.of("set field [1][0] for player 2", 1, 0, 'o', new char[][] {{'x', '-', '-'}, {'o', '-', '-'}, {'-', '-', '-'}}), Arguments.of("try to set occupied field [1][0] for player 1", 1, 0, 'x', new char[][] {{'x', '-', '-'}, {'o', '-', '-'}, {'-', '-', '-'}}) ); } private static Stream testCasesForCheckEmptyField() { return Stream.of( Arguments.of("check an empty field", 0, 0, true, new char[][] {{'-', '-', '-'}, {'-', '-', '-'}, {'-', '-', '-'}}), Arguments.of("check a field set by player 1", 0, 0, false, new char[][] {{'x', '-', '-'}, {'-', '-', '-'}, {'-', '-', '-'}}), Arguments.of("check a field set by player 2", 0, 0, false, new char[][] {{'o', '-', '-'}, {'-', '-', '-'}, {'-', '-', '-'}}) ); } private static Stream testCasesForCheckForWin() { return Stream.of( Arguments.of("check win in column 0 for player 1", 'x', true, new char[][] {{'x', '-', '-'}, {'x', '-', '-'}, {'x', '-', '-'}}), Arguments.of("check win in column 1 for player 1", 'x', true, new char[][] {{'-', 'x', '-'}, {'-', 'x', '-'}, {'-', 'x', '-'}}), Arguments.of("check win in column 2 for player 1", 'x', true, new char[][] {{'-', '-', 'x'}, {'-', '-', 'x'}, {'-', '-', 'x'}}), Arguments.of("check win in column 0 for player 2", 'o', true, new char[][] {{'o', '-', '-'}, {'o', '-', '-'}, {'o', '-', '-'}}), Arguments.of("check win in row 0 for player 1", 'x', true, new char[][] {{'x', 'x', 'x'}, {'-', '-', '-'}, {'-', '-', '-'}}), Arguments.of("check win in row 0 for player 2", 'o', true, new char[][] {{'o', 'o', 'o'}, {'-', '-', '-'}, {'-', '-', '-'}}), Arguments.of("check win in row 1 for player 2", 'o', true, new char[][] {{'-', '-', '-'}, {'o', 'o', 'o'}, {'-', '-', '-'}}), Arguments.of("check win in row 2 for player 2", 'o', true, new char[][] {{'-', '-', '-'}, {'-', '-', '-'}, {'o', 'o', 'o'}}), Arguments.of("check win in column 0 for player 1 with full board", 'x', true, new char[][] {{'x', 'o', 'o'}, {'x', 'o', 'x'}, {'x', 'x', 'o'}}), Arguments.of("check win in column 1 for player 2 with full board", 'o', true, new char[][] {{'x', 'o', 'o'}, {'x', 'o', 'x'}, {'o', 'o', 'x'}}), Arguments.of("check win in column 2 for player 2 with full board", 'o', true, new char[][] {{'x', 'o', 'o'}, {'x', 'x', 'o'}, {'o', 'o', 'o'}}), Arguments.of("check win in row 0 for player 1 with full board", 'x', true, new char[][] {{'x', 'x', 'x'}, {'x', 'o', 'o'}, {'o', 'o', 'x'}}), Arguments.of("check win in row 1 for player 1 with full board", 'x', true, new char[][] {{'x', 'x', 'o'}, {'x', 'x', 'x'}, {'o', 'o', 'x'}}), Arguments.of("check win in row 2 for player 2 with full board", 'o', true, new char[][] {{'x', 'x', 'o'}, {'o', 'x', 'x'}, {'o', 'o', 'o'}}), Arguments.of("check win in column 0 for player 2", 'o', false, new char[][] {{'o', '-', '-'}, {'o', '-', '-'}, {'-', '-', '-'}}), Arguments.of("check a draw for player 2", 'o', false, new char[][] {{'o', 'o', 'x'}, {'o', 'x', 'x'}, {'x', 'x', 'o'}}), Arguments.of("check a draw for player 1", 'x', false, new char[][] {{'o', 'o', 'x'}, {'o', 'o', 'x'}, {'x', 'x', 'o'}}), Arguments.of("check diagonal left win for player 1", 'x', true, new char[][] {{'x', 'o', 'x'}, {'x', 'x', 'o'}, {'o', 'o', 'x'}}), Arguments.of("check diagonal right win for player 2", 'o', true, new char[][] {{'x', 'x', 'o'}, {'x', 'o', 'o'}, {'o', 'x', 'x'}}) ); } private static Stream testCasesForCheckEndOfGame() { return Stream.of( Arguments.of("check empty board", false, new char[][] {{'-', '-', '-'}, {'-', '-', '-'}, {'-', '-', '-'}}), Arguments.of("end of game with win for player 1", true, new char[][] {{'x', 'o', 'x'}, {'x', 'x', 'o'}, {'x', 'o', 'o'}}), Arguments.of("end of game with win for player 2", true, new char[][] {{'x', 'x', 'o'}, {'o', 'o', 'o'}, {'x', 'o', 'x'}}), Arguments.of("check tied game", true, new char[][] {{'x', 'x', 'o'}, {'o', 'x', 'o'}, {'x', 'o', 'x'}}), Arguments.of("check not yet finished game", false, new char[][] {{'x', 'x', '-'}, {'o', 'o', '-'}, {'x', 'o', 'x'}}) ); } }