これは、なにをしたくて書いたもの?
Bash関数のテストをBatsで書くには?と思って調べてみたのですが、なんのことはなくrunで実行すればよいだということが
わかりました。
せっかくなので練習を兼ねて書いてみます。
またrunコマンドについても詳しく見ておきましょう。
runでテスト対象の関数を呼び出す
前にBatsを使った時はrunコマンドでシェルスクリプトを呼び出していたのですが、関数についてもrunコマンドを使えば
よいみたいです。
あらためてrun関数の説明を見てみます。
run関数は、そもそもコマンドを実行する関数だと書かれていますね。
Many Bats tests need to run a command and then make assertions about its exit status and output. Bats includes a run helper that invokes its arguments as a command, saves the exit status and output into special global variables, and then returns with a 0 status code so you can continue to make assertions in your test case.
Writing tests / run: Test other commands
終了ステータスと出力を特別なグローバル変数に格納します。
特別なグローバル変数とは以下の4つです。
$status… コマンドのステータスコード$output… コマンドの標準出力と標準エラー出力$BATS_RUN_COMMAND… 実行したコマンドと引数$lines… 出力の個々の行を格納した配列。デフォルトでは空行は省略される
出力についてですが、--separate-stderrを使うと標準出力と標準エラー出力を$outputと$stderr、
${lines[@]}と${stderr_lines[@]}に分割できるようです。
なお、runコマンドはサブシェルで実行されます。
あまり使わない気もしますが、パイプを使いたい場合はサブシェルを使います。
run bash -c "command args ... | jq -e '.limit == 42'"
あとは簡単に使っていってみます。
環境
今回の環境はこちら。
$ 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.
Bats。
$ bats --version Bats 1.10.0 $ 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でBash関数のテストを書く
まずはテスト対象を用意。
src/func.sh
#!/bin/bash greeting() { local name=$1 echo "Hello ${name}!!" return 0 } always_fail() { return 1 } multiple_line() { cat << EOS hello world EOS }
少しわざとらしいですが、runコマンドの確認を兼ねています。
テストコードの雛形はこちら。
test/func.bats
setup() { bats_load_library bats-support bats_load_library bats-assert DIR=$(cd "$(dirname "$BATS_TEST_FILENAME")" > /dev/null 2>&1 && pwd) # shellcheck disable=SC1091 source "${DIR}/../src/func.sh" } # ここにテストを書く
引数付きの関数呼び出し。
@test "test greeting function" { run greeting 'World' assert_success assert_output 'Hello World!!' }
runコマンドのグローバル変数は使っていません。
使った場合はこんな感じですね。
@test "test greeting function2" { run greeting 'Bats' assert_equal "$status" 0 assert_equal "$output" 'Hello Bats!!' assert_equal "$BATS_RUN_COMMAND" 'greeting Bats' }
0で終了しない関数の場合。
@test "test always fail function" { run always_fail assert_failure assert_failure 1 assert_equal $status 1 }
複数行を出力する関数のテスト。
@test "test multiple line" { multiple_line run multiple_line assert_success assert_output --partial "hello" assert_output --partial "world" assert_equal "${lines[0]}" "hello" assert_equal "${lines[1]}" "world" assert_equal "${lines[*]}" "hello world" }
こんなところでしょうか。
アサーションはこちらを確認しましょう。
GitHub - bats-core/bats-assert at v2.1.0
おわりに
BatsでBash関数のテストを書いてみました。
これ自体はふつうにrunコマンドを使えばよかったのでなんのことはなかったのですが、せっかくなのでrunコマンドに
ついてもちゃんと見ておきました。
シェルスクリプトを書くのは得意ではない割に書く機会が妙に増えている気がするので、慣れておきたいですね…。