[英]Comparing text files with Junit
I am comparing text files in junit using:我正在使用以下方法比较 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());
}
Is this a good way to compare text files?这是比较文本文件的好方法吗? What is preferred?
什么是首选?
Here's one simple approach for checking if the files are exactly the same:这是检查文件是否完全相同的一种简单方法:
assertEquals("The files differ!",
FileUtils.readFileToString(file1, "utf-8"),
FileUtils.readFileToString(file2, "utf-8"));
Where file1
and file2
are File
instances, and FileUtils
is from Apache Commons IO .其中
file1
和file2
是File
实例, FileUtils
来自Apache Commons IO 。
Not much own code for you to maintain, which is always a plus.没有多少自己的代码需要你维护,这总是一个加分项。 :) And very easy if you already happen to use Apache Commons in your project.
:) 如果您已经在您的项目中使用了 Apache Commons,则非常容易。 But no nice, detailed error messages like in mark's solution .
但是没有像mark 的解决方案那样好的、详细的错误消息。
Edit :编辑:
Heh, looking closer at the FileUtils
API, there's an even simpler way :呵呵,仔细看看
FileUtils
API,还有一种更简单的方法:
assertTrue("The files differ!", FileUtils.contentEquals(file1, file2));
As a bonus, this version works for all files, not just text.作为奖励,此版本适用于所有文件,而不仅仅是文本。
junit-addons has nice support for it: FileAssert junit-addons对它有很好的支持: FileAssert
It gives you exceptions like:它为您提供以下例外情况:
junitx.framework.ComparisonFailure: aa Line [3] expected: [b] but was:[a]
Here is a more exhaustive list of File comparator's in various 3rd-party Java libraries:以下是各种 3rd-party Java 库中文件比较器的更详尽列表:
As of 2015, I would recomment AssertJ , an elegant and comprehensive assertion library.到 2015 年为止,我会推荐AssertJ ,这是一个优雅而全面的断言库。 For files, you can assert against another file:
对于文件,您可以针对另一个文件进行断言:
@Test
public void file() {
File actualFile = new File("actual.txt");
File expectedFile = new File("expected.txt");
assertThat(actualFile).hasSameContentAs(expectedFile);
}
or against inline strings:或针对内联字符串:
@Test
public void inline() {
File actualFile = new File("actual.txt");
assertThat(linesOf(actualFile)).containsExactly(
"foo 1",
"foo 2",
"foo 3"
);
}
The failure messages are very informative as well.失败消息也非常有用。 If a line is different, you get:
如果一行不同,你会得到:
java.lang.AssertionError:
File:
<actual.txt>
and file:
<expected.txt>
do not have equal content:
line:<2>,
Expected :foo 2
Actual :foo 20
and if one of the files has more lines you get:如果其中一个文件有更多行,您会得到:
java.lang.AssertionError:
File:
<actual.txt>
and file:
<expected.txt>
do not have equal content:
line:<4>,
Expected :EOF
Actual :foo 4
Simple comparison of the content of two files with java.nio.file
API.用
java.nio.file
API简单比较两个文件的内容。
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);
Or if you want to compare individual lines:或者,如果您想比较各个行:
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));
}
I'd suggest using Assert.assertThat and a hamcrest matcher (junit 4.5 or later - perhaps even 4.4).我建议使用 Assert.assertThat 和hamcrest 匹配器(junit 4.5 或更高版本 - 甚至可能是 4.4)。
I'd end up with something like:我最终会得到类似的东西:
assertThat(fileUnderTest, containsExactText(expectedFile));
where my matcher is:我的匹配器在哪里:
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;
}
}
}
}
Matcher pros:匹配器优点:
Cons:缺点:
FileUtils
sure is a good one. FileUtils
肯定是一个不错的选择。 Here's yet another simple approach for checking if the files are exactly the same.这是检查文件是否完全相同的另一种简单方法。
assertEquals(FileUtils.checksumCRC32(file1), FileUtils.checksumCRC32(file2));
While the assertEquals() does provide a little more feedback than the assertTrue(), the result of checksumCRC32() is a long.虽然 assertEquals() 确实比 assertTrue() 提供了更多的反馈,但 checksumCRC32() 的结果很长。 So, that may not be intrisically helpful.
所以,这可能没有内在的帮助。
If expected has more lines than actual, you'll fail an assertEquals before getting to the assertNull later.如果预期的行数多于实际行数,则在稍后到达 assertNull 之前,您将失败 assertEquals。
It's fairly easy to fix though:不过修复起来相当容易:
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());
}
This is my own implementation of equalFiles
, no need to add any library to your project.这是我自己的
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;
}
And to use it just use regular AssertTrue
JUnit method并使用它只需使用常规的
AssertTrue
JUnit 方法
assertTrue(equalFiles(expected, output)) ;
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.