JUnit用と言っていますがhamcrestしか使っていません。
取りあえず作ってみた状態なのでテストはせず、ちょっと動かしてみた程度です。直さなければいけない部分もあるかと思いますが、作ったことを忘れてしまいそうなので上げておきます。
使用しているライブラリは下記の通りです。
・hamcrest-core-1.3.jar
+各ライブラリで必要なライブラリ
package my.junit.matcher; import java.io.InputStream; import org.hamcrest.Matcher; /** * テキスト形式でInputStreamの比較を行えるMatcher * * @author blog owner * * @param <T> * 任意のクラス */ class TextInputStreamMatcher extends AbstractTextFileMatcher<InputStream> { /** * コンストラクタ */ protected TextInputStreamMatcher(InputStream expected) { this(expected, CHAR_SET); } /** * コンストラクタ */ protected TextInputStreamMatcher(InputStream expected, String charSet) { super(); this.charSet = charSet; expectedName = "expected file"; expectedIs = expected; } /** * <pre> * テキストファイル比較用のMatcherを取得します。 * キャラクターセットはUTF-8です。 * </pre> * * @param expected * 予想されるファイル * @return テキストファイル比較用のMatcher */ public static Matcher<InputStream> equalsContentsOf(InputStream expected) { return new TextInputStreamMatcher(expected); } /** * テキストファイル比較用のMatcherを取得します。 * * @param expected * 予想されるファイル * @param charSet * キャラクターセット * @return テキストファイル比較用のMatcher */ public static Matcher<InputStream> equalsContentsOf(InputStream expected, String charSet) { return new TextInputStreamMatcher(expected, charSet); } /** * {@inheritDoc} */ @Override protected InputStream getActualIs(InputStream actual) { actualIs = actual; return actualIs; } }
TextFileMatcher.java
package my.junit.matcher; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.InputStream; import org.hamcrest.Matcher; /** * テキストファイルの比較を行えるMatcher * * @author blog owner * * @param <T> * 任意のクラス */ class TextFileMatcher extends AbstractTextFileMatcher<File> { /** * コンストラクタ */ protected TextFileMatcher(File expected) { this(expected, CHAR_SET); } /** * コンストラクタ */ protected TextFileMatcher(File expected, String charSet) { super(); this.charSet = charSet; File expectedFile = expected; expectedName = expectedFile.getPath(); try { expectedIs = new FileInputStream(expectedFile); } catch (FileNotFoundException e) { throw new IllegalArgumentException(e); } } /** * <pre> * テキストファイル比較用のMatcherを取得します。 * キャラクターセットはUTF-8です。 * </pre> * * @param expected * 予想されるファイル * @return テキストファイル比較用のMatcher */ public static Matcher<File> equalsContentsOf(File expected) { return new TextFileMatcher(expected); } /** * テキストファイル比較用のMatcherを取得します。 * * @param expected * 予想されるファイル * @param charSet * キャラクターセット * @return テキストファイル比較用のMatcher */ public static Matcher<File> equalsContentsOf(File expected, String charSet) { return new TextFileMatcher(expected, charSet); } /** * {@inheritDoc} */ @Override protected InputStream getActualIs(File actual) { actualName = actual.getPath(); try { actualIs = new FileInputStream(actual); } catch (FileNotFoundException e) { throw new IllegalArgumentException(e); } return actualIs; } }
TextFilePathMatcher.java
package my.junit.matcher; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.InputStream; import org.hamcrest.Matcher; /** * テキストファイルの比較を行えるMatcher * * @author blog owner * * @param <T> * 任意のクラス */ class TextFilePathMatcher extends AbstractTextFileMatcher<String> { /** * コンストラクタ */ protected TextFilePathMatcher(String expected) { this(expected, CHAR_SET); } /** * コンストラクタ */ protected TextFilePathMatcher(String expected, String charSet) { super(); this.charSet = charSet; String expectedPath = (String) expected; File expectedFile = new File(expectedPath); expectedName = expectedFile.getPath(); try { expectedIs = new FileInputStream(expectedFile); } catch (FileNotFoundException e) { throw new IllegalArgumentException(e); } } /** * <pre> * テキストファイル比較用のMatcherを取得します。 * キャラクターセットはUTF-8です。 * </pre> * * @param expected * 予想されるファイルのパス * @return テキストファイル比較用のMatcher */ public static Matcher<String> equalsContentsOf(String expected) { return new TextFilePathMatcher(expected); } /** * テキストファイル比較用のMatcherを取得します。 * * @param expected * 予想されるファイルのパス * @param charSet * キャラクターセット * @return テキストファイル比較用のMatcher */ public static Matcher<String> equalsContentsOf(String expected, String charSet) { return new TextFilePathMatcher(expected, charSet); } /** * {@inheritDoc} */ @Override protected InputStream getActualIs(String actual) { File actualFile = new File(actual); actualName = actualFile.getPath(); try { actualIs = new FileInputStream(actualFile); } catch (FileNotFoundException e) { throw new IllegalArgumentException(e); } return actualIs; } }
AbstractTextFileMatcher.java
package my.junit.matcher; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.UnsupportedEncodingException; import java.util.ArrayList; import java.util.List; import org.hamcrest.Description; import org.hamcrest.TypeSafeMatcher; /** * テキストファイルの比較を行えるMatcherの抽象クラス * * @author blog owner * * @param <T> * 任意のクラス */ abstract class AbstractTextFileMatcher<T> extends TypeSafeMatcher<T> { /** * デフォルトキャラクターセット */ protected static final String CHAR_SET = "UTF-8"; /** * キャラクターセット */ protected String charSet = null; /** * 予想されるファイルの表示名 */ protected String expectedName = null; /** * 予想されるファイルのインプットストリーム */ protected InputStream expectedIs = null; /** * 実際のファイルの表示名 */ protected String actualName = null; /** * 実際のファイルのインプットストリーム */ protected InputStream actualIs = null; /** * 不一致だった予想されるファイルの行 */ protected List<String> unmatchedExpectedLines = new ArrayList<String>(); /** * 不一致だった実際のファイルの行 */ protected List<String> unmatchedActualLines = new ArrayList<String>(); /** * 不一致だった行番号 */ protected List<Integer> unmatchedLineNums = new ArrayList<Integer>(); /** * デフォルトコンストラクタ */ protected AbstractTextFileMatcher() { super(); } /** * コンストラクタ */ protected AbstractTextFileMatcher(String expectedName, InputStream expectedIs) { this(expectedName, expectedIs, CHAR_SET); } /** * コンストラクタ */ protected AbstractTextFileMatcher(String expectedName, InputStream expectedIs, String charSet) { this.expectedName = expectedName; this.expectedIs = expectedIs; this.charSet = charSet; } /** * 実際のファイルのインプットストリームを取得します。 * * @param actual * 実際のファイルの情報 * @return 実際のファイルのインプットストリーム */ protected abstract InputStream getActualIs(T actual); /** * 実際のファイルの表示名を取得する。 * * @return 実際のファイルの表示名 */ private String getActualName() { if (actualName == null) { return "actual file"; } else { return actualName; } } /** * 比較を行います。 * * @param actual * 実際の値 * @return 比較結果 */ @Override public boolean matchesSafely(T actual) { // インプットストリームを取得 actualIs = getActualIs(actual); BufferedReader expectedReader = null; try { // 予想されるファイル expectedReader = new BufferedReader(new InputStreamReader( expectedIs, charSet)); } catch (UnsupportedEncodingException e) { throw new IllegalArgumentException(e); } BufferedReader actualReader = null; try { // 実際のファイル actualReader = new BufferedReader(new InputStreamReader(actualIs, charSet)); } catch (UnsupportedEncodingException e) { throw new IllegalArgumentException(e); } int lineNum = 0; String expectedLine = null; String actualLine = null; try { while ((expectedLine = expectedReader.readLine()) != null & (actualLine = actualReader.readLine()) != null) { lineNum++; if (!expectedLine.equals(actualLine)) { // 1行分の内容が一致しない unmatchedLineNums.add(Integer.valueOf(lineNum)); unmatchedExpectedLines.add(expectedLine); unmatchedActualLines.add(actualLine); } } if (expectedLine != null || actualLine != null) { // 行数が一致しない lineNum++; unmatchedLineNums.add(Integer.valueOf(lineNum)); unmatchedExpectedLines.add(expectedLine); unmatchedActualLines.add(actualLine); } } catch (IOException e) { // どうにもならないので例外 throw new IllegalStateException(e); } finally { try { expectedReader.close(); } catch (IOException e) { // 比較は終わっているので握りつぶす } try { actualReader.close(); } catch (IOException e) { // 比較は終わっているので握りつぶす } } return unmatchedLineNums.isEmpty(); } /** * エラーの場合に表示する、実際の値を示す文字列を追加します。 * * @param actual * 実際の値 * @param description * エラー時の文章 */ @Override public void describeMismatchSafely(T actual, Description mismatchDescription) { setUpDescription(mismatchDescription, getActualName(), unmatchedActualLines, unmatchedLineNums); } /** * エラーの場合に表示する、予測の値を示す文字列を追加します。 * * @param description * エラー時の文章 */ @Override public void describeTo(Description description) { setUpDescription(description, expectedName, unmatchedExpectedLines, unmatchedLineNums); } /** * エラーの詳細を設定します。 * * @param description * 設定先 * @param name * 表示名 * @param lines * エラーになった行の内容 * @param lineNums * エラーになった行番号 */ private void setUpDescription(Description description, String name, List<String> lines, List<Integer> lineNums) { description.appendText(name + " = "); if (lineNums.isEmpty()) { description.appendText("想定外のエラー"); } for (int i = 0; i < lineNums.size(); i++) { if (i != 0) { description.appendText(", "); } description.appendText(lineNums.get(i) + ":"); description.appendValue(lines.get(i)); } return; } }
0 件のコメント:
コメントを投稿