私は次を使用してjunitのテキストファイルを比較しています:
public static void assertReaders(BufferedReader expected,
BufferedReader actual) throws IOException {
String line;
while ((line = expected.readLine()) != null) {
assertEquals(line, actual.readLine());
}
assertNull("Actual had more lines then the expected.", actual.readLine());
assertNull("Expected had more lines then the actual.", expected.readLine());
}
これはテキストファイルを比較する良い方法ですか?優先されるものは何ですか?
junit-addons にはいいサポートがあります: FileAssert
次のような例外が発生します。
junitx.framework.ComparisonFailure: aa Line [3] expected: [b] but was:[a]
ファイルが正確に同じであるかどうかを確認するための簡単な方法を1つ示します。
assertEquals("The files differ!",
FileUtils.readFileToString(file1, "utf-8"),
FileUtils.readFileToString(file2, "utf-8"));
どこ file1
およびfile2
はFile
インスタンスであり、 FileUtils
は Apache Commons IO からのものです。
維持する必要のある独自のコードはあまりありません。これは常にプラスです。 :)また、プロジェクトで既にApache Commonsを使用している場合は非常に簡単です。しかし、 マークの解決策 のようなニースの詳細なエラーメッセージはありません。
編集:
ヘー、FileUtils
APIを詳しく見ると、偶数の 簡単な方法 があります。
assertTrue("The files differ!", FileUtils.contentEquals(file1, file2));
ボーナスとして、このバージョンはテキストだけでなく、すべてのファイルで機能します。
2015年の時点で、エレガントで包括的なアサーションライブラリである AssertJ を推奨します。ファイルの場合、別のファイルに対してアサートできます。
@Test
public void file() {
File actualFile = new File("actual.txt");
File expectedFile = new File("expected.txt");
assertThat(actualFile).hasSameContentAs(expectedFile);
}
またはインライン文字列に対して:
@Test
public void inline() {
File actualFile = new File("actual.txt");
assertThat(linesOf(actualFile)).containsExactly(
"foo 1",
"foo 2",
"foo 3"
);
}
失敗メッセージも非常に有益です。行が異なる場合、以下を取得します。
Java.lang.AssertionError:
File:
<actual.txt>
and file:
<expected.txt>
do not have equal content:
line:<2>,
Expected :foo 2
Actual :foo 20
そして、ファイルの1つにさらに行がある場合、次のようになります。
Java.lang.AssertionError:
File:
<actual.txt>
and file:
<expected.txt>
do not have equal content:
line:<4>,
Expected :EOF
Actual :foo 4
Assert.assertThatと hamcrest matcher (junit 4.5以降-おそらく4.4)を使用することをお勧めします。
私は次のようなものになるでしょう:
assertThat(fileUnderTest, containsExactText(expectedFile));
私のマッチャーは:
class FileMatcher {
static Matcher<File> containsExactText(File expectedFile){
return new TypeSafeMatcher<File>(){
String failure;
public boolean matchesSafely(File underTest){
//create readers for each/convert to strings
//Your implementation here, something like:
String line;
while ((line = expected.readLine()) != null) {
Matcher<?> equalsMatcher = CoreMatchers.equalTo(line);
String actualLine = actual.readLine();
if (!equalsMatcher.matches(actualLine){
failure = equalsMatcher.describeFailure(actualLine);
return false;
}
}
//record failures for uneven lines
}
public String describeFailure(File underTest);
return failure;
}
}
}
}
マッチャーの長所:
短所:
FileUtils
確かに良いものです。ファイルがまったく同じであるかどうかをチェックするための別の 単純なアプローチ を次に示します。
assertEquals(FileUtils.checksumCRC32(file1), FileUtils.checksumCRC32(file2));
AssertEquals()はassertTrue()よりも少し多くのフィードバックを提供しますが、checksumCRC32()の結果は長いです。したがって、本質的には役に立たない可能性があります。
Java.nio.file APIを使用した2つのファイルの内容のSimpel比較。
byte[] file1Bytes = Files.readAllBytes(Paths.get("Path to File 1"));
byte[] file2Bytes = Files.readAllBytes(Paths.get("Path to File 2"));
String file1 = new String(file1Bytes, StandardCharsets.UTF_8);
String file2 = new String(file2Bytes, StandardCharsets.UTF_8);
assertEquals("The content in the strings should match", file1, file2);
または、個々の行を比較する場合:
List<String> file1 = Files.readAllLines(Paths.get("Path to File 1"));
List<String> file2 = Files.readAllLines(Paths.get("Path to File 2"));
assertEquals(file1.size(), file2.size());
for(int i = 0; i < file1.size(); i++) {
System.out.println("Comparing line: " + i)
assertEquals(file1.get(i), file2.get(i));
}
予想よりも実際の行数が多い場合、後でassertNullに到達する前にassertEqualsに失敗します。
ただし、修正はかなり簡単です。
public static void assertReaders(BufferedReader expected,
BufferedReader actual) throws IOException {
String expectedLine;
while ((expectedLine = expected.readLine()) != null) {
String actualLine = actual.readLine();
assertNotNull("Expected had more lines then the actual.", actualLine);
assertEquals(expectedLine, actualLine);
}
assertNull("Actual had more lines then the expected.", actual.readLine());
}
これはequalFiles
の独自の実装であり、プロジェクトにライブラリを追加する必要はありません。
private static boolean equalFiles(String expectedFileName,
String resultFileName) {
boolean equal;
BufferedReader bExp;
BufferedReader bRes;
String expLine ;
String resLine ;
equal = false;
bExp = null ;
bRes = null ;
try {
bExp = new BufferedReader(new FileReader(expectedFileName));
bRes = new BufferedReader(new FileReader(resultFileName));
if ((bExp != null) && (bRes != null)) {
expLine = bExp.readLine() ;
resLine = bRes.readLine() ;
equal = ((expLine == null) && (resLine == null)) || ((expLine != null) && expLine.equals(resLine)) ;
while(equal && expLine != null)
{
expLine = bExp.readLine() ;
resLine = bRes.readLine() ;
equal = expLine.equals(resLine) ;
}
}
} catch (Exception e) {
} finally {
try {
if (bExp != null) {
bExp.close();
}
if (bRes != null) {
bRes.close();
}
} catch (Exception e) {
}
}
return equal;
}
それを使用するには、通常のAssertTrue
JUnitメソッドを使用するだけです
assertTrue(equalFiles(expected, output)) ;