Comparer des fichiers texte avec Junit

je compare des fichiers texte en junit en utilisant:

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

Est-ce une bonne façon de comparer des fichiers texte? Ce qui est préférable?

41
demandé sur Cœur 2009-01-21 23:27:26

9 réponses

junit-addons a beau soutien pour elle: FileAssert

il vous donne des exceptions comme:

junitx.framework.ComparisonFailure: aa Line [3] expected: [b] but was:[a]
31
répondu IAdapter 2014-06-16 12:44:32

Voici une approche simple pour vérifier si les fichiers sont exactement le même:

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

file1 et file2 sont File instances, et FileUtils est de Apache Commons IO .

pas beaucoup de propre code à maintenir pour vous, ce qui est toujours un plus. :) Et très facile si vous utilisez déjà Apache Commons dans votre projet. Mais pas de bons messages d'erreur détaillés comme dans mark's solution .

Modifier :

Heh, en regardant de plus près à la FileUtils API, il y a un pair voie plus simple :

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

en bonus, cette version Fonctionne pour tous les fichiers, pas seulement le texte.

38
répondu Jonik 2017-05-23 11:54:43

à partir de 2015, je recomenterais AssertJ , une bibliothèque d'assertions élégante et complète. Pour les fichiers, vous pouvez affirmer contre un autre fichier:

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

ou contre inline chaînes:

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

les messages de défaillance sont également très informatifs. Si une ligne est différente, vous obtenez:

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

et si l'un des fichiers a plus de lignes vous obtenez:

java.lang.AssertionError:
File:
  <actual.txt>
and file:
  <expected.txt>
do not have equal content:
line:<4>,
Expected :EOF
Actual   :foo 4
11
répondu Bogdan Calmac 2017-02-02 06:02:17

je suggère D'utiliser Assert.assertThat et un hamcrest matcher (junit 4.5 ou plus tard - peut-être même 4.4).

je finirais avec quelque chose comme:

assertThat(fileUnderTest, containsExactText(expectedFile));

où mon matcher est:

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

  • Composition et réutilisation
  • utiliser en code normal ainsi qu'en test
    • Collections
    • utilisé dans le(S) cadre (s) simulé (s)
    • peut être utilisé une fonction générale de prédicat
  • Vraiment sympa journal-capacité
  • peut être combiné avec d'autres assemblages et les descriptions et descriptions des défaillances sont exactes et précises

Inconvénients:

  • Eh bien, c'est assez évident, non? C'est beaucoup plus verbeux que assert ou junitx (pour ce cas particulier)
  • vous aurez probablement besoin d'inclure les libs hamcrest pour obtenir le plus d'avantages
7
répondu Stephen 2009-01-21 21:01:04

FileUtils c'est une bonne idée. Voici encore un autre approche simple pour vérifier si les fichiers sont exactement les mêmes.

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

alors que les assertEquals() fournissent un peu plus de feedback que l'assertTrue(), le résultat de checksumCRC32() est long. Oui, c'est peut-être pas intrinsèquement utile.

5
répondu Mookie Wilson 2011-01-13 18:15:52

simple comparaison du contenu de deux fichiers avec java.nio.fichier 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);

ou si vous voulez comparer les lignes individuelles:

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
répondu Jonathan Andersson 2016-03-30 13:01:42

si prévu a plus de lignes que réel, vous échouerez une assertEquals avant d'arriver à l'assertNull plus tard.

il est assez facile de fixer cependant:

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
répondu Jon Skeet 2014-01-31 20:32:21

C'est ma propre implémentation de equalFiles , pas besoin d'ajouter de bibliothèque à votre projet.

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;

}

et pour l'utiliser il suffit d'utiliser régulier AssertTrue méthode de JUnit

assertTrue(equalFiles(expected, output)) ;
0
répondu Mauricio Gracia Gutierrez 2015-06-07 05:29:07