これは、なにをしたくて書いたもの?
前にBashのテスティングフレームワークである、Batsのチュートリアルを試しました。
Bashのテスティングフレームワーク、Batsを試す - CLOVER🍀
この時、bats-assertおよびbats-supportをロードするのにload関数で絶対パスを指定するのが嫌だなと思っていたのですが、bats_load_libraryを
使うと少し改善されそうなので試してみることにしました。
bats_load_library関数
bats_load_libraryは、システムにインストールされたライブラリーをロードする関数です。
Writing tests / bats_load_library: Load system wide libraries
BATS_LIB_PATHという環境変数を使って、次の動作を行うようです。
- ライブラリーのファイルを
BATS_LIB_PATHからの相対パスとして解釈する - ライブラリー名には、
load.bashというエントリーポイントを示すファイルがある
たとえば、BATS_LIB_PATHが~/.bats/libs:/usr/lib/bats(:区切りで複数パスの設定可)と設定されている場合に以下のように書くと
setup() {
bats_load_library test_helper
}
test_helperの探索パスは以下になります。
- ~/.bats/libs/test_helper
- ~/.bats/libs/test_helper/load.bash
- /usr/lib/bats/test_helper
- /usr/lib/bats/test_helper/load.bash
ライブラリーの一部だけをロードしたい場合や、エントリーポイントがload.bashではない場合はbats_load_library関数の引数に指定する必要が
あります。
たとえば以下の例だと
setup() {
bats_load_library library_name/file_to_load
}
探索パスは以下になります。
- ~/.bats/libs/library_name/file_to_load
- ~/.bats/libs/library_name/file_to_load/load.bash
- /usr/lib/bats/library_name/file_to_load
- /usr/lib/bats/library_name/file_to_load/load.bash
ちなみにディストリビューションのパッケージのメンテナー向けではありますが、BATS_LIB_PATHは/usr/lib/bats/に設定することが推奨されて
いるようです。
では、少し試してみましょう。
環境
今回の環境はこちら。
$ bash --version GNU bash, バージョン 5.2.21(1)-release (x86_64-pc-linux-gnu) Copyright (C) 2022 Free Software Foundation, Inc. ライセンス GPLv3+: GNU GPL バージョン 3 またはそれ以降 <http://gnu.org/licenses/gpl.html> This is free software; you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. $ apt search ^bats.* ソート中... 完了 全文検索... 完了 bats/noble,noble,now 1.10.0-1 all [インストール済み] bash automated testing system bats-assert/noble,noble,now 2.1.0-3 all [インストール済み] Helper library providing common assertions for Bats bats-file/noble,noble,now 0.4.0-1 all [インストール済み] Helper library providing filesystem-related assertions for Bats bats-support/noble,noble,now 0.3.0-4 all [インストール済み、自動] Supporting library to test bats helper libraries
bats_load_library関数を使ってみる
以前のチュートリアルのエントリーで使ったコードを、bats_load_library関数で書き換えてみたいと思います。
Bashのテスティングフレームワーク、Batsを試す - CLOVER🍀
テスト対象。
src/project.sh
#!/bin/bash echo 'Welcome to our project!' echo 'NOT IMPLEMENTED!' >&2 exit 1
テストコード。
test/test.bats
setup() {
load '/usr/lib/bats/bats-support/load'
load '/usr/lib/bats/bats-assert/load'
DIR=$(cd $(dirname $BATS_TEST_FILENAME) >/dev/null 2>&1 && pwd)
PATH="$DIR/../src:$PATH"
}
@test "can run our script" {
run project.sh
assert_output --partial 'Welcome to our project!'
}
確認。
$ bats test/test.bats test.bats ✓ can run our script 1 test, 0 failures
見てのとおり、bats-supportとbats-assertは/usr/lib/batsディレクトリー配下にあります。
setup() {
load '/usr/lib/bats/bats-support/load'
load '/usr/lib/bats/bats-assert/load'
DIR=$(cd $(dirname $BATS_TEST_FILENAME) >/dev/null 2>&1 && pwd)
PATH="$DIR/../src:$PATH"
}
では、bats_load_library関数を使ってテストコードをこのように書き換えてみます。
test/test.bats
setup() {
# load '/usr/lib/bats/bats-support/load'
# load '/usr/lib/bats/bats-assert/load'
bats_load_library bats-support
bats_load_library bats-assert
DIR=$(cd $(dirname $BATS_TEST_FILENAME) >/dev/null 2>&1 && pwd)
PATH="$DIR/../src:$PATH"
}
@test "can run our script" {
run project.sh
assert_output --partial 'Welcome to our project!'
}
確認。
$ bats test/test.bats test.bats ✓ can run our script 1 test, 0 failures
テストをパスしました。いいですね。
BATS_LIB_PATHのデフォルト値?
ところで、今回はBATS_LIB_PATH環境変数を設定しているわけではありません。
$ env | grep BATS
今回はいったいどのような設定で動作したんでしょうね?
答えは、batsコマンドのようです。
https://github.com/bats-core/bats-core/blob/v1.10.0/libexec/bats-core/bats#L123
batsコマンドは、最後にlibexecディレクトリー内にあるコマンドを実行するようになっています。
$ tail -n 1 $(which bats) exec env BATS_ROOT="$BATS_ROOT" "$BATS_ROOT/libexec/bats-core/bats" "$@"
この中に、BATS_LIB_PATH環境変数が定義されていない場合はデフォルト値が/usr/lib/batsになるようになっています。
$ grep BATS_LIB_PATH /usr/libexec/bats-core/bats
export BATS_LIB_PATH=${BATS_LIB_PATH-/usr/lib/bats}
せっかくなので確認してみましょう。
テストを書いて
test/lib.bats
setup() {
bats_load_library bats-support
bats_load_library bats-assert
}
@test "BATS_LIB_PATH default value" {
assert_equal "$BATS_LIB_PATH" '/usr/lib/bats'
}
確認。
$ bats test/lib.bats lib.bats ✓ BATS_LIB_PATH default value 1 test, 0 failures
OKですね。
おわりに
Batsのbats_load_library関数で、ロードするライブラリーのパスを簡潔に指定できることを確認してみました。
チュートリアルを扱った時はload関数しか知らなかったので「絶対パスを書くのは嫌だな…」と思っていたのですが、bats_load_library関数の
おかげでちょっと印象が変わりましたね。
せっかくなので使っていきましょう。