標準出力に結果を出すプログラムをJUnit 4.1でテストする方法とかで解説されていますが、
それを汎用的にしてみました。
名付けて、StandardOutputSnatcherクラスです。
略してSOS!
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.io.BufferedOutputStream; | |
import java.io.ByteArrayOutputStream; | |
import java.io.PrintStream; | |
/** | |
* 標準出力・標準エラー出力の出力先を奪うクラスです. | |
* テストなどでコンソール出力の内容を知りたい場合に使います. | |
* このクラスはスレッドセーフではありません。 | |
* マルチスレッド環境では利用しないでください。 | |
*/ | |
public final class StandardOutputSnatcher { | |
/** シングルトンパターンのためのインスタンス. */ | |
private static final StandardOutputSnatcher INSTANCE = | |
new StandardOutputSnatcher(); | |
/** 元の標準出力. */ | |
private PrintStream nativeOut = null; | |
/** 元の標準エラー出力. */ | |
private PrintStream nativeErr = null; | |
/** 変更後の標準出力. */ | |
private ByteArrayOutputStream snatchedOut = new ByteArrayOutputStream(); | |
/** 変更後の標準エラー出力. */ | |
private ByteArrayOutputStream snatchedErr = new ByteArrayOutputStream(); | |
/** 奪取済みフラグ. */ | |
private boolean stealFlag = false; | |
/** デフォルトコンストラクタの禁止. */ | |
private StandardOutputSnatcher() { } | |
/** | |
* このクラスのインスタンスを取得します. | |
* このクラスはスレッドセーフ化しにくい形で標準出力に干渉するので、 | |
* シングルトンパターンを採用しました. | |
* @return インスタンス | |
*/ | |
public static StandardOutputSnatcher getInstance() { | |
return INSTANCE; | |
} | |
/** | |
* 出力先を奪い、 | |
* コンソールからこのクラスへ出力するように設定します. | |
*/ | |
public void snatch() { | |
// ダブルスティールの禁止 | |
if (!stealFlag) { | |
nativeOut = System.out; | |
nativeErr = System.err; | |
System.setOut(new PrintStream(new BufferedOutputStream(snatchedOut))); | |
System.setErr(new PrintStream(new BufferedOutputStream(snatchedErr))); | |
stealFlag = true; | |
} | |
} | |
/** 標準出力をクリアします. */ | |
public void clearOutput() { | |
snatchedOut.reset(); | |
} | |
/** 標準エラー出力をクリアします. */ | |
public void clearErrorOutput() { | |
snatchedErr.reset(); | |
} | |
/** | |
* 標準出力の出力内容を取得します. | |
* @return 標準出力の出力内容 | |
*/ | |
public String getOutput() { | |
System.out.flush(); | |
return snatchedOut.toString(); | |
} | |
/** | |
* 標準エラー出力の出力内容を取得します. | |
* @return 標準エラー出力の出力内容 | |
*/ | |
public String getErrorOutput() { | |
System.err.flush(); | |
return snatchedErr.toString(); | |
} | |
/** | |
* 奪取した標準出力先を取得します. | |
* @return 奪取した標準出力先 | |
*/ | |
public PrintStream getNativeOutputStream() { | |
return nativeOut; | |
} | |
/** | |
* 奪取した標準エラー出力先を取得します. | |
* @return 奪取した標準エラー出力先 | |
*/ | |
public PrintStream getNativeErrorOutputStream() { | |
return nativeErr; | |
} | |
/** | |
* 出力先を元に戻します. | |
* このメソッドの呼び忘れにご注意ください. | |
*/ | |
public void release() { | |
// ダブルリリースの禁止 | |
if (stealFlag) { | |
clearOutput(); | |
clearErrorOutput(); | |
System.setOut(nativeOut); | |
System.setErr(nativeErr); | |
stealFlag = false; | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class StandardOutputSnatcherSample { | |
public static void main(String[] args) { | |
StandardOutputSnatcher sos = StandardOutputSnatcher.getInstance(); | |
System.out.println("開始"); | |
sos.snatch(); | |
// 標準出力 | |
System.out.print("標準出力テスト"); | |
if (sos.getOutput().equals("標準出力テスト")) { | |
sos.getNativeOutputStream().println("標準出力テスト成功!"); | |
} | |
// 出力内容のクリア | |
sos.clearOutput(); | |
// 標準出力(2回目) | |
System.out.print("標準出力テスト2"); | |
if (sos.getOutput().equals("標準出力テスト2")) { | |
sos.getNativeOutputStream().println("標準出力テスト2成功!"); | |
} | |
// 標準エラー出力 | |
sos.clearErrorOutput(); | |
System.err.print("標準エラー出力テスト"); | |
if (sos.getErrorOutput().equals("標準エラー出力テスト")) { | |
sos.getNativeOutputStream().println("標準エラー出力テスト成功!"); | |
} | |
// 出力内容のクリア | |
sos.clearErrorOutput(); | |
// 標準エラー出力(2回目) | |
System.err.print("標準エラー出力テスト2"); | |
if (sos.getErrorOutput().equals("標準エラー出力テスト2")) { | |
sos.getNativeOutputStream().println("標準エラー出力テスト2成功!"); | |
} | |
sos.release(); | |
System.out.println("終了"); | |
} | |
} |
ちなみにLog4jの出力テストにも使えることにお気づきでしょうか?
そうです、ConsoleAppenderで出力すれば、
Log4jで出力した内容をStringで取得できるのです。
適当にコピー&ペーストでお試しあれ。
…ちゃんと意味を理解したうえでね。
2012/07/08追記:微妙に修正
こんにちは。
返信削除標準出力先の変更、なかなか使う機会がありませんが、覚えたてのころから知っているメソッドなので、よく注目しますね。
返信が遅れて失礼しました。
削除コメントありがとうございます。
覚えたてのことから知っているとはすごいです。
確かに使う機会はそうそうありませんね。
でも出来るということは知っておいて欲しい、
そんな機能だと思っています。