You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

337 lines
12 KiB

  1. package de.tims.tictactoe;
  2. import static org.junit.jupiter.api.Assertions.assertArrayEquals;
  3. import static org.junit.jupiter.api.Assertions.assertEquals;
  4. import java.awt.Component;
  5. import java.util.stream.Stream;
  6. import javax.swing.JButton;
  7. import javax.swing.JPanel;
  8. import org.junit.jupiter.api.BeforeAll;
  9. import org.junit.jupiter.api.Test;
  10. import org.junit.jupiter.api.TestInstance;
  11. import org.junit.jupiter.api.TestInstance.Lifecycle;
  12. import org.junit.jupiter.params.ParameterizedTest;
  13. import org.junit.jupiter.params.provider.Arguments;
  14. import org.junit.jupiter.params.provider.MethodSource;
  15. @TestInstance(Lifecycle.PER_CLASS)
  16. class GameLogicTest {
  17. private final int SIZE = 3;
  18. private GameLogic game;
  19. @BeforeAll
  20. void setUpBeforeClass() throws Exception {
  21. this.game = new GameLogic(SIZE);
  22. }
  23. @Test
  24. void createGameLogicTest() {
  25. GameLogic expectedResult = this.game;
  26. GameLogic realResult = new GameLogic(SIZE);
  27. assertEquals(expectedResult.getClass(), realResult.getClass());
  28. }
  29. @Test
  30. void getBoardTest() {
  31. // @formatter:off
  32. char[][] expectedResult = new char[][]{{'-', '-', '-'},
  33. {'-', '-', '-'},
  34. {'-', '-', '-'}};
  35. // @formatter:on
  36. char[][] realResult = this.game.getBoard();
  37. assertArrayEquals(expectedResult, realResult);
  38. }
  39. @Test
  40. void createGameLogicWithGivenBoardTest() {
  41. // @formatter:off
  42. char[][] expectedResult = new char[][]{{'x', '-', '-'},
  43. {'-', 'o', '-'},
  44. {'x', '-', '-'}};
  45. // @formatter:on
  46. char[][] givenBoard = expectedResult;
  47. char[][] realResult = new GameLogic(givenBoard).getBoard();
  48. assertArrayEquals(expectedResult, realResult);
  49. }
  50. @Test
  51. void generateGUITest() {
  52. JPanel expectedResult = new JPanel();
  53. JPanel realResult = this.game.generateGUI();
  54. assertEquals(expectedResult.getClass(), realResult.getClass());
  55. }
  56. @Test
  57. void numberOfGUIFieldsTest() {
  58. int expectedResult = (int) Math.pow(SIZE, 2);
  59. int realResult = 0;
  60. JPanel gui = this.game.generateGUI();
  61. Component[] components = gui.getComponents();
  62. for (Component component : components) {
  63. if (component instanceof JButton)
  64. realResult++;
  65. }
  66. assertEquals(expectedResult, realResult);
  67. }
  68. @Test
  69. void getCurrentPlayerTest() {
  70. GameLogic game = new GameLogic(SIZE);
  71. char expectedResult = 'x';
  72. char realResult = game.getCurrentPlayer();
  73. assertEquals(expectedResult, realResult);
  74. }
  75. @Test
  76. void switchPlayerTest() {
  77. GameLogic game = new GameLogic(SIZE);
  78. game.switchPlayer();
  79. char expectedResult = 'o';
  80. char realResult = game.getCurrentPlayer();
  81. assertEquals(expectedResult, realResult);
  82. }
  83. @Test
  84. void resetBoardTest() {
  85. GameLogic game = new GameLogic(SIZE);
  86. game.setField(1, 2, 'x');
  87. // @formatter:off
  88. char[][] expectedResult = new char[][]{{'-', '-', '-'},
  89. {'-', '-', '-'},
  90. {'-', '-', '-'}};
  91. // @formatter:on
  92. game.resetBoard();
  93. char[][] realResult = game.getBoard();
  94. assertArrayEquals(expectedResult, realResult);
  95. }
  96. @ParameterizedTest(name = "[{index}] {0} -> {2} fields")
  97. @MethodSource("testCasesForCountPlayfields")
  98. void fieldCountTest(String testName, int size, int expectedResult) {
  99. GameLogic game = new GameLogic(size);
  100. int realResult = game.countFields();
  101. assertEquals(expectedResult, realResult);
  102. }
  103. @ParameterizedTest(name = "[{index}] {0}")
  104. @MethodSource("testCasesForSetField")
  105. void setFieldTest(String testName, int column, int row, char player, char[][] expectedResult) {
  106. this.game.setField(column, row, player);
  107. char[][] realResult = this.game.getBoard();
  108. assertArrayEquals(expectedResult, realResult);
  109. }
  110. @ParameterizedTest(name = "[{index}] {0}")
  111. @MethodSource("testCasesForCheckEmptyField")
  112. void fieldIsEmptyTest(String testName, int columnToCheck, int rowToCheck, boolean expectedResult, char[][] board) {
  113. GameLogic game = new GameLogic(board);
  114. boolean realResult = game.fieldIsEmpty(columnToCheck, rowToCheck);
  115. assertEquals(expectedResult, realResult);
  116. }
  117. @ParameterizedTest(name = "[{index}] {0}: should be {2}")
  118. @MethodSource("testCasesForCheckForWin")
  119. void checkForWinTest(String testName, char player, boolean expectedResult, char[][] boardToCheck) {
  120. boolean realResult = new GameLogic(boardToCheck).checkForWin(player);
  121. assertEquals(expectedResult, realResult);
  122. }
  123. @ParameterizedTest(name = "[{index}] {0}: should be {1}")
  124. @MethodSource("testCasesForCheckEndOfGame")
  125. void checkEndOfGameTest(String testName, boolean expectedResult, char[][] boardToCheck) {
  126. boolean realResult = new GameLogic(boardToCheck).checkEndOfGame();
  127. assertEquals(expectedResult, realResult);
  128. }
  129. @ParameterizedTest(name = "[{index}] {0}: should be {1}")
  130. @MethodSource("testCasesForCheckButtonState")
  131. void buttonStateTest(String testName, boolean expectedResult, boolean doClick, int column, int row) throws InterruptedException {
  132. GameLogic game = new GameLogic(SIZE);
  133. game.generateGUI();
  134. JButton currentField = game.getGUIField(0, 0);
  135. if (doClick)
  136. currentField.doClick();
  137. boolean realResult = !currentField.getText().isEmpty();
  138. assertEquals(expectedResult, realResult);
  139. }
  140. // @formatter:off
  141. private static Stream<Arguments> testCasesForCountPlayfields() {
  142. return Stream.of(Arguments.of("1x1 board with too few fields", 1, 9),
  143. Arguments.of("2x2 board with too few fields", 2, 9),
  144. Arguments.of("3x3 board with 9 playfields", 3, 9),
  145. Arguments.of("4x4 board with 16 playfields", 4, 16),
  146. Arguments.of("5x5 board with 25 playfields", 5, 25));
  147. }
  148. private static Stream<Arguments> testCasesForSetField() {
  149. return Stream.of(
  150. Arguments.of("set field [0][0] for player 1", 0, 0, 'x', new char[][]
  151. {{'x', '-', '-'},
  152. {'-', '-', '-'},
  153. {'-', '-', '-'}}),
  154. Arguments.of("set field [1][0] for player 2", 1, 0, 'o', new char[][]
  155. {{'x', '-', '-'},
  156. {'o', '-', '-'},
  157. {'-', '-', '-'}}),
  158. Arguments.of("try to set occupied field [1][0] for player 1", 1, 0, 'x', new char[][]
  159. {{'x', '-', '-'},
  160. {'o', '-', '-'},
  161. {'-', '-', '-'}})
  162. );
  163. }
  164. private static Stream<Arguments> testCasesForCheckEmptyField() {
  165. return Stream.of(
  166. Arguments.of("check an empty field", 0, 0, true, new char[][]
  167. {{'-', '-', '-'},
  168. {'-', '-', '-'},
  169. {'-', '-', '-'}}),
  170. Arguments.of("check a field set by player 1", 0, 0, false, new char[][]
  171. {{'x', '-', '-'},
  172. {'-', '-', '-'},
  173. {'-', '-', '-'}}),
  174. Arguments.of("check a field set by player 2", 0, 0, false, new char[][]
  175. {{'o', '-', '-'},
  176. {'-', '-', '-'},
  177. {'-', '-', '-'}})
  178. );
  179. }
  180. private static Stream<Arguments> testCasesForCheckForWin() {
  181. return Stream.of(
  182. Arguments.of("check win in column 0 for player 1", 'x', true, new char[][]
  183. {{'x', '-', '-'},
  184. {'x', '-', '-'},
  185. {'x', '-', '-'}}),
  186. Arguments.of("check win in column 1 for player 1", 'x', true, new char[][]
  187. {{'-', 'x', '-'},
  188. {'-', 'x', '-'},
  189. {'-', 'x', '-'}}),
  190. Arguments.of("check win in column 2 for player 1", 'x', true, new char[][]
  191. {{'-', '-', 'x'},
  192. {'-', '-', 'x'},
  193. {'-', '-', 'x'}}),
  194. Arguments.of("check win in column 0 for player 2", 'o', true, new char[][]
  195. {{'o', '-', '-'},
  196. {'o', '-', '-'},
  197. {'o', '-', '-'}}),
  198. Arguments.of("check win in row 0 for player 1", 'x', true, new char[][]
  199. {{'x', 'x', 'x'},
  200. {'-', '-', '-'},
  201. {'-', '-', '-'}}),
  202. Arguments.of("check win in row 0 for player 2", 'o', true, new char[][]
  203. {{'o', 'o', 'o'},
  204. {'-', '-', '-'},
  205. {'-', '-', '-'}}),
  206. Arguments.of("check win in row 1 for player 2", 'o', true, new char[][]
  207. {{'-', '-', '-'},
  208. {'o', 'o', 'o'},
  209. {'-', '-', '-'}}),
  210. Arguments.of("check win in row 2 for player 2", 'o', true, new char[][]
  211. {{'-', '-', '-'},
  212. {'-', '-', '-'},
  213. {'o', 'o', 'o'}}),
  214. Arguments.of("check win in column 0 for player 1 with full board", 'x', true, new char[][]
  215. {{'x', 'o', 'o'},
  216. {'x', 'o', 'x'},
  217. {'x', 'x', 'o'}}),
  218. Arguments.of("check win in column 1 for player 2 with full board", 'o', true, new char[][]
  219. {{'x', 'o', 'o'},
  220. {'x', 'o', 'x'},
  221. {'o', 'o', 'x'}}),
  222. Arguments.of("check win in column 2 for player 2 with full board", 'o', true, new char[][]
  223. {{'x', 'o', 'o'},
  224. {'x', 'x', 'o'},
  225. {'o', 'o', 'o'}}),
  226. Arguments.of("check win in row 0 for player 1 with full board", 'x', true, new char[][]
  227. {{'x', 'x', 'x'},
  228. {'x', 'o', 'o'},
  229. {'o', 'o', 'x'}}),
  230. Arguments.of("check win in row 1 for player 1 with full board", 'x', true, new char[][]
  231. {{'x', 'x', 'o'},
  232. {'x', 'x', 'x'},
  233. {'o', 'o', 'x'}}),
  234. Arguments.of("check win in row 2 for player 2 with full board", 'o', true, new char[][]
  235. {{'x', 'x', 'o'},
  236. {'o', 'x', 'x'},
  237. {'o', 'o', 'o'}}),
  238. Arguments.of("check win in column 0 for player 2", 'o', false, new char[][]
  239. {{'o', '-', '-'},
  240. {'o', '-', '-'},
  241. {'-', '-', '-'}}),
  242. Arguments.of("check a draw for player 2", 'o', false, new char[][]
  243. {{'o', 'o', 'x'},
  244. {'o', 'x', 'x'},
  245. {'x', 'x', 'o'}}),
  246. Arguments.of("check a draw for player 1", 'x', false, new char[][]
  247. {{'o', 'o', 'x'},
  248. {'o', 'o', 'x'},
  249. {'x', 'x', 'o'}}),
  250. Arguments.of("check diagonal left win for player 1", 'x', true, new char[][]
  251. {{'x', 'o', 'x'},
  252. {'x', 'x', 'o'},
  253. {'o', 'o', 'x'}}),
  254. Arguments.of("check diagonal right win for player 2", 'o', true, new char[][]
  255. {{'x', 'x', 'o'},
  256. {'x', 'o', 'o'},
  257. {'o', 'x', 'x'}})
  258. );
  259. }
  260. private static Stream<Arguments> testCasesForCheckEndOfGame() {
  261. return Stream.of(
  262. Arguments.of("check empty board", false, new char[][]
  263. {{'-', '-', '-'},
  264. {'-', '-', '-'},
  265. {'-', '-', '-'}}),
  266. Arguments.of("end of game with win for player 1", true, new char[][]
  267. {{'x', 'o', 'x'},
  268. {'x', 'x', 'o'},
  269. {'x', 'o', 'o'}}),
  270. Arguments.of("end of game with win for player 2", true, new char[][]
  271. {{'x', 'x', 'o'},
  272. {'o', 'o', 'o'},
  273. {'x', 'o', 'x'}}),
  274. Arguments.of("check tied game", true, new char[][]
  275. {{'x', 'x', 'o'},
  276. {'o', 'x', 'o'},
  277. {'x', 'o', 'x'}}),
  278. Arguments.of("check not yet finished game", false, new char[][]
  279. {{'x', 'x', '-'},
  280. {'o', 'o', '-'},
  281. {'x', 'o', 'x'}})
  282. );
  283. }
  284. private static Stream<Arguments> testCasesForCheckButtonState() {
  285. return Stream.of(
  286. Arguments.of("trigger gui field [0][0]", true, true, 0, 0),
  287. Arguments.of("dont't trigger gui field [1][1]", false, false, 1, 1)
  288. );
  289. }
  290. // @formatter:on
  291. }