Folioscope

プログラミング/Unix系/デザイン/CG などのメモがもりもり

Bash用ユニットテストフレームワーク作りました

Bash用テストフレームワークに、Batsshunit2がありますが、イケてないなーと思ってたら、気づいたら自分で作ってました。

github.com

テストの結果はモダンなテストフレームワークのように、カラフルに表示します。

f:id:ibenza:20151102185312p:plain

またFAIL時は、FAILしたテストの結果を表示します。

f:id:ibenza:20151102185316p:plain

自分の Arch Linux 上の Bash 4.3.42 および、Travis CI 上で動作することを確認しています。

インストール

curl -o ~/bin/bashtub https://raw.githubusercontent.com/ueokande/bashtub/v0.1/bin/bashtub
chmod +x ~/bin/bashtub

です。ただし~/binはパスが通ってるとします。 これでターミナルから bashtub と打つことで実行できます。

bashtub

テストを書く

各テストケースは testcase_ で始まる関数内に記述するだけで、 bashtub が勝手に実行します。 テストはxUnit系のようにassertionベースで書きます。

最初のテスト

まずはシンプルな例を示します。

# first_test_case.sh
lorem_ipsum='lorem ipsum dolor sit amet'

testcase_first_word() {
  first_word=$(echo $lorem_ipsum | cut -f1 -d' ')
  assert_equal 'lorem' $first_word
}

testcase_word_count() {
  number_of_words=$(echo $lorem_ipsum | wc -w)
  assert_match 5 $number_of_words
}

1つ目の testcase_word_count$lorem_ipsum 内に文字列 lorem を含むかチェックします. 2つ目の testcase_word_count は、$lorem_ipsum に含まれる単語数を調べます。 テストを実行するには、bashtubにテストファイルを指定します。 するとテストの結果が表示されます。

bashtub first_test_case.sh

subject ヘルパーメソッド

コマンドのstdout, stderr および終了コードを簡単にキャプチャする、 subject ヘルパーメソッドを用意しています。 いま Hello を各言語に変換してstdoutに出力する関数 hello_in があるとします。 指定された言語が非対応の場合、stderrにエラーを表示して終了コード1を返します。

hello_in() {
  case $1 in
  english) echo Hello;;
  italian) echo Ciao;;
  *) echo unsupported $1 >&2; return 1;;
  esac
  return 0
}

そしてこの関数をテストするための、 subject メソッドの使用例を以下に示します。 このテストでは、標準操作時のstdoutと、例外処理時のstderrと終了コードをチェックします。

testcase_translate_to_english() {
  subject hello_in english
  assert_equal 0 $status
  assert_match 'Hello' "$stdout"
}

testcase_translate_to_unsupported_language() {
  subject hello_in bash
  assert_equal 1 $status
  assert_match 'bash' "$stderr"
}

その他のアサーション

assert_equal

assert_equal expected actual

actualexpected と等しいならパスします。

assert_match

assert_match regex actual

actual正規表現 regex とマッチするならパスします。

assert_true/assert_false

assert_true command
assert_false command

assert_trueassert_false は、指定されたコマンドの終了コードが、それぞれ0、0以外ならパスします。 assert_truesubject メソッドで終了コードを0と等しいかチェックするのと等価です。 したがって以下のテストケースは同じ結果となります。

assert_true command
subject command
assert_equal 0 $status

setupteardown

テストの初期化処理・終了処理を記述するのに、setupteardown が便利です。 最も典型的な使い方として、setup で一時ファイルを作成し、teardown で削除します。 これは mktemp コマンドと相性が良いです。

setup() {
  TMPDIR=$(mktemp -d)
}

teardown() {
  rm -rf "$TMPDIR"
}

testcase_file_is_empty() {
  local tmpfile=$(mktemp -p $TMPDIR)
  subject file $tmpfile
  assert_match "empty" "$stdout"
}

開発について

開発はGitHub上で行っており、pull req. 大歓迎です。

ueokande/bashtub · GitHub