Skip to content

Commit df19640

Browse files
katrecgrindel
andauthored
Add a facility for running script tests (#161)
Script tests are shell scripts that take a Bazel binary and create their own workspace directories, set up files, etc. These are similar to the existing integration tests in https://github.com/bazelbuild/bazel/tree/master/src/test/shell/integration. --------- Co-authored-by: Chuck Grindel <chuck.grindel@gmail.com>
1 parent b919543 commit df19640

File tree

5 files changed

+171
-2
lines changed

5 files changed

+171
-2
lines changed

.bazelrc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@
33
# This lets us glob() up all the files inside the examples to make them inputs to tests
44
# (Note, we cannot use `common --deleted_packages` because the bazel version command doesn't support it)
55
# To update these lines, run tools/update_deleted_packages.sh
6-
build --deleted_packages=examples/custom_test_runner,examples/custom_test_runner/Sources/CustomTestRunner,examples/custom_test_runner/Sources/CustomTestRunnerLib,examples/custom_test_runner/Tests/CustomTestRunnerTests,examples/custom_test_runner/integration_tests,examples/custom_test_runner/integration_tests/workspace,examples/env_var_with_rootpath/sample_workspace,examples/simple,examples/simple/mockascript,examples/simple/mockascript/private,examples/simple/tests,tests/params_tests/workspace
7-
query --deleted_packages=examples/custom_test_runner,examples/custom_test_runner/Sources/CustomTestRunner,examples/custom_test_runner/Sources/CustomTestRunnerLib,examples/custom_test_runner/Tests/CustomTestRunnerTests,examples/custom_test_runner/integration_tests,examples/custom_test_runner/integration_tests/workspace,examples/env_var_with_rootpath/sample_workspace,examples/simple,examples/simple/mockascript,examples/simple/mockascript/private,examples/simple/tests,tests/params_tests/workspace
6+
build --deleted_packages=examples/custom_test_runner,examples/custom_test_runner/integration_tests,examples/custom_test_runner/integration_tests/workspace,examples/custom_test_runner/Sources/CustomTestRunner,examples/custom_test_runner/Sources/CustomTestRunnerLib,examples/custom_test_runner/Tests/CustomTestRunnerTests,examples/env_var_with_rootpath/sample_workspace,examples/simple,examples/simple/mockascript,examples/simple/mockascript/private,examples/simple/tests,tests/params_tests/workspace
7+
query --deleted_packages=examples/custom_test_runner,examples/custom_test_runner/integration_tests,examples/custom_test_runner/integration_tests/workspace,examples/custom_test_runner/Sources/CustomTestRunner,examples/custom_test_runner/Sources/CustomTestRunnerLib,examples/custom_test_runner/Tests/CustomTestRunnerTests,examples/env_var_with_rootpath/sample_workspace,examples/simple,examples/simple/mockascript,examples/simple/mockascript/private,examples/simple/tests,tests/params_tests/workspace
88

99
# Import Shared settings
1010
import %workspace%/shared.bazelrc

bazel_integration_test/defs.bzl

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,10 @@ load(
1717
"//bazel_integration_test/private:integration_test_utils.bzl",
1818
_integration_test_utils = "integration_test_utils",
1919
)
20+
load(
21+
"//bazel_integration_test/private:script_test.bzl",
22+
_script_test = "script_test",
23+
)
2024

2125
# Macros
2226
bazel_integration_test = _bazel_integration_test
@@ -28,3 +32,6 @@ bazel_binaries = _bazel_binaries
2832

2933
# APIs
3034
integration_test_utils = _integration_test_utils
35+
36+
# Script tests
37+
script_test = _script_test
Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
"A facility for script tests that create workspaces and call Bazel."
2+
3+
load(
4+
"//bazel_integration_test/private:bazel_integration_test.bzl",
5+
"bazel_integration_test",
6+
)
7+
8+
_RUNNER_SCRIPT = """
9+
#!/bin/bash
10+
11+
script="${PWD}/%s"
12+
13+
working_dir="${BIT_WORKSPACE_DIR:-}"
14+
cd "${working_dir}"
15+
16+
# Run the actual tests
17+
# Bazel is available as ${BIT_BAZEL_BINARY}.
18+
if "${script}"; then
19+
echo "test passed"
20+
else
21+
echo "test failed"
22+
exit 1
23+
fi
24+
25+
exit 0
26+
"""
27+
28+
def _write_runner_impl(ctx):
29+
script = ctx.file.script
30+
runner = ctx.outputs.out
31+
32+
ctx.actions.write(
33+
output = runner,
34+
content = _RUNNER_SCRIPT % script.path,
35+
)
36+
37+
return [DefaultInfo(
38+
executable = runner,
39+
runfiles = ctx.runfiles(files = ctx.files.script),
40+
)]
41+
42+
_write_runner = rule(
43+
implementation = _write_runner_impl,
44+
attrs = {
45+
"out": attr.output(mandatory = True),
46+
"script": attr.label(allow_single_file = True, mandatory = True),
47+
},
48+
executable = True,
49+
)
50+
51+
def script_test(
52+
name,
53+
srcs,
54+
deps,
55+
bazel_binaries,
56+
bazel_version):
57+
"""
58+
Macro that allows writing script tests which create a Bazel workspace and call the binary directly.
59+
60+
These are intended to be like the Bazel integration tests found at https://github.com/bazelbuild/bazel/tree/master/src/test/shell/integration.
61+
62+
Tests will find the Bazel binary via the `${BIT_BAZEL_BINARY}` environment variable.
63+
64+
Args:
65+
name: name of the resulting test
66+
srcs: The file containing the shell script. This attribute must be a
67+
singleton list, whose only element is the shell script. This script
68+
must be executable, and may be a source file or a generated file. All
69+
other files required at runtime (whether scripts or data) belong in the
70+
deps attribute.
71+
deps: The list of library targets to be used in this test.
72+
bazel_binaries: Optional for WORKSPACE loaded repositories. Required
73+
for repositories that enable bzlmod. The value for this parameter
74+
is loaded by adding
75+
`load("@bazel_binaries//:defs.bzl", "bazel_binaries")` to your
76+
build file.
77+
bazel_version: Optional. A `string` value representing the semantic
78+
version of Bazel to use for the integration test. If a
79+
version is not specified, then the `bazel_binary` must
80+
be specified.
81+
"""
82+
runner_script = "%s_runner.sh" % name
83+
runner_target = "%s_runner" % name
84+
85+
if len(srcs) != 1:
86+
fail("script_test.srcs must be a singleton list, got %s" % srcs)
87+
88+
src = srcs[0]
89+
90+
# Generate the test runner script that calls inner.
91+
_write_runner(
92+
name = "generate_%s" % runner_target,
93+
script = src,
94+
out = runner_script,
95+
testonly = True,
96+
)
97+
98+
# Create the test runner that sets up and calls the test.
99+
native.sh_binary(
100+
name = runner_target,
101+
testonly = True,
102+
srcs = [runner_script],
103+
data = [src],
104+
deps = deps,
105+
tags = ["manual"],
106+
)
107+
108+
# The actual test that is invoked.
109+
bazel_integration_test(
110+
name = name,
111+
bazel_binaries = bazel_binaries,
112+
bazel_version = bazel_version,
113+
test_runner = ":%s" % runner_target,
114+
)

examples/BUILD.bazel

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ load(
66
"bazel_integration_tests",
77
"default_test_runner",
88
"integration_test_utils",
9+
"script_test",
910
)
1011

1112
bzlformat_pkg(name = "bzlformat")
@@ -119,6 +120,19 @@ bazel_integration_test(
119120
test_runner = ":dynamic_workspace_test_runner",
120121
)
121122

123+
# MARK: - script_test sample
124+
125+
script_test(
126+
name = "sample_script_test",
127+
srcs = ["sample_script_test.sh"],
128+
bazel_binaries = bazel_binaries,
129+
bazel_version = bazel_binaries.versions.current,
130+
deps = [
131+
"@bazel_tools//tools/bash/runfiles",
132+
"@cgrindel_bazel_starlib//shlib/lib:assertions",
133+
],
134+
)
135+
122136
# MARK: - Test Suite
123137

124138
# By default, the integration test targets are tagged as `manual`. This
@@ -133,6 +147,7 @@ test_suite(
133147
tests = [
134148
":custom_test_runner_test",
135149
":dynamic_workspace_test",
150+
":sample_script_test",
136151
":simple_test",
137152
":use_create_scratch_dir_test",
138153
] + integration_test_utils.bazel_integration_test_names(

examples/sample_script_test.sh

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
#!/bin/bash
2+
3+
# A sample test script which wants to execute Bazel commands and check the
4+
# result with assertions. script tests are responsible for creating the needed
5+
# files in the workspace and calling `${bazel}` as needed.
6+
7+
# --- begin runfiles.bash initialization v2 ---
8+
# Copy-pasted from the Bazel Bash runfiles library v2.
9+
set -uo pipefail; f=bazel_tools/tools/bash/runfiles/runfiles.bash
10+
source "${RUNFILES_DIR:-/dev/null}/$f" 2>/dev/null || \
11+
source "$(grep -sm1 "^$f " "${RUNFILES_MANIFEST_FILE:-/dev/null}" | cut -f2- -d' ')" 2>/dev/null || \
12+
source "$0.runfiles/$f" 2>/dev/null || \
13+
source "$(grep -sm1 "^$f " "$0.runfiles_manifest" | cut -f2- -d' ')" 2>/dev/null || \
14+
source "$(grep -sm1 "^$f " "$0.exe.runfiles_manifest" | cut -f2- -d' ')" 2>/dev/null || \
15+
{ echo>&2 "ERROR: cannot find $f"; exit 1; }; f=; set -e
16+
# --- end runfiles.bash initialization v2 ---
17+
18+
# Use shlib assertions for testing.
19+
assertions_sh_location=cgrindel_bazel_starlib/shlib/lib/assertions.sh
20+
assertions_sh="$(rlocation "${assertions_sh_location}")" || \
21+
(echo >&2 "Failed to locate ${assertions_sh_location}" && exit 1)
22+
# shellcheck disable=SC1090 # external source
23+
source "${assertions_sh}"
24+
25+
logfile="${TEST_TMPDIR}/test.log"
26+
27+
# Verify the Bazel binary by checking the release number.
28+
touch WORKSPACE
29+
${BIT_BAZEL_BINARY} info release > "${logfile}"
30+
31+
if ! grep -E -q "^release [0-9]+\.[0-9]+\.[0-9]$" "${logfile}"; then
32+
fail "Did not find release in output of $(bazel info release)"
33+
fi

0 commit comments

Comments
 (0)