texto sublime por pasar para linea leer herramientas entre diferencias comparar como array archivos archivo java junit compare text-files

java - sublime - Comparando archivos de texto con Junit



leer un archivo de texto en java linea por linea (9)

Estoy comparando archivos de texto en junit usando:

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

¿Es esta una buena forma de comparar archivos de texto? ¿Qué se prefiere?


A partir de 2015, recomendaría AssertJ , una biblioteca de aserciones elegante y completa. Para los archivos, puede afirmar contra otro archivo:

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

o contra cadenas en línea:

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

Los mensajes de falla son muy informativos también. Si una línea es diferente, obtienes:

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

y si uno de los archivos tiene más líneas, obtienes:

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


Esta es mi propia implementación de equalFiles , no es necesario agregar ninguna biblioteca a su proyecto.

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

Y para usarlo simplemente use el método AssertTrue JUnit regular

assertTrue(equalFiles(expected, output)) ;



Sugiero usar Assert.assertThat y un matcrest matcher (junit 4.5 o posterior - quizás incluso 4.4).

Terminaría con algo como:

assertThat(fileUnderTest, containsExactText(expectedFile));

donde mi matcher es:

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

Profesionales de Matcher:

  • Composición y reutilización
  • Usar en el código normal y en la prueba
    • Colecciones
    • Utilizado en marco (s) simulado (s)
    • Se puede usar una función de predicado general
  • Habilidad de registro realmente agradable
  • Se puede combinar con otras combinaciones y las descripciones y las descripciones de fallas son precisas y precisas

Contras:

  • Bueno, es bastante obvio, ¿verdad? Esto es mucho más detallado que assert o junitx (para este caso en particular)
  • Probablemente necesites incluir Hamcrest libs para obtener el mayor beneficio

FileUtils seguro es bueno. Aquí hay otro enfoque simple para verificar si los archivos son exactamente iguales.

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

Mientras que assertEquals () proporciona un poco más de feedback que assertTrue (), el resultado de checksumCRC32 () es largo. Entonces, eso puede no ser intrínsicamente útil.


Si se espera que tenga más líneas que las reales, fallará una assertEquals antes de llegar a assertNull más tarde.

Sin embargo, es bastante fácil de arreglar:

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


Junit-Addons tiene un buen soporte para esto: FileAssert

Te da excepciones como:

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


Simpel comparación del contenido de dos archivos con 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);

O si quiere comparar líneas individuales:

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


Aquí hay un enfoque simple para verificar si los archivos son exactamente iguales:

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

Donde file1 y file2 son instancias de File y FileUtils es de Apache Commons IO .

No hay mucho código propio para mantener, que siempre es un plus. :) Y es muy fácil si ya utilizas Apache Commons en tu proyecto. Pero no hay mensajes de error agradables y detallados como en la solución de mark .

Editar :
Heh, mirando más de cerca la API de FileUtils , hay una manera aún más simple :

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

Como beneficio adicional, esta versión funciona para todos los archivos, no solo para texto.