Java 比较文本文件与Junit

Java 比较文本文件与Junit,java,junit,compare,text-files,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());

我使用以下方法比较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());
}

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

如果预期的行数多于实际行数,则在稍后访问assertNull之前,AssertQuals将失败

不过,修复起来相当容易:

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());
}
对它有很好的支持:

它为您提供了以下例外情况:

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

我建议使用Assert.assertThat和a(JUnit4.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;
         }
      }
   }
}
类文件匹配器{
静态匹配器包含ExactText(文件expectedFile){
返回新的TypeSafeMatcher(){
管柱失效;
公共布尔匹配安全(测试中的文件){
//为每个/转换为字符串创建读卡器
//您在这里的实现类似于:
弦线;
而((line=expected.readLine())!=null){
Matcher equalsMatcher=CoreMatchers.equalTo(行);
字符串actualLine=actual.readLine();
如果(!EqualMatcher.matches)匹配(实际值){
失败=相等匹配器。描述失败(实际线);
返回false;
}
}
//记录不均匀线路的故障
}
公共字符串描述失败(测试中的文件);
返回失败;
}
}
}
}
Matcher的优点:

  • 组合与重用
  • 用于普通代码和测试
    • 收藏
    • 在模拟框架中使用
    • 可以用作一般谓词函数
  • 非常好的日志功能
  • 可与其他匹配器组合,描述和故障描述准确、准确
缺点:

  • 这很明显,对吧?这比assert或junitx(对于这种特殊情况)要详细得多
  • 您可能需要包括hamcrest LIB以获得最大的收益

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

      assertEquals("The files differ!", 
          FileUtils.readFileToString(file1, "utf-8"), 
          FileUtils.readFileToString(file2, "utf-8"));
      
      其中
      file1
      file2
      File
      实例,并且来自

      您没有太多自己的代码需要维护,这通常是一个优点。:)如果您碰巧在项目中使用了ApacheCommons,那么这非常容易。但是没有像中那样漂亮、详细的错误消息

      编辑
      嘿,仔细看一下
      FileUtils
      API,甚至有一个:


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

      以下是各种第三方Java库中文件比较程序的详细列表:


        • FileUtils
          当然是一个不错的选择。下面是另一个检查文件是否完全相同的方法

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

          虽然assertEquals()提供的反馈确实比assertTrue()多一点,但checksumCRC32()的结果是一个漫长的过程。因此,这可能没有本质上的帮助。

          从2015年起,我推荐一个优雅而全面的断言库。对于文件,您可以针对另一个文件断言:

          @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
          
          java.lang.AssertionError:
          文件:
          和文件:
          不具有相同的内容:
          行:,
          预期:foo 2
          实际人数:foo 20
          
          如果其中一个文件的行数更多,则:

          java.lang.AssertionError:
          File:
            <actual.txt>
          and file:
            <expected.txt>
          do not have equal content:
          line:<4>,
          Expected :EOF
          Actual   :foo 4
          
          java.lang.AssertionError:
          文件:
          和文件:
          不具有相同的内容:
          行:,
          预期:EOF
          实际人数:foo4
          
          这是我自己实现的
          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)) ;
          

          使用
          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));
          }
          
          List file1=Files.readAllLines(Path.get(“文件1的路径”);
          List file2=Files.readAllLines(Path.get(“文件2的路径”);
          assertEquals(file1.size(),file2.size());
          对于(int i=0;i
          assertTrue表单简洁,但失败时相对无用。至少assertEquals方法会向您显示几个不同日期的字符:现在,我建议您不要使用Commons IO,而是将文件读取为字符串:
          files.toString(file1,Charset.forName(“UTF-8”)在这种情况下没有太大区别,但总体而言,Guava是一个更干净、文档更完整、维护更积极的库。由于Java 7,您可以非常简单地不使用任何外部库:
          新字符串(Files.readAllBytes(path.get(“/path/to/file.txt”)、StandardCharsets.UTF_8)
          +1,我想这对于真正大的文件来说很有用(当你只关心文件是否不同,而不关心差异是什么时),我喜欢你的答案不依赖任何第三方库,但这段代码不会编译。变量“actual”的作用域限制在while循环中,因此最终assertNull行不会编译。@buzz3791:否,
          actualLine
          的作用域限制在while循环中。
          actual
          的范围是整个方法。甜蜜的概述!如果spring包含了一些内容,请不要让我进行网络搜索;)请注意,vin maven central repo的最新版本是2003年版和1.4版,因此我不知道它是否与最新版本兼容。截至此评论,hasContentEqualTo方法已被弃用。改用hasSameContentAs
          。我对你在这个问题上的解决方案投赞成票。由于这是一篇较旧的文章,JUnit附加组件已经过时(可能与JUnit4不兼容),我不喜欢ApacheUtils,并且鉴于您的assertReaders方法是多么简洁,我认为没有理由包含一个全新的实用程序库。你的工作正常
          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));
          }