import static org.junit.Assert.assertEquals; import cs3500.tictactoe.TicTacToe; import cs3500.tictactoe.TicTacToeConsoleController; import cs3500.tictactoe.TicTacToeController; import cs3500.tictactoe.TicTacToeModel; import java.io.StringReader; import java.util.Arrays; import org.junit.Test; /** * Test cases for the tic tac toe controller, using mocks for readable and appendable. */ public class TicTacToeControllerTest { // ADDITIONAL TEST CASES TO IMPLEMENT: // Play game to completion, where there is a winner // Input where the q comes instead of an integer for the row // Input where the q comes instead of an integer for the column // Input where non-integer garbage comes instead of an integer for the row // Input where non-integer garbage comes instead of an integer for the column // Input where the move is integers, but outside the bounds of the board // Input where the move is integers, but invalid because the cell is occupied // Multiple invalid moves in a row of various kinds // Input including valid moves interspersed with invalid moves, game is played to completion // What happens when the input ends "abruptly" -- no more input, but not quit, and game not over // THIS IS NOT AN EXHAUSTIVE LIST @Test public void testSingleValidMove() { TicTacToe m = new TicTacToeModel(); StringBuilder gameLog = new StringBuilder(); TicTacToeController c = new TicTacToeConsoleController(new StringReader("2 2 q"), gameLog); c.playGame(m); assertEquals(" | | \n" + "-----------\n" + " | | \n" + "-----------\n" + " | | \n" + "Enter a move for X:\n" + " | | \n" + "-----------\n" + " | X | \n" + "-----------\n" + " | | \n" + "Enter a move for O:\n" + "Game quit! Ending game state:\n" + " | | \n" + "-----------\n" + " | X | \n" + "-----------\n" + " | | \n", gameLog.toString()); } @Test public void testBogusInputAsRow() { TicTacToe m = new TicTacToeModel(); StringReader input = new StringReader("!#$ 2 q"); StringBuilder gameLog = new StringBuilder(); TicTacToeController c = new TicTacToeConsoleController(input, gameLog); c.playGame(m); // split the output into an array of lines String[] lines = gameLog.toString().split("\n"); // check that it's the correct number of lines assertEquals(13, lines.length); // check that the last 6 lines are correct String lastMsg = String.join("\n", Arrays.copyOfRange(lines, lines.length - 6, lines.length)); assertEquals("Game quit! Ending game state:\n" + " | | \n" + "-----------\n" + " | | \n" + "-----------\n" + " | | ", lastMsg); // note no trailing \n here, because of the earlier split } @Test public void testTieGame() { TicTacToe m = new TicTacToeModel(); // note the entire sequence of user inputs for the entire game is in this one string: StringReader input = new StringReader("2 2 1 1 3 3 1 2 1 3 2 3 2 1 3 1 3 2"); StringBuilder gameLog = new StringBuilder(); TicTacToeController c = new TicTacToeConsoleController(input, gameLog); c.playGame(m); String[] lines = gameLog.toString().split("\n"); assertEquals(60, lines.length); assertEquals("Game is over! Tie game.", lines[lines.length - 1]); } @Test(expected = IllegalStateException.class) public void testFailingAppendable() { TicTacToe m = new TicTacToeModel(); StringReader input = new StringReader("2 2 1 1 3 3 1 2 1 3 2 3 2 1 3 1 3 2"); Appendable gameLog = new FailingAppendable(); TicTacToeController c = new TicTacToeConsoleController(input, gameLog); c.playGame(m); } }