2009-01-21 43 views
36

比較文本文件我用的比較在JUnit文本文件?什麼是首選?使用JUnit

回答

31

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

它給你的例外,如:

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

只需注意最新版本vin maven中央回購是從2003年和版本1.4,所以我不知道它是否與最新版本兼容。 – kohlerfc 2015-11-19 21:00:39

4

如果預計有更多的行比實際更多,那麼在稍後進入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()); 
} 
+0

我喜歡你的答案不依賴於任何第三方庫,但這些代碼不會編譯。變量'actual'的範圍限於while循環,所以最終的assertNull行不會被編譯。 – buzz3791 2014-01-31 20:30:50

+0

@ buzz3791:不,「actualLine」的範圍僅限於while循環。 「實際」的範圍是整個方法。 – 2014-01-31 20:32:41

+0

哎呀,謝謝你指出我的錯誤。 – buzz3791 2014-01-31 20:40:07

7

我建議使用斷言。 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; 
     } 
     } 
    } 
} 

匹配器的優點:

  • 組成和重用
  • 在正常使用代碼以及測試 個
    • 集合
    • 用於模擬框架(S)
    • 可以使用一般的斷言函數
  • 非常好的日誌能力
  • 可以與其他的匹配,並說明和故障描述相結合是準確和精確

缺點:

  • 那麼這是非常明顯的權利?這是方式比斷言或JUnitX的(針對這種特殊情況下)
  • 你可能需要包括hamcrest庫,以獲得最大的效益更詳細的
36

下面是檢查一個簡單的方法,如果該文件是正是一樣:

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

file1file2File實例,FileUtilsApache Commons IO

沒有太多自己的代碼供您維護,這總是一個加號。 :)如果你已經碰巧在你的項目中使用了Apache Commons,那麼這很簡單。但沒有好的,詳細的錯誤信息,如mark's solution

編輯
嘿,看着FileUtils API接近,有一種更simpler way

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

作爲獎勵,該版本適用於所有文件,而不僅僅是文字。

+2

assertTrue形式簡潔,但失敗時相對無用。至少assertEquals方法會告訴你幾個不同的字符 – Stephen 2010-06-10 10:33:08

+3

** Update **:現在我推薦[Google Guava](http://code.google.com/p/guava-libraries/) Commons IO將文件讀取爲字符串:`Files.toString(file1,Charset.forName(「UTF-8」));`在這種情況下沒有太大區別,但是整體Guava是一個更清潔,更好的文檔並積極維護圖書館。 – Jonik 2011-07-18 18:12:09

5

FileUtils肯定是一個很好的一個。這是另一個simple approach用於檢查文件是否完全相同。

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

雖然的assertEquals()並提供比assertTrue()多一點反饋,checksumCRC32()的結果是一個長。所以,這可能不是有幫助的。

11

截至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 

,如果文件中的一個具有更多的行您可以:

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

這是我自己實現的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; 

} 

,並使用它只是使用普通的JUnit AssertTrue方法

assertTrue(equalFiles(expected, output)) ; 
4

的兩個文件java.nio.file API內容的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)); 
}