比较文本文件与Junit

de90aj5v  于 2022-11-11  发布在  其他
关注(0)|答案(9)|浏览(201)

我在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());
}

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

vltsax25

vltsax251#

这里有一个简单的方法来检查文件是否 * 完全 * 相同:

assertEquals("The files differ!", 
    FileUtils.readFileToString(file1, "utf-8"), 
    FileUtils.readFileToString(file2, "utf-8"));

其中,file1file2File示例,而FileUtils来自Apache Commons IO
没有太多自己的代码需要维护,这总是一个优点。:)如果你已经在你的项目中使用了Apache Commons,这很容易。但是没有像mark的解决方案中那样漂亮、详细的错误消息。

编辑

仔细看看FileUtils API,还有一种更简单的方法:

assertTrue("The files differ!", FileUtils.contentEquals(file1, file2));

作为一个额外的好处,这个版本适用于所有文件,而不仅仅是文本。

sqserrrh

sqserrrh2#

junit-addons对此有很好的支持:FileAssert
它提供了如下例外:

junitx.framework.ComparisonFailure: aa Line [3] expected: [b] but was:[a]
dtcbnfnu

dtcbnfnu3#

以下是各种第三方Java库中的文件比较器的更详尽列表:

k97glaaz

k97glaaz4#

在2015年,我会重新注解AssertJ,一个优雅而全面的Assert库。

@Test
public void file() {
    File actualFile = new File("actual.txt");
    File expectedFile = new File("expected.txt");
    assertThat(actualFile).hasSameTextualContentAs(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

如果其中一个文件有更多行,则会得到:

java.lang.AssertionError:
File:
  <actual.txt>
and file:
  <expected.txt>
do not have equal content:
line:<4>,
Expected :EOF
Actual   :foo 4
of1yzvn4

of1yzvn45#

使用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);

或者,如果要比较单个行:

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));
}
nkhmeac6

nkhmeac66#

我建议使用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;
         }
      }
   }
}

比赛职业选手:

  • 组成和再利用
  • 在正常代码和测试中使用
  • 集合
  • 用于模拟框架
  • 可用于一般 predicate 函数
  • 非常好的记录能力
  • 可与其他匹配器组合,描述和故障描述准确、精确

缺点:

  • 很明显,这比assert或junitx(对于这个特定的例子)要冗长得多。
  • 您可能需要包括hamcrest libs以获得最大的好处
wxclj1h5

wxclj1h57#

FileUtils当然是一个很好的方法。这里还有另一个简单的方法来检查文件是否完全相同。

assertEquals(FileUtils.checksumCRC32(file1), FileUtils.checksumCRC32(file2));

虽然assertEquals()确实比assertTrue()提供了更多的反馈,但checksumCRC32()的结果是long。因此,这可能没有本质上的帮助。

4c8rllxm

4c8rllxm8#

如果expected的行数比实际的多,那么在稍后到达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());
}
erhoui1w

erhoui1w9#

这是我自己实现的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)) ;

相关问题