Итак, я разработал эту очень простую игру TicTacToe. Я хочу протестировать метод, приведенный ниже:
public class Board {
private Scanner scan = new Scanner(System.in);
public int inputBoardSize() {
while (flag) {
System.out.print("Enter the number of grids you want to play with:");
try {
boardSize = Integer.parseInt(scan.next());
if (boardSize < 3 || boardSize > 10) {
System.out.println("Please choose a board size between 3 and 10");
continue;
}
flag = false;
break;
} catch (NumberFormatException e) {
e.getMessage();
System.out.println("Please enter a number");
continue;
}
}
printBoard(boardSize);
return boardSize;
}
Но я новичок в модульном тестировании и мне нужна небольшая помощь. Я не могу понять, как проверить два условия
Мой класс тестирования для второго условия выглядит примерно так:
public class BoardTest extends TestCase {
@Test
public void test() {
Board board = new Board();
String input = "2";
InputStream in = new ByteArrayInputStream(input.getBytes());
System.setIn(in);
}
}
Я не могу понять, что делать дальше.
Вам нужно использовать то, что называется Внедрение зависимости. Предоставьте экземпляр Scanner вашему методу. В производстве вы можете использовать System.in, тогда как при тестировании вы можете использовать другой InputStream, который будет воспроизводить ваш тестовый пример.
Я использовал InputStream. Примерно так: @Test public void test () {Board board = new Board (); Строка input = "2"; InputStream in = новый ByteArrayInputStream (input.getBytes ()); System.setIn (вход); }
Итак, что мешает вам создавать копии этого метода тестирования, в которых вы меняете "2" на "11" или "not a number"?




Добавьте следующие конструкторы:
public class Board {
private Scanner;
public Board() {
this(System.in);
}
public Board(InputStream in) {
scan = new Scanner(in);
}
}
Затем вы можете предоставить InputStream извне при тестировании класса.
Вы можете выделить логику проверки в отдельный метод, а затем протестировать этот метод. Это устраняет необходимость взаимодействовать или вводить объект Scanner. Извлеченный код будет напоминать
public int inputBoardSize() {
while (flag) {
System.out.print("Enter the number of grids you want to play with:");
validateBoardSize(scan.next());
}
printBoard(boardSize);
return boardSize;
}
protected void validateBoardSize(String input) {
try {
boardSize = Integer.parseInt(input);
if (boardSize < 3 || boardSize > 10) {
System.out.println("Please choose a board size between 3 and 10");
}
else {
flag = false;
}
}
catch (NumberFormatException e) {
e.getMessage();
System.out.println("Please enter a number");
}
}
Вот некоторые тестовые примеры JUnit для проверки метода validateBoardSize:
public class BoardTest {
private static final String OUT_OUT_BOUNDS_ERROR_MESSAGE = "Please choose a board size between 3 and 10";
private static final String NFE_ERROR_MESSAGE = "Please enter a number";
private final ByteArrayOutputStream outContent = new ByteArrayOutputStream();
private Board board;
@Before
public void setUp() {
System.setOut(new PrintStream(outContent));
board = new Board();
}
@Test
public void setBoardSizeOf2EnsureErrorMessageDisplayed() {
board.validateBoardSize("2");
assertOutOfBoundsErrorMessageDisplayed();
}
private void assertOutOfBoundsErrorMessageDisplayed() {
assertEquals(OUT_OUT_BOUNDS_ERROR_MESSAGE, outContent.toString().trim());
}
@Test
public void setBoardSizeOf3EnsureNoErrorMessageDisplayed() {
board.validateBoardSize("3");
assertNoErrorMessageDisplayed();
}
private void assertNoErrorMessageDisplayed() {
assertEquals("", outContent.toString().trim());
}
@Test
public void setBoardSizeOf4EnsureNoErrorMessageDisplayed() {
board.validateBoardSize("4");
assertNoErrorMessageDisplayed();
}
@Test
public void setBoardSizeOf9EnsureNoErrorMessageDisplayed() {
board.validateBoardSize("9");
assertNoErrorMessageDisplayed();
}
@Test
public void setBoardSizeOf10EnsureNoErrorMessageDisplayed() {
board.validateBoardSize("10");
assertNoErrorMessageDisplayed();
}
@Test
public void setBoardSizeOf11EnsureErrorMessageDisplayed() {
board.validateBoardSize("11");
assertOutOfBoundsErrorMessageDisplayed();
}
@Test
public void setBoardSizeWithInvalidNumberEnsureInvalidNumberMessageDisplayed() {
board.validateBoardSize("blah");
assertInvalidNumberMessageDisplayed();
}
private void assertInvalidNumberMessageDisplayed() {
assertEquals(NFE_ERROR_MESSAGE, outContent.toString().trim());
}
}
Обратите внимание, что поскольку ваша программа обозначает ошибки через сообщения, отправленные через стандартный вывод (в отличие от выдачи исключений), тесты должны перехватывать выводимое сообщение, отправленное на стандартный вывод, и сравнивать строку, чтобы увидеть, что говорится в сообщении. Следовательно, в setUp() для OutputStream для стандартного вывода устанавливается экземпляр OutputStream, строковое значение которого можно сравнить с помощью методов тестирования: System.setOut(new PrintStream(outContent)). Чтобы проверить вывод, вы можете просто извлечь строковое значение OutputStream: outContent.toString().trim(). Обратите внимание, что trim() используется для удаления завершающего символа (ов) новой строки, поскольку println будет включать их в сообщение об ошибке. Новые строки чувствительны к ОС, поэтому их удаление значительно упрощает сравнение строки.
Для получения дополнительной информации см. Тест JUnit для System.out.println().
Большое спасибо! Это очень помогло понять, как это работает.
Поэтому я использую System.err вместо System.out. И модульный тест не работает org.junit.ComparisonFailure: ожидалось: <[Пожалуйста, введите число]>, но было: <[]>. Есть ли другой способ проверить операторы system.err?
Есть способ проверить стандартную ошибку вместо стандартного вывода. В методе setUp() замените System.setOut(new PrintStream(outContent)) на System.setErr(new PrintStream(outContent)). Это позволит вам захватить и протестировать вывод, напечатанный на стандартную ошибку. Для получения дополнительной информации о том, как это работает, см. Документация по System.setErr.
Как вы проверяете 3-е условие: входные является 3 и 10?