it-swarm.com.de

Textdateien mit Junit vergleichen

Ich vergleiche Textdateien in junit mit:

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

Ist dies eine gute Möglichkeit, Textdateien zu vergleichen? Was ist bevorzugt?

43
jon077

junit-addons hat Nice-Unterstützung dafür: FileAssert

Es gibt Ausnahmen wie:

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

Hier ist ein einfacher Ansatz, um zu überprüfen, ob die Dateien genau identisch sind:

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

Wobei file1 und file2File Instanzen sind und FileUtils von Apache Commons IO ist.

Sie müssen nicht viel eigenen Code pflegen, was immer von Vorteil ist. :) Und sehr einfach, wenn Sie Apache Commons bereits in Ihrem Projekt verwenden. Aber keine Nizza, detaillierte Fehlermeldungen wie in mark's solution .

Bearbeiten :
Heh, bei genauerem Hinsehen auf die API FileUtils gibt es ein geradzahliges einfacher Weg :

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

Als Bonus funktioniert diese Version für alle Dateien, nicht nur für Text.

42
Jonik
19
Scott Langley

Ab 2015 empfehle ich AssertJ eine elegante und umfassende Bestätigungsbibliothek. Für Dateien können Sie gegen eine andere Datei geltend machen:

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

oder gegen Inline-Strings:

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

Die Fehlermeldungen sind ebenfalls sehr informativ. Wenn eine Zeile anders ist, erhalten Sie:

Java.lang.AssertionError: 
File:
  <actual.txt>
and file:
  <expected.txt>
do not have equal content:
line:<2>, 
Expected :foo 2
Actual   :foo 20

und wenn eine der Dateien mehr Zeilen enthält, erhalten Sie:

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

Ich würde Assert.assertThat und einen hamcrest matcher (junit 4.5 oder später - vielleicht sogar 4.4) vorschlagen.

Ich würde mit so etwas wie enden:

assertThat(fileUnderTest, containsExactText(expectedFile));

wo mein Matcher ist:

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-Profis:

  • Zusammensetzung und Wiederverwendung
  • Verwendung in normalem Code sowie test
    • Sammlungen
    • Wird in Mock-Frameworks verwendet
    • Kann eine allgemeine Prädikatfunktion verwendet werden
  • Wirklich schöne Log-Fähigkeit
  • Kann mit anderen Matchern kombiniert werden und Beschreibungen und Fehlerbeschreibungen sind genau und präzise

Nachteile:

  • Nun, es ist ziemlich offensichtlich, richtig? Dies ist viel ausführlicher als Assert oder Junitx (für diesen speziellen Fall)
  • Sie müssen wahrscheinlich die Hamcrest-Bibliotheken einschließen, um den größtmöglichen Nutzen zu erzielen
7
Stephen

FileUtils ist sicher gut. Hier ist noch eine andere einfache Methode um zu überprüfen, ob die Dateien genau gleich sind.

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

Während assertEquals () etwas mehr Feedback liefert als assertTrue (), ist das Ergebnis von checksumCRC32 () ein langes Ergebnis. Das kann also nicht unbedingt hilfreich sein.

5
Mookie Wilson

Einfacher Vergleich des Inhalts zweier Dateien mit der 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);

Oder wenn Sie einzelne Zeilen vergleichen möchten: 

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

Wenn erwartet wird, dass mehr Zeilen als tatsächlich vorhanden sind, schlagen Sie ein AssertEquals fehl, bevor Sie später auf AssertNull zugreifen.

Es ist ziemlich einfach zu beheben:

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());
}
4
Jon Skeet

Dies ist meine eigene Implementierung von equalFiles. Sie müssen Ihrem Projekt keine Bibliothek hinzufügen. 

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;

}

Um es zu verwenden, verwenden Sie einfach die normale JUnit-Methode AssertTrue

assertTrue(equalFiles(expected, output)) ;