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?
-
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());}
-
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]
-
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
-
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
file1andfile2areFileinstances, andFileUtilsis 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 theFileUtilsAPI, 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.
Stephen : 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 -
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
0 comments:
Post a Comment