sh_test is my most commonly used test rule by far. It is the easiest way to
write quick-and-dirty tests and works nearly everywhere. For anything beyond
the most trivial tests, I use Bazel’s Bash unit test framework. This explains
what the framework is and how to use it.
Within Bazel’s source code there exist a Bash unit test framework called
unittest.bash. This framework allows you to write a test script as
a collection of test cases, each implemented as a Bash function. The
Bash unit test framework integrates nicely with Bazel, as it:
- Provides a series of assertions such as
assert_equalsandexpect_log - Supports filtering test cases using
--test_filter - Supports suite
set_upandtear_downfunctions - Ensures that each test is run in a new subshell and in its own directory
- Implements the Bazel test sharding protocol
Unlike bazel_tool’s runfiles.bash, I have not figured out how to
refer to the Bash unittest framework directly, so I use the Bash unit
test framework as follows:
- Download
unittest.bashandunittest_utils.shinto their own directory, typically//tools/bash/unittest - Wrap these two scripts into a
sh_library()calledunittest:
# //tools/bash/unittest:BUILD.bazel
sh_library(
name = "unittest",
srcs = [
"unittest.bash",
"unittest_utils.sh",
],
visibility = ["//visibility:public"],
)
- Add the
unittestlibrary as a dependency to my test script:
sh_test(
name = "my_test",
srcs = ["my_test.sh"],
deps = ["//tools/bash/unittest"],
)
- Use the Bash unit test framework within the test script:
#!/bin/bash
#
# my_test.sh: A sample sh_test written using the unittest.bash framework
source ./tools/bash/unittest/unittest.bash || exit 1
function test_example() {
assert_equals 1 2 # cause a deliberate test failure
}
run_suite "my test suite"
To learn more about how to use Bash unit test framework, see the comments in
unittest.bash.