1

I want to convert our integration pytests over to bazel, but it doesn't seem to actually run nor produce the junitxml output I'm expecting:

ARGS = [
    "--verbose",
    "--json-report",
    "--junit-xml=junit.xml",
]

py_test(
    name = "test_something",
    srcs = ["test_something.py"],
    args = ARGS,
    tags = [
        "yourit",
    ],
    deps = [
        requirement("pytest"),
        requirement("pytest-json-report"),
        ":lib",
    ],
)

There is a similar question here: How do I use pytest with bazel?. But it didn't cover the multitude of issues I ran into.

Dennis Hoer
  • 3,039
  • 2
  • 23
  • 34

1 Answers1

2

So there were multiple things to address in order to make bazel's py_test work with pytest.

  1. Of course you need the pytest dependency requirement("pytest") added.

  2. The pytest files require a hook being added (note that the args are passed as well sys.argv[1:], so py_test args can be passed on to the pytest file):

    if __name__ == "__main__":
       sys.exit(pytest.main(\[__file__\] + sys.argv\[1:\]))
    
  3. Since our pytests are trying to access the host network, we need to tell bazel to allow network traffic outside the sandbox by adding a requires-network tag.

  4. The host network is local, so we need to make sure the test runs locally by adding the local tag.

  5. Bazel py_test will create junitxml under bazel-testlogs, but it only shows if py_test rule passed or failed. To get more granular junitxml results, we need to tell pytest how to overwrite bazel's py_test results using XML_OUTPUT_FILE environment variable. Note the $$ is needed to prevent variable expansion. See https://docs.bazel.build/versions/main/test-encyclopedia.html and https://github.com/bazelbuild/bazel/blob/master/tools/test/test-setup.sh#L67 for more info.

  6. Attempts to write json report output to bazel-testlogs using TEST_UNDECLARED_OUTPUTS_DIR environment variable didn't work. The report is still written, but inside bazel-out. There might be a way to scoop up those files, but solving that problem was not a priority.

  7. Note that the ARGS is used to keep it DRY (don't repeat yourself). We use the same arguments across multiple py_test rules.

So the BUILD now looks like this:

ARGS = [
    "--verbose",
    "--json-report",
    "--junit-xml=$$XML_OUTPUT_FILE",
]

py_test(
    name = "test_something",
    srcs = ["test_something.py"],
    args = ARGS,
    tags = [
        "local",
        "requires-network",
        "yourit",
    ],
    deps = [
        requirement("pytest"),
        requirement("pytest-json-report"),
        ":lib",
    ],
)
Dennis Hoer
  • 3,039
  • 2
  • 23
  • 34