0

I'd like to check a text file in our monorepo codebase via JUnit tests. JUnit tests are executed via bazel test command. How can I configure Bazel to pass the source code directory path (not cached compiled JAR file path) to my unit tests? it could be CLI args, environment variables, etc.

1 Answer 1

0

One way to do this is to use the data attribute which makes files available to tests (and other binaries) at runtime, and for Java there's the Runfiles library provided with Bazel for finding data files. E.g.:

BUILD:

java_test(
  name = "TextFileTest",
  srcs = ["javatests/txtfile/TextFileTest.java"],
  data = ["text.txt"],
  deps = [
      "@bazel_tools//tools/java/runfiles:runfiles",
      "@maven//:junit_junit",
  ],
)

WORKSPACE:

load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")

RULES_JVM_EXTERNAL_TAG = "4.2"
RULES_JVM_EXTERNAL_SHA = "cd1a77b7b02e8e008439ca76fd34f5b07aecb8c752961f9640dea15e9e5ba1ca"

http_archive(
    name = "rules_jvm_external",
    strip_prefix = "rules_jvm_external-%s" % RULES_JVM_EXTERNAL_TAG,
    sha256 = RULES_JVM_EXTERNAL_SHA,
    url = "https://github.com/bazelbuild/rules_jvm_external/archive/%s.zip" % RULES_JVM_EXTERNAL_TAG,
)

load("@rules_jvm_external//:defs.bzl", "maven_install")

maven_install(
    artifacts = [
        "junit:junit:4.13.2",
    ],
    repositories = [
        "https://repo1.maven.org/maven2",
    ],
)

javatests/txtfile/TextFileTest.java:

package txtfile;

import com.google.devtools.build.runfiles.Runfiles;

import java.nio.file.Files;
import java.nio.file.Paths;
import java.nio.file.Path;

import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;

@RunWith(JUnit4.class)
public class TextFileTest {

  @Test
  public void testTextFile() throws Exception {
    Runfiles runfiles = Runfiles.create();
    Path path = Paths.get(runfiles.rlocation("__main__/text.txt"));
    String line = Files.readAllLines(path).get(0);
    Assert.assertEquals(line, "this is text");
  }
}

text.txt:

this is text
$ bazel test TextFileTest
INFO: Build option --test_sharding_strategy has changed, discarding analysis cache.
INFO: Analyzed target //:TextFileTest (0 packages loaded, 547 targets configured).
INFO: Found 1 test target...
Target //:TextFileTest up-to-date:
  bazel-bin/TextFileTest.jar
  bazel-bin/TextFileTest
INFO: Elapsed time: 0.288s, Critical Path: 0.01s
INFO: 1 process: 1 internal.
INFO: Build completed successfully, 1 total action
//:TextFileTest                                                 (cached) PASSED in 0.3s

Executed 0 out of 1 test: 1 test passes.
INFO: Build completed successfully, 1 total action

Note that in runfiles.rlocation("__main__/text.txt") the __main__ is the workspace name, which by default is __main__. If there's a workspace(name = "workspace name") in the WORKSPACE file, then the workspace name would be set from that.

Sign up to request clarification or add additional context in comments.

5 Comments

Thanks for the snippet. This is not exactly what I'm looking for. This gets me the path to text.txt inside Bazel's sandbox, e.g. /home/username/.cache/bazel/_bazel_username/fb0aa84527816b9bbc697a27654311ce/sandbox/linux-sandbox/24/execroot/myworkspace/bazel-out/k8-fastbuild/bin/javatest/mytarget.runfiles/myworkspace/text.txt. however, I want the absolute path to the local Git repository of my project(source files outside of Bazel sandbox) e.g. /home/username/Documents/myproject.
Bazel doesn't provide this in general because it would make it easier to write things that don't work with sandboxing, or with remote execution, or are non-reproducible. But, if you really need this, you can take advantage of the fact that (on linux and mac) data files in the runfiles tree are symlinks to files in the source tree. So toRealPath() will give you the path in the workspace, and you can get the workspace root based on where the data file is.
that's a nice trick. I decided to write a separate python script for the CI check I needed to do. It's better to respect the sandboxing practices of Bazel.
Yeah that sounds best
Though one way that might be better than what I described above is to use --action_env. It would need to be specified on the command line every time though (something like --action_env=WORKSPACE_DIR=$(pwd), if you're invoking bazel from the workspace root)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.