Some weeks ago, during a workroom lesson in University, I’ve faced a typical TDD-addicted dilemma: how can I test driven develop a console-based Java application?
The main problem is clearly how to automatically interact with the application, which relies to System.in for
user input and to System.out
for user output.
You can use System.setIn
and System.setOut
methods, of course: but this is IMHO a dirty solution to the console-interaction testability problem, which can be resolved in a cleaner way referring to the dependency inversion principle, ubiquitous in test driven design: rather than directly referring to concrete System.in
and System.out
streams (this reference is concrete because it’s direct, not because it points to a concrete class: InputStream
is actually an abstract class), the console-based application should reference to some abstraction that encapsulates standard I/O streams dependency - for example to Scanner
(for user input) and PrintStream
(for user ouput: again, direct reference to System.out
is concrete because it’s direct, not because it points to something concrete).
So, application behaviour can be encapsulated into a classe having a constructor like this:
1 | public HelloApp(Scanner scanner, PrintStream out) |
The application main method instances such a class and invokes a method thar triggers application logic execution, simply providing Scanner
and PrintStream
that wrap standard I/O streams:
1 | public static void main(String[] args) { |
Testing code, however, can provide to HelloApp
testing oriented instances of Scanner
and PrintStream
:
1 | final Scanner scanner = new Scanner("Duke y Goofy y Donald n"); |
So, we have gracefully decoupled application logic from console-based user interactions, providing a solid framework for automated application testing and, even more satisfying for TDD addicted, for Test Driven Development.
A complete example can be found here: https://bitbucket.org/pietrom/automatically-testing-the-console
Code repository can be cloned using git:git clone https://bitbucket.org/pietrom/automatically-testing-the-console.git
This post was originally published here on 21/05/2012.