1

I am aware that this might be a duplicate (forgive me if that is the case), any one of these two could be a duplicate to what I'm searching for, but as I have no idea if they do answer my problem I'll ask it here anyway.

JUnit test for console input and output,
JUnit test for System.out.println()

My assignment (school):

We're to write a simple compiler that tracks the colour of a pencil and movement across the x- and y-axis. i.e.

Input:

% This is a comment
% Now we're making a square
DOWN.
FORW 1. LEFT 90.
FORW 1. LEFT 90.
FORW 1. LEFT 90.
FORW 1. LEFT 90.

Output:

#0000FF 0.0000 0.0000 1.0000 0.0000
#0000FF 1.0000 0.0000 1.0000 1.0000
#0000FF 1.0000 1.0000 0.0000 1.0000
#0000FF 0.0000 1.0000 0.0000 0.0000

My problem:

To get a passing grade our code is subjected to a rigorous series of tests, many of these give you no clue as to what went wrong. i.e.

"A random generated program on 1215 bytes, with 1 syntax error"

So I feel that a great part of this assignment is to learn how to write good test-code, I've been thinking about trying to use JUnit (or perhaps I should use something else?). My input comes from System.in and the output goes through System.out.println().

Hopefully there is a way to do this by using existing textfiles (went through some difficulties earlier with assertEquals and super long strings full of \n). To clarify: I want to test I/O (through text-files) of my Java-program and I can't find any good clear explanation on how I can do this.

Community
  • 1
  • 1
MrJalapeno
  • 1,532
  • 3
  • 18
  • 37

2 Answers2

0

The most important part writing unit tests is separating the code you want to test from boilerplate/well-tested code out of given frameworks - so you might create classes which create the output but separate the part of reading the input from System.in and writing it to System.out from your business logic to concentrate on the "serious" parts.

Smutje
  • 17,733
  • 4
  • 24
  • 41
0

I came against this problem when refactoring some legacy code recently. I extracted input/output into new classes and made them dependency of my program. Using dependency injection I inserted mocks/fakes so I could define what will be the input and what the output should be.

public class InputReader {

    private static final Scanner SCANNER = new Scanner(System.in);

    public String nextLine() {
        return SCANNER.nextLine();
    }

}

public class OutputPrinter {

    public void println(String string) {
        System.out.println(string);
    }

}

And then the test using mockito:

public class MainProgramTest {

    private final InputReader inputReader = mock(InputReader.class);
    private final OutputPrinter outputPrinter = mock(OutputPrinter.class);

    @Test
    public void playsSimpleGame() {
        when(inputReader.nextLine())
                .thenReturn("hello")
                .thenReturn("help")
                .thenReturn("exit");

        MainProgram mainProgram = new MainProgram(inputReader, outputPrinter);
        mainProgram.run();

        InOrder inOrder = inOrder(inputReader, outputPrinter);
        inOrder.verify(inputReader).nextLine(); // -> "hello"
        inOrder.verify(outputPrinter).println("\"hello\" is not recognised command, type \"help\" for known commands");
        inOrder.verify(inputReader).nextLine(); // -> "help"
        inOrder.verify(outputPrinter).println("This is help, the only known commands are \"help\" and \"exit\"");
        inOrder.verify(inputReader).nextLine(); // -> "exit"
        inOrder.verify(outputPrinter).println("Goodbye");
        verifyNoMoreInteractions(inputReader, outputPrinter);
    }

}
Jaroslaw Pawlak
  • 5,538
  • 7
  • 30
  • 57