views:

1210

answers:

5

I am comparing text files in junit using:

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

Is this a good way to compare text files? What is preferred?

+1  A: 

If expected has more lines than actual, you'll fail an assertEquals before getting to the assertNull later.

It's fairly easy to fix though:

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

}

Jon Skeet
+6  A: 

junit-addons(http://sourceforge.net/projects/junit-addons) has nice support for it

http://junit-addons.sourceforge.net/junitx/framework/FileAssert.html

it gives you exceptions like junitx.framework.ComparisonFailure: aa Line [3] expected: [b] but was:[a]

01
+1  A: 

I'd suggest using Assert.assertThat and a hamcrest matcher (junit 4.5 or later - perhaps even 4.4).

I'd end up with something like:

assertThat(fileUnderTest, containsExactText(expectedFile));

where my matcher is:

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 and reuse
  • Use in normal code as well as test
    • Collections
    • Used in mock framework(s)
    • Can be used a general predicate function
  • Really nice log-ability
  • Can be combined with other matchers and descriptions and failure descriptions are accurate and precise

Cons:

  • Well it's pretty obvious right? This is way more verbose than assert or junitx (for this particular case)
  • You'll probably need to include the hamcrest libs to get the most benefit
Stephen
+4  A: 

Here's one simple approach for checking if the files are exactly the same:

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

Where file1 and file2 are File instances, and FileUtils is from Apache Commons IO.

Not much own code for you to maintain, which is always a plus. :) And very easy if you already happen to use Apache Commons in your project. But no nice, detailed error messages like in mark's solution.

Edit:
Heh, looking closer at the FileUtils API, there's an even simpler way:

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

As a bonus, this version works for all files, not just text.

Jonik
The assertTrue form is concise, but relatively useless when it fails. At least the assertEquals method will show you a few characters where they are different
Stephen
+1  A: 

Here is a more exhaustive list of File comparator's in various 3rd-party Java libraries:

www.unitils.org/apidocs/org/unitils/thirdparty/org/apache/commons/io/FileUtils.html#contentEquals%28java.io.File,%20java.io.File%29

www.dbunit.org/cobertura/org.dbunit.util.FileAsserts.html

easytesting.org/assert/apidocs/org/fest/assertions/FileAssert.html

junit-addons.sourceforge.net/junitx/framework/FileAssert.html

static.springsource.org/spring-batch/apidocs/org/springframework/batch/test/AssertFile.html

bits.netbeans.org/dev/javadoc/org-netbeans-modules-nbjunit/org/netbeans/junit/NbTestCase.html#assertFile%28java.io.File,%20java.io.File%29

Scott Langley