[Java] I want to test standard input & standard output with JUnit

Trigger

Recently I started studying competitive programming. It is troublesome to input each time when checking the operation locally. I want to do it with JUnit.

environment

Referenced articles

Qiita --Push standard input in JUnit Kenkoba's Diary-Stealing Standard I / O Nyoki Nyoki Blog --Let's replace System.out

Overview

You can change the output destination and input destination from standard output and input with setOut and setIn of the System class. You can define and set a class that inherits PrintStream for Out and ʻInputStream` for In.

Implementation

Create input class and output class.

Input class --StandardInputStream

StandardInputStream.java


import java.io.InputStream;

public class StandardInputStream extends InputStream {
    private StringBuilder sb = new StringBuilder();
    private String lf = System.getProperty("line.separator");

    /**
     *Enter the character string. Line breaks are done automatically
     * @param str input string
     */
    public void inputln(String str){
        sb.append(str).append(lf);
    }

    @Override
    public int read() {
        if (sb.length() == 0) return -1;
        int result = sb.charAt(0);
        sb.deleteCharAt(0);
        return result;
    }
}

Output class --StandardOutputStream

StandardOutputStream.java


import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.PrintStream;
import java.io.StringReader;

public class StandardOutputStream extends PrintStream {
    private BufferedReader br = new BufferedReader(new StringReader(""));

    public StandardOutputStream() {
        super(new ByteArrayOutputStream());
    }

    /**
     *Read one line of string
     * @return Characters that do not contain newlines. Null for termination
     */
    public String readLine() {
        String line = "";
        try {
            if ((line = br.readLine()) != null) return line;
            br = new BufferedReader(new StringReader(out.toString()));
            ((ByteArrayOutputStream) out).reset();
            return br.readLine();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}

Code to be tested

The code to be tested is borrowed from atcoder. PracticeA - Welcome to AtCoder

** Problem ** Given the integers a, b, c and the string s. Display the calculation result of a + b + c and the character string s side by side.

** Input **

a b c s




#### **`WelcomeToAtCoder.java`**
```java

import java.util.Scanner;

public class WelcomeToAtCoder {
    public static void main(String[] args) {
        try (Scanner sc = new Scanner(System.in)) {
            int r = sc.nextInt();
            r += sc.nextInt();
            r += sc.nextInt();
            String s = sc.next();
            System.out.println(r + " " + s);
        }
    }
}

Test code

WelcomeToAtCoderTest.java


import WelcomeToAtCoder;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import util.io.StandardInputStream;
import util.io.StandardOutputStream;

import static org.hamcrest.CoreMatchers.is;

public class WelcomeToAtCoderTest {

    private StandardInputStream in = new StandardInputStream();
    private StandardOutputStream out = new StandardOutputStream();

    @Before
    public void before() {
        System.setIn(in);
        System.setOut(out);
    }

    @After
    public void after() {
        System.setIn(null);
        System.setOut(null);
    }

    @Test
    public void main01() {
        in.inputln("1");
        in.inputln("2 3");
        in.inputln("hoge");
        WelcomeToAtCoder.main(null);
        Assert.assertThat(out.readLine(), is("6 hoge"));
    }
}

I / O is switched and tested in advance.

in conclusion

It's easy to write test cases, so I think it's easier to implement. Not limited to this, I decided to write the test properly. I want to study TDD. ~~ JUnit touched after a long time ~~

Recommended Posts

[Java] I want to test standard input & standard output with JUnit
Even in Java, I want to output true with a == 1 && a == 2 && a == 3
[Java] How to test for null with JUnit
I want to test Action Cable with RSpec test
[Java] How to get and output standard input
Even in Java, I want to output true with a == 1 && a == 2 && a == 3 (PowerMockito edition)
I want to transition screens with kotlin and java!
I want to get along with Map [Java beginner]
Even in Java, I want to output true with a == 1 && a == 2 && a == 3 (Javassist second decoction)
Even in Java, I want to output true with a == 1 && a == 2 && a == 3 (black magic edition)
(´-`) .. oO (I want to easily find the standard output "Hello".
I want to make a list with kotlin and java!
I want to make a function with kotlin and java!
I tried to interact with Java
[Java] Test private methods with JUnit
I want to implement various functions with kotlin and java!
I want to return a type different from the input element with Java8 StreamAPI reduce ()
I want to return to the previous screen with kotlin and java!
[Java] I want to perform distinct with the key in the object
I want to use DBViewer with Eclipse 2018-12! !!
I want to write a unit test!
Java automated test implementation with JUnit 5 + Gradle
[Java] Color the standard output to the terminal
From terminal to Ruby (standard input / output)
I want to display images with REST Controller of Java and Spring!
[Java] I want to make it easier because it is troublesome to input System.out.println.
Let's write Java file input / output with NIO
[CircleCI 2.0] [Java] [Maven] [JUnit] Aggregate JUnit test results with CircleCI 2.0
I want to output the day of the week
Run R from Java I want to run rJava
I tried to make Basic authentication with Java
I want to send an email in Java.
How to test interrupts during Thread.sleep with JUnit
rsync4j --I want to touch rsync in Java.
I want to play with Firestore from Rails
I tried to output multiplication table in Java
I want to write quickly from java to sqlite
I tried to break a block with java (1)
I want to perform aggregation processing with spring-batch
[Rails] I want to load CSS with webpacker
[Rails] I want to test with RSpec. We support your step [Introduction procedure]
I tried Java Lambda input / output type ~ POJO edition ~
I want to do something like "cls" in Java
[Java] I want to calculate the difference from the date
I tried to read and output CSV with Outsystems
I tried to implement TCP / IP + BIO with JAVA
[Java 11] I tried to execute Java without compiling with javac
How to input / output IBM mainframe files in Java?
I want to use ES2015 in Java too! → (´ ・ ω ・ `)
[Java] How to encrypt with AES encryption with standard library
I tried Java Lambda input / output type ~ Stream version ~
I want to dark mode with the SWT app
I want to monitor a specific file with WatchService
I want to authenticate users to Rails with Devise + OmniAuth
How to output standard from an array with forEach
I tried to implement Stalin sort with Java Collector
paiza skill check standard input / output summary [Java edition]
I wrote a test with Spring Boot + JUnit 5 now
I used to make nc (netcat) with JAVA normally
I want to redirect sound from Ubuntu with xrdp
I want to simplify the log output on Android