Unit Tests for Console Output
I’ve received several questions about how to test console output, such as verifying that the Quoridor board is printed correctly. Here’s some rough (pseudo)code to facilitate testing:
public class Quoridor {
// ...
public void printBoard() {
printBoard(System.out);
}
void printBoard(PrintStream printStream) {
// replace "System.out" with "printStream"
}
// ...
}
The corresponding unit test is as follows:
public class QuoridorTest {
// ...
@Test
public void printBoardTest() {
ByteArrayOutputStream stream = new ByteArrayOutputStream();
quoridor.printBoard(new PrintStream(stream));
actual = stream.toString();
expected = /* String representation of board */;
Assertions.assertEquals(expected, actual);
}
// ...
}
In the Quoridor
class, the overloaded printBoard
method that accepts a
PrintStream
as a parameter has package visibility to facilitate testing; it
isn’t expected that this method will be used in practice (though other classes
in the same package certainly could use it if desired). In the unit test, the
ByteArrayOutputStream
effectively captures the output, allowing its
comparison with the expected output.
One potential issue that isn’t highlighted in the code is line endings, which
are system dependent. That is, System.out.println(...)
uses \r\n
to end
lines on Windows, but \n
on Linux, which means that the unit tests may pass
on your own machine but not when executed by the CI jobs on GitHub. You can
avoid this problem by using System.lineSeparator()
or %n
to end lines
printed by System.out.printf(...)
instead of hard-coded new line characters.