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 件のコメント:
コメントを投稿