新人研修のプログラム課題においては、標準入出力を使うものが多々あります。
そういったものは目視で動作確認してるんですが、
やはり問題集を作るとなると、自動テストを回したい気がします。
import java.io.IOException; import java.io.InputStream; /** * 標準入力に対し、文字列入力を行う */ public class StandardInputSnatcher extends InputStream { private StringBuilder buffer = new StringBuilder(); private static String crlf = System.getProperty("line.separator"); /** * 文字列を入力する。改行は自動的に行う * @param str 入力文字列 */ public void inputln(String str) { buffer.append(str).append(crlf); } @Override public int read() throws IOException { if (buffer.length() == 0) { return -1; } int result = buffer.charAt(0); buffer.deleteCharAt(0); return result; } }
import java.io.BufferedReader; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.PrintStream; import java.io.StringReader; /** * 標準出力に対し、読み出しができるようにする */ public class StandardOutputSnatcher extends PrintStream { private BufferedReader buffer = new BufferedReader(new StringReader("")); public StandardOutputSnatcher() { super(new ByteArrayOutputStream()); } /** * 1行文の文字列を読み込む * @return 改行を含まない文字。終端の場合はnull */ public String readLine() { try { String line = ""; if ((line = buffer.readLine()) != null) { return line; } else { buffer = new BufferedReader(new StringReader(out.toString())); ((ByteArrayOutputStream) out).reset(); return buffer.readLine(); } } catch (IOException ex) { throw new RuntimeException(ex); } } }
テスト対象コード
package target; import java.io.BufferedReader; import java.io.InputStreamReader; /** * 標準入出力を使用しまくりのサンプルコード */ public class StandardIOSample { public static void main(String[] args) { try { BufferedReader stdReader = new BufferedReader(new InputStreamReader(System.in)); for (int i = 0; i < 2; i++) { System.out.println("INPUT: "); String line; line = stdReader.readLine(); System.out.println("OUTPUT: " + line); } stdReader.close(); System.out.println("PROGRAM END"); } catch (Exception e) { e.getStackTrace(); System.exit(-1); // プログラムを終了 } } }
やりたかったこと。
package target; import org.hamcrest.core.Is; import org.junit.After; import org.junit.Assert; import org.junit.Before; import org.junit.Test; import StandardInputSnatcher; import StandardOutputSnatcher; /** * 標準入出力の結果自体をテストすることができる。 */ public class TestStandardIOSample { private StandardOutputSnatcher out = new StandardOutputSnatcher(); private StandardInputSnatcher in = new StandardInputSnatcher(); @Before public void before() { System.setOut(out); System.setIn(in); } @After public void after() { System.setOut(null); System.setIn(null); } @Test public void testHello() { in.inputln("aaa"); // 標準入力への入力はあらかじめ全部与える。 in.inputln("bbb"); StandardIOSample.main(null); // テストターゲット実行 Assert.assertThat(out.readLine(), Is.is("INPUT: ")); // 出力は改行ごとに取得される Assert.assertThat(out.readLine(), Is.is("OUTPUT: aaa")); Assert.assertThat(out.readLine(), Is.is("INPUT: ")); Assert.assertThat(out.readLine(), Is.is("OUTPUT: bbb")); Assert.assertThat(out.readLine(), Is.is("PROGRAM END")); } }
うーむ、どうかなぁ。
参考資料。ありがとうございました。
http://d.hatena.ne.jp/shawshank99/20110917/1316242496