Test resources as files

2,132 views
Skip to first unread message

Dan Fabulich

unread,
Mar 24, 2016, 7:00:52 PM3/24/16
to bazel-discuss
Consider this example repository.


It has a simple App.java:

public class App 
{
    public String readFile(String path) throws Exception {
        File file = new File(path);
        FileInputStream fis = new FileInputStream(file);
        return new java.util.Scanner(fis).useDelimiter("\\A").next();
    }
}

And it has an AppTest.java.

public class AppTest
    extends TestCase
{

    public void testApp() throws Exception
    {
        String path = AppTest.class.getResource("hello.txt").getFile();
        System.out.println(path);
        App app = new App();
        assertEquals("hello", app.readFile(path));
    }
}

The repository includes a Maven pom.xml and Bazel WORKSPACE/BUILD files. The test passes when I run "mvn test", but fails when I "bazel test //:test"

In Maven, the classpath contains the exploded target/test-classes directory, so getResource("hello.txt").getFile() returns an absolute file path, suitable for use with App.java.

In Bazel, the resources are first zipped into a jar, so getResource("hello.txt').getFile() returns a jar URL string, like this:

    file:/private/var/tmp/_bazel_dfabulich/dea6568d2b91f5e0663b4131b12cb24c/file-resources-example/bazel-out/local_darwin-fastbuild/bin/test.jar!/com/redfin/hello.txt

Note the exclamation point in that path: file:/path/to/test.jar!/com/redfin/hello.txt

I suppose it was inappropriate for the test to assume that it would be run with an exploded directory on the classpath (though that assumption was correct when the test was originally written, in Maven). Nonetheless, I would like Bazel to do what Maven does, and run the tests against an exploded directory, rather than jarring the test resources up.

Is it possible to run Bazel tests in that way?

-Dan

Alex Humesky

unread,
Mar 30, 2016, 5:18:11 PM3/30/16
to Dan Fabulich, bazel-discuss
One option might be to refactor the code to accept InputStreams instead of file paths as strings, and then you can do this:

public String readFile(InputStream is) throws Exception {
    return new java.util.Scanner(is).useDelimiter("\\A").next();
}

public void testApp() throws Exception
{
    URL url = AppTest.class.getResource("hello.txt").toURI().toURL();
    System.out.println(url);
    App app = new App();
    assertEquals("hello", app.readFile(url.openStream()));
}

and url.openStream() should handle files within zip files ("foo.zip!path") and regular files on the file system.

--
You received this message because you are subscribed to the Google Groups "bazel-discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email to bazel-discus...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/bazel-discuss/abe8f7b8-7816-4a71-ae14-ed07228ae49d%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Ronnie R.

unread,
Apr 19, 2016, 11:24:57 AM4/19/16
to bazel-discuss, danfa...@gmail.com
If you don't want the test data file included in the jar, but prefer them to be standard files, use "data" instead of "resources".
Instead of resources=glob(['src/test/resources/**/*']),  use data=glob(['src/test/resources/**/*']),

When you execute the tests through bazle, you'll have an environment variable that points to the runfiles location.  You'll need to update your tests so to look at that path and make a decision on it being there (for Bazel) or not there (for the IDE and MVN).  Here's sample code...

private String getResource(String testfile) {
String resourceDir = "src/test/resources/";

String path = System.getenv("TEST_SRCDIR"); // Set in the Bazel wrapper
if (path == null) {
// This handles both the IDE and Maven
path = resourceDir;
} else {
// This works for Bazel
path = Paths.get(path, "/your_dir/" + resourceDir).toString();
}
return Paths.get(path, testfile).toString();
}

I find this to be very clunky, but it was the only way I could get my tests to reliably work in Maven, Bazel, and the IDE.

Helen

unread,
Apr 20, 2016, 8:28:27 PM4/20/16
to bazel-discuss
Thanks Alex and Ronnie!

I tried Ronnie's approach and it worked. The directory the resources live in is something like:
 /private/var/tmp/_bazel_helen/27683dcc4905fc6bfddcd381450719bc/main/bazel-out/local_darwin-fastbuild/bin/packagename/AllTests.runfiles/packagenamel/src/test/resources/util/img.bmp
Reply all
Reply to author
Forward
0 new messages