Question

Je compare des fichiers texte dans 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 un bon moyen de comparer des fichiers texte? Qu'est-ce qui est préféré?

Était-ce utile?

La solution

junit-addons est très bien supporté: FileAssert

Cela vous donne des exceptions telles que:

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

Autres conseils

Voici une approche simple pour vérifier si les fichiers sont exactement identiques:

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

fichier1 et fichier2 sont des instances Fichier et FileUtils provient de Apache Commons IO .

Peu de code personnel à gérer, ce qui est toujours un avantage. :) Et très facile si vous utilisez déjà Apache Commons dans votre projet. Mais pas de messages d'erreur détaillés comme dans la solution de la marque .

Modifier :
En regardant de plus près l’API FileUtils , il existe même un moyen plus simple :

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

En prime, cette version fonctionne pour tous les fichiers, pas seulement le texte.

À partir de 2015, je recommanderais AssertJ , une affirmation élégante et complète bibliothèque. 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 des chaînes en ligne:

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

Les messages d'échec 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 contient plusieurs 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

Je suggérerais d'utiliser Assert.assertThat et un hamcrest matcher (Junit version 4.5 ou ultérieure). - peut-être même 4,4).

Je finirais avec quelque chose comme:

assertThat(fileUnderTest, containsExactText(expectedFile));

où se trouve mon matcher:

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

  • Composition et réutilisation
  • Utiliser dans le code normal ainsi que dans les tests
    • Collections
    • Utilisé dans un ou plusieurs cadres
    • Peut être utilisée comme fonction de prédicat général
  • Très belle capacité de journalisation
  • Peut être combiné avec d'autres correspondants et les descriptions et les descriptions d'échec sont précises

Inconvénients:

  • C'est assez évident non? C'est beaucoup plus verbeux que l'assert ou junitx (pour ce cas particulier)
  • Vous aurez probablement besoin d'inclure les bibliothèques hamcrest pour obtenir le plus d'avantages

FileUtils est certainement bon. Voici encore un autre approche simple pour vérifier si les fichiers sont exactement les mêmes.

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

Bien que l'assertEquals () fournisse un peu plus de retour que l'assertTrue (), le résultat de checksumCRC32 () est long. Donc, cela pourrait ne pas être très utile.

Comparaison Simpel du contenu de deux fichiers avec l'API java.nio.file.

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 souhaitez comparer des 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));
}

Si vous avez prévu plus de lignes que de résultats, vous échouerez avec assertEquals avant de passer à assertNull plus tard.

Il est assez facile de résoudre ce problème:

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

Ceci est ma propre implémentation de equalFiles , inutile d'ajouter une 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 la méthode AssertTrue JUnit classique

assertTrue(equalFiles(expected, output)) ;
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top