Load helpers in Bats
Share code between Bats tests with load helpers, which reads helpers.bash from the test file's directory. A plain source breaks when bats runs from elsewhere.
A helper file sourced from a test works on your machine and fails in CI, which starts Bats from a different directory.
mkdir -p tests
cat > tests/helpers.bash <<'EOT'
greet() { echo "hello $1"; }
EOT
cat > tests/with_load.bats <<'EOT'
load helpers
@test "load finds the helper next to the test" {
run greet ada
[ "$output" = "hello ada" ]
}
EOT
cat > tests/with_source.bats <<'EOT'
source tests/helpers.bash
@test "source depends on the current directory" {
run greet ada
[ "$output" = "hello ada" ]
}
EOT
dir=$PWD
bats tests/with_load.bats tests/with_source.bats | head -n 3
echo ---
cd / && bats "$dir/tests/with_load.bats" "$dir/tests/with_source.bats" 2>&1 | head -n 61..2
ok 1 load finds the helper next to the test
ok 2 source depends on the current directory
---
1..2
ok 1 load finds the helper next to the test
not ok 2 setup_file failed
# (in test file /tmp/run/S1905-1/w/tests/with_source.bats, line 1)
# `source tests/helpers.bash' failed with status 0
# /tmp/run/S1905-1/w/tests/with_source.bats: line 1: tests/helpers.bash: No such file or directoryload name looks for name.bash in the directory of the test file, so it works wherever Bats is started from. The other file uses source with a path relative to the project root, which works only while that root is the current directory, and the second run from / shows it failing before any test runs. The command is documented in the Bats manual.
load adds .bash to the name unless the name already ends in it, and an absolute path is used as it is. For helper libraries installed elsewhere, such as bats-assert, load them by an absolute path or one built from BATS_TEST_DIRNAME. Code in a loaded file runs once per test, since every test is its own process, so keep it quick.