Practical Bazel: Using Bazel’s Bash Unittest Framework
Practical Bazel bazel bash
Published: 2023-02-26
Practical Bazel: Using Bazel's Bash Unittest Framework

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_equals and expect_log
  • Supports filtering test cases using --test_filter
  • Supports suite set_up and tear_down functions
  • 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:

  1. Download unittest.bash and unittest_utils.sh into their own directory, typically //tools/bash/unittest
  2. Wrap these two scripts into a sh_library() called unittest:
1
2
3
4
5
6
7
8
9
# //tools/bash/unittest:BUILD.bazel
sh_library(
    name = "unittest",
    srcs = [
        "unittest.bash",
        "unittest_utils.sh",
    ],
    visibility = ["//visibility:public"],
)
  1. Add the unittest library as a dependency to my test script:
1
2
3
4
5
sh_test(
    name = "my_test",
    srcs = ["my_test.sh"],
    deps = ["//tools/bash/unittest"],
)
  1. Use the Bash unit test framework within the test script:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
#!/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.