使用Junit比较文本文件

jon*_*077 45 java junit compare text-files

我正在比较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());
}
Run Code Online (Sandbox Code Playgroud)

这是比较文本文件的好方法吗?什么是首选?

Jon*_*nik 43

这是检查文件是否完全相同的一种简单方法:

assertEquals("The files differ!", 
    FileUtils.readFileToString(file1, "utf-8"), 
    FileUtils.readFileToString(file2, "utf-8"));
Run Code Online (Sandbox Code Playgroud)

其中file1file2File实例,FileUtils来自Apache Commons IO.

没有太多自己的代码供您维护,这总是一个加号.:)如果您已经在项目中使用Apache Commons,那么非常简单.但没有像mark的解决方案那样好的,详细的错误消息.

编辑:
嘿,仔细看看FileUtilsAPI,有一个更简单的方法:

assertTrue("The files differ!", FileUtils.contentEquals(file1, file2));
Run Code Online (Sandbox Code Playgroud)

作为奖励,此版本适用于所有文件,而不仅仅是文本.

  • **更新**:现在我建议[Google Guava](http://code.google.com/p/guava-libraries/)通过Commons IO读取文件为字符串:`Files.toString(file1, Charset.forName("UTF-8"));`在这种情况下没有太大的区别,但整体番石榴是一个更清洁,更好记录和积极维护的库. (3认同)
  • assertTrue表单简洁,但失败时相对无用.至少assertEquals方法会显示几个不同的字符 (2认同)
  • 而且由于** Java 7 **,您可以非常简单地[以字符串形式读取文本文件](http://stackoverflow.com/a/326440/56285),而无需任何外部库:`new String(Files.readAllBytes(Paths。 get(“ / path / to / file.txt”)),StandardCharsets.UTF_8)` (2认同)

IAd*_*ter 31

junit-addons对它有很好的支持:FileAssert

它为您提供以下例外:

junitx.framework.ComparisonFailure: aa Line [3] expected: [b] but was:[a]
Run Code Online (Sandbox Code Playgroud)

  • 请注意,最新版本的 vin maven central repo 来自 2003 和 1.4 版,所以我不知道它是否与最新版本兼容。 (3认同)

Bog*_*mac 14

截至2015年,我会推荐AssertJ,一个优雅而全面的断言库.对于文件,您可以断言另一个文件:

@Test
public void file() {
    File actualFile = new File("actual.txt");
    File expectedFile = new File("expected.txt");
    assertThat(actualFile).hasSameContentAs(expectedFile);
}
Run Code Online (Sandbox Code Playgroud)

或者反对内联字符串:

@Test
public void inline() {
    File actualFile = new File("actual.txt");
    assertThat(linesOf(actualFile)).containsExactly(
            "foo 1",
            "foo 2",
            "foo 3"
    );
}
Run Code Online (Sandbox Code Playgroud)

失败消息也非常有用.如果一条线不同,你得到:

java.lang.AssertionError: 
File:
  <actual.txt>
and file:
  <expected.txt>
do not have equal content:
line:<2>, 
Expected :foo 2
Actual   :foo 20
Run Code Online (Sandbox Code Playgroud)

如果其中一个文件包含更多行:

java.lang.AssertionError:
File:
  <actual.txt>
and file:
  <expected.txt>
do not have equal content:
line:<4>,
Expected :EOF
Actual   :foo 4
Run Code Online (Sandbox Code Playgroud)

  • 从本评论开始,“hasContentEqualTo”方法已被弃用。请改用“hasSameContentAs”。 (2认同)

Ste*_*hen 7

我建议使用Assert.assertThat和一个hamcrest匹配器(junit 4.5或更高版本 - 甚至可能是4.4).

我最终会得到类似的东西:

assertThat(fileUnderTest, containsExactText(expectedFile));
Run Code Online (Sandbox Code Playgroud)

我的匹配器在哪里:

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;
         }
      }
   }
}
Run Code Online (Sandbox Code Playgroud)

Matcher职业选手:

  • 组成和重用
  • 在普通代码中使用以及测试
    • 集合
    • 用于模拟框架
    • 可以使用一般谓词函数
  • 非常好的日志能力
  • 可与其他匹配器和描述结合使用,故障描述准确,精确

缺点:

  • 嗯,这很明显吧?这比assert或junitx更冗长(对于这个特殊情况)
  • 您可能需要包含hamcrest库以获得最大收益


Moo*_*son 5

FileUtils肯定是一个很好的.这是检查文件是否完全相同的另一种简单方法.

assertEquals(FileUtils.checksumCRC32(file1), FileUtils.checksumCRC32(file2));
Run Code Online (Sandbox Code Playgroud)

虽然assertEquals()确实提供了比assertTrue()更多的反馈,但checksumCRC32()的结果很长.所以,这可能没有内在的帮助.


Jon*_*son 5

Simpel使用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);
Run Code Online (Sandbox Code Playgroud)

或者,如果您想比较各个行:

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));
}
Run Code Online (Sandbox Code Playgroud)