Redirecting stdout to a new PrintStream is an easy way
to test simple console output in Java. But as my Tic-Tac-Toe game has
grown more complex, the tests I wrote using this pattern have started
to stink. There’s a lot of duplicated code (create the stream,
redirect, tear down with each test), each test uses a hand-constructed
string filled with finicky newline characters, and tests are prone to
break when unrelated view components change the way they print to the
screen. Inspired by my input
queue,
I created an OutputRecorder class that extends PrintStream and
captures output string by string for later playback:
@TestpublicvoidcontrollerShouldPassErrorMessageToViewOnInvalidMove()throwsGameOverException{view.enqueueInput("middle center");view.enqueueInput("middle center");controller.newGame();System.setOut(outputRecorder);try{controller.playRound();}catch(NoSuchElementExceptione){outputRecorder.discardFirstNStrings(4);Stringoutput=outputRecorder.popFirstOutput();assertEquals("Square is already full.",output);}System.setOut(stdout);view.clearInput();}
The utility might not be immediately obvious, but capturing output
string by string has already put an end to tracking down small
differences between expected and actual output that come from an extra
space or misplaced newline.