8

I'm writing unit tests for IM- and exporting files. I need to test the resulting directory recursively byte by byte. I implemented a routine for flat directories by myself and know how to do this recursively also. But I don't want to reinvent the wheel.

So is there something like the following examples?

Matchers.matches(Path actual, equalsRecursive(Path value));

or

FileAssertions.equalsRecursive(Path actual, Path value);
Puneet Pandey
  • 960
  • 2
  • 14
  • 28
Andreas
  • 1,183
  • 1
  • 11
  • 24

2 Answers2

2

I am not aware of such a Matcher. So, IMO you will have to do it yourself. 2 options I could think of are as follows:

  1. Use Apache Commons FileUtils in order to

    1.1. make sure that each and every file/sub-directory(recursive call goes here) exists inside the directory currently being tested. For each subdir get a collection of files, iterate and use directoryContains method for the corresponding subdir.

    1.2 make sure that the content of 2 corresponding files are equal using contentEquals method. I am not sure what happens if you pass 2 directories to this method.

  2. Second option: if you run your tests on Linux box you can run a Linux command from Java using Runtime.exec()docs are here. The single command you need to run is diff -r <directory1> <directory2>

Good luck!

aviad
  • 8,229
  • 9
  • 50
  • 98
  • Thx for the hints! Luckily i could use Java7 and can use Files.walkFileTree(). For binary comparison i could use Files.readAllBytes(Path path) and can compare with Assert.assertArrayEquals(). I don't wan't resort to platfrom specific routines. – Andreas Aug 04 '15 at 09:08
  • would be interesting to see if there is a better way/out-of-the-box lib to do this. Please update if you find anything! – aviad Aug 04 '15 at 09:11
2

Didn't found anything. So i programmed it by myself. It's not very sophisticated and slow for large files, but seems to work.

import java.io.IOException;
import java.nio.file.FileVisitResult;
import java.nio.file.FileVisitor;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.attribute.BasicFileAttributes;

import org.junit.Assert;

/**
 * Assertion for recursively testing directories.
 * 
 * @author andreas
 */
public class AssertFile {

private AssertFile() {
    throw new RuntimeException("This class should not be instantiated");
}

/**
 * Asserts that two directories are recursively equal. If they are not, an {@link AssertionError} is thrown with the
 * given message.<br/>
 * There will be a binary comparison of all files under expected with all files under actual. File attributes will
 * not be considered.<br/>
 * Missing or additional files are considered an error.<br/>
 * 
 * @param expected
 *            Path expected directory
 * @param actual
 *            Path actual directory
 */
public static final void assertPathEqualsRecursively(final Path expected, final Path actual) {
    Assert.assertNotNull(expected);
    Assert.assertNotNull(actual);
    final Path absoluteExpected = expected.toAbsolutePath();
    final Path absoluteActual = actual.toAbsolutePath();
    try {
        Files.walkFileTree(expected, new FileVisitor<Path>() {

            @Override
            public FileVisitResult preVisitDirectory(Path expectedDir, BasicFileAttributes attrs)
                    throws IOException {
                Path relativeExpectedDir = absoluteExpected.relativize(expectedDir.toAbsolutePath());
                Path actualDir = absoluteActual.resolve(relativeExpectedDir);

                if (!Files.exists(actualDir)) {
                    Assert.fail(String.format("Directory \'%s\' missing in target.", expectedDir.getFileName()));
                }

                Assert.assertEquals(String.format("Directory size of \'%s\' differ. ", relativeExpectedDir),
                        expectedDir.toFile().list().length, actualDir.toFile().list().length);

                return FileVisitResult.CONTINUE;
            }

            @Override
            public FileVisitResult visitFile(Path expectedFile, BasicFileAttributes attrs) throws IOException {
                Path relativeExpectedFile = absoluteExpected.relativize(expectedFile.toAbsolutePath());
                Path actualFile = absoluteActual.resolve(relativeExpectedFile);

                if (!Files.exists(actualFile)) {
                    Assert.fail(String.format("File \'%s\' missing in target.", expectedFile.getFileName()));
                }
                Assert.assertEquals(String.format("File size of \'%s\' differ. ", relativeExpectedFile),
                        Files.size(expectedFile), Files.size(actualFile));
                Assert.assertArrayEquals(String.format("File content of \'%s\' differ. ", relativeExpectedFile),
                        Files.readAllBytes(expectedFile), Files.readAllBytes(actualFile));

                return FileVisitResult.CONTINUE;
            }

            @Override
            public FileVisitResult visitFileFailed(Path file, IOException exc) throws IOException {
                Assert.fail(exc.getMessage());
                return FileVisitResult.TERMINATE;
            }

            @Override
            public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
                return FileVisitResult.CONTINUE;
            }

        });
    } catch (IOException e) {
        Assert.fail(e.getMessage());
    }
}

}
Andreas
  • 1,183
  • 1
  • 11
  • 24