私が長年にわたって取り組んできたほとんどすべての製品には、何らかのレベルのシェルスクリプト(またはWindowsのバッチファイル、PowerShellなど)が関係しています。コードの大部分をJavaまたはC++で記述しましたが、シェルスクリプトを使用した方がよい統合タスクまたはインストールタスクが常に存在するように見えました。
したがって、シェルスクリプトは出荷されたコードの一部になるため、コンパイルされたコードと同様にテストする必要があります。 shunit2 など、世の中にあるシェルスクリプトユニットテストフレームワークの経験がある人はいますか?今のところ、主にLinuxシェルスクリプトに興味があります。テストハーネスが他のxUnitフレームワークの機能と使いやすさをいかにうまく複製できるか、CruiseControlやHudsonなどの継続的なビルドシステムとの統合がいかに簡単かを知りたいと思います。
更新2019-03-01:私の好みは bats nowです。私は数年間小さなプロジェクトでそれを使用しました。簡潔で簡潔な構文が好きです。 CI/CDフレームワークと統合していませんが、終了ステータスはスイートの全体的な成功/失敗を反映しており、以下に説明するshunit2よりも優れています。
前の回答:
Linux環境のJava/Ruby Webアプリケーションに関連するシェルスクリプトに shunit2 を使用しています。使いやすく、他のxUnitフレームワークから大きく逸脱していません。
CruiseControlやHudson/Jenkinsとの統合を試みたことはありませんが、他の手段で継続的な統合を実装する際に、これらの問題に遭遇しました。
[〜#〜] bats [〜#〜] 。誰も言及しなかった理由を疑問に思う。最新かつ [〜#〜] tap [〜#〜] に準拠しています。
説明する:
#!/usr/bin/env bats
@test "addition using bc" {
result="$(echo 2+2 | bc)"
[ "$result" -eq 4 ]
}
実行:
$ bats addition.bats
✓ addition using bc
1 tests, 0 failures
@ blake-mizeranyによるまとめは素晴らしいと思います。将来的にそれを利用する必要がありますが、単体テストを作成するための私の「貧乏人」アプローチは次のとおりです。
functions.sh
およびsource
itをスクリプトに移動します。この目的でsource `dirname $0`/functions.sh
を使用できます。functions.sh
の最後に、以下のif条件にテストケースを埋め込みます。
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
fi
テストは、関数のリテラルコールと、それに続く終了コードと変数値の簡単なチェックです。以下のような単純なユーティリティ関数を追加して、簡単に記述できるようにします。
function assertEquals()
{
msg=$1; shift
expected=$1; shift
actual=$1; shift
if [ "$expected" != "$actual" ]; then
echo "$msg EXPECTED=$expected ACTUAL=$actual"
exit 2
fi
}
最後に、functions.sh
を直接実行してテストを実行します。
アプローチを示すサンプルを次に示します。
#!/bin/bash
function adder()
{
return $(($1+$2))
}
(
[[ "${BASH_SOURCE[0]}" == "${0}" ]] || exit 0
function assertEquals()
{
msg=$1; shift
expected=$1; shift
actual=$1; shift
/bin/echo -n "$msg: "
if [ "$expected" != "$actual" ]; then
echo "FAILED: EXPECTED=$expected ACTUAL=$actual"
else
echo PASSED
fi
}
adder 2 3
assertEquals "adding two numbers" 5 $?
)
まとめ: http://bmizerany.github.com/roundup/
READMEで詳細に説明している記事にリンクがあります。
roundup および shunit2 に加えて、シェルユニットテストツールの概要にも assert.sh および shelltestrunner が含まれていました。
筆者はshunit2(一部は主観的)についての総括著者の批判にほぼ同意するため、ドキュメントと例を見てからshunit2を除外しました。ただし、jUnitの使用経験があることはおなじみのようです。
私の意見では、shelltestrunnerは、テストケースの定義に単純な宣言構文を使用しているため、私が見た中で最も独創的なツールです。いつものように、あらゆるレベルの抽象化は、ある程度の柔軟性を犠牲にしてある程度の利便性を提供します。とはいえ、シンプルさは魅力的ですが、主にセットアップ/ tearDownアクションを定義する方法がないために、ツールが私が持っているケースに限定しすぎていることがわかりました(たとえば、テスト前に入力ファイルを操作し、テスト後に状態ファイルを削除します)など)。
私は、assert.shが出力または終了ステータスのどちらかしかアサートできないのに対し、両方が必要だと最初は少し混乱していました。切り上げを使用していくつかのテストケースを記述するのに十分な長さ。しかし、すぐにまとめを見つけましたset -e
モードは、stdoutに加えて結果を通信する手段として、ゼロ以外の終了ステータスが予期される場合があり、このモードではテストケースが失敗します。 サンプルの1つ は解を示します。
status=$(set +e ; rup roundup-5 >/dev/null ; echo $?)
しかし、ゼロ以外の終了ステータスと出力の両方が必要な場合はどうなりますか?もちろん、set +e
呼び出し前およびset -e
の後またはset +e
テストケース全体。しかし、それはまとめの原則に反します 「すべてはアサーションです」 。だから、私はこのツールに対して働き始めているように感じました。
それまでに、このような複合式でtest
を渡すことができるので、終了ステータスまたは出力のいずれかのみをアサートできるassert.shの「欠点」が実際には問題ではないことに気付きました。
output=$($tested_script_with_args)
status=$?
expected_output="the expectation"
assert_raises "test \"$output\" = \"$expected_output\" -a $status -eq 2"
私のニーズは本当に基本的なものだったので(一連のテストを実行し、すべてがうまくいったか失敗したかを表示します)、私はassert.shのシンプルさが気に入ったので、それを選択しました。
Jenkinsのxml結果を生成でき、実際には何も見つからない、Shellの簡単な単体テストフレームワークを探した後、私はそれを書きました。
Sourceforgeにあります-プロジェクトの名前はjshuです。
assert.sh libを試してみてください。非常に便利で使いやすいです
local expected actual
expected="Hello"
actual="World!"
assert_eq "$expected" "$actual" "not equivalent!"
# => x Hello == World :: not equivalent!
最近、shellspecと呼ばれる新しいテストフレームワークをリリースしました。
shellspecはBDDスタイルのテストフレームワークです。 bash、dash、ksh、busyboxなどを含むPOSIX互換のシェルスクリプトで動作します。
もちろん、終了ステータスは仕様の実行結果を反映しており、TAP準拠のフォーマッターを備えています。
Specfileは自然言語に近く、読みやすく、またシェルスクリプト互換の構文です。
#shellcheck Shell=sh
Describe 'sample'
Describe 'calc()'
calc() { echo "$(($*))"; }
It 'calculates the formula'
When call calc 1 + 2
The output should equal 3
End
End
End