Javaコードの他にいくつかのBashスクリプトが実行されているシステムがあります。壊れてしまう可能性のあるすべてのものをテストしようとしているので、それらのBashスクリプトが壊れている可能性があるので、それらをテストしたいと思います。
問題は、Bashスクリプトをテストするのが難しいことです。
Bashスクリプトをテストする方法またはベストプラクティスはありますか?または、Bashスクリプトの使用をやめて、テスト可能な代替ソリューションを探す必要がありますか?
Javaコードの他にいくつかのBashスクリプトが実行されているシステムがあります。壊れてしまう可能性のあるすべてのものをテストしようとしているので、それらのBashスクリプトが壊れている可能性があるので、それらをテストしたいと思います。
問題は、Bashスクリプトをテストするのが難しいことです。
Bashスクリプトをテストする方法またはベストプラクティスはありますか?または、Bashスクリプトの使用をやめて、テスト可能な代替ソリューションを探す必要がありますか?
実際には、Bourneベースのシェルスクリプト用のxUnitベースのユニットテストフレームワークであるshunit2があります。自分で使ったことはありませんが、チェックする価値があるかもしれません。
同様の質問が以前に尋ねられました:
TAP準拠のBashテスト:Bash自動テストシステム
Test Anything ProtocolであるTAPは、テストハーネス内のテストモジュール間の単純なテキストベースのインターフェイスです。TAPは、Perlのテストハーネスの一部として誕生しましたが、現在はC、C ++、Python、PHP、Perl、Java、JavaScriptなどで実装されています。
ディスカッショングループから次の回答を得ました。
外部ファイルからプロシージャ(関数、名前が何であれ)をインポート(インクルードなど)することができます。これがテストスクリプトを作成するための鍵です。スクリプトを独立したプロシージャに分割し、実行中のスクリプトとテストスクリプトの両方にインポートして、実行中のスクリプトを可能な限りシンプルにします。
この方法は、スクリプトの依存性注入のようなものであり、合理的に聞こえます。Bashスクリプトを避け、よりテスト可能でわかりにくい言語を使用することをお勧めします。
Nikita Sobolevは、いくつかの異なるBashテストフレームワークを比較する優れたブログ投稿を作成しました。Bashアプリケーションのテスト
せっかちな人のために:ニキータの結論はバットを使用することでしたが、元のバットプロジェクトは2013年以来積極的に維持されていないため、ニキータは私が今後使用するものであると思われるバットコアプロジェクトを見逃したようです。
Epoxyは、主に他のソフトウェアをテストするために設計したBashテストフレームワークですが、それ自体やCartonを含むBashモジュールのテストにも使用しています。
主な利点は、コーディングオーバーヘッドが比較的低く、アサーションのネストが無制限で、検証するアサーションを柔軟に選択できることです。
私はそれをBeakerLib(Red Hatの一部で使用されているフレームワーク)と比較してプレゼンテーションを行いました。
誰もOSHTについて話していないなんて信じられません!TAPとJUnitの両方 と互換性があり、純粋なシェル(つまり、他の言語は含まれていません)であり、スタンドアロンでも機能し、シンプルで直接的なものです。
テストは次のようになります(プロジェクトページから取得したスニペット):
#!/bin/bash
. osht.sh
# Optionally, indicate number of tests to safeguard against abnormal exits
PLAN 13
# Comparing stuff
IS $(whoami) != root
var="foobar"
IS "$var" =~ foo
ISNT "$var" == foo
# test(1)-based tests
OK -f /etc/passwd
NOK -w /etc/passwd
# Running stuff
# Check exit code
RUNS true
NRUNS false
# Check stdio/stdout/stderr
RUNS echo -e 'foo\nbar\nbaz'
GREP bar
OGREP bar
NEGREP . # verify empty
# diff output
DIFF <<EOF
foo
bar
baz
EOF
# TODO and SKIP
TODO RUNS false
SKIP test $(uname -s) == Darwin
簡単な実行:
$ bash test.sh
1..13
ok 1 - IS $(whoami) != root
ok 2 - IS "$var" =~ foo
ok 3 - ISNT "$var" == foo
ok 4 - OK -f /etc/passwd
ok 5 - NOK -w /etc/passwd
ok 6 - RUNS true
ok 7 - NRUNS false
ok 8 - RUNS echo -e 'foo\nbar\nbaz'
ok 9 - GREP bar
ok 10 - OGREP bar
ok 11 - NEGREP . # verify empty
ok 12 - DIFF <<EOF
not ok 13 - TODO RUNS false # TODO Test Know to fail
最後のテストは「問題あり」と表示されますが、終了コードは。であるため0ですTODO
。詳細を設定することもできます。
$ OSHT_VERBOSE=1 bash test.sh # Or -v
1..13
# dcsobral \!= root
ok 1 - IS $(whoami) != root
# foobar =\~ foo
ok 2 - IS "$var" =~ foo
# \! foobar == foo
ok 3 - ISNT "$var" == foo
# test -f /etc/passwd
ok 4 - OK -f /etc/passwd
# test \! -w /etc/passwd
ok 5 - NOK -w /etc/passwd
# RUNNING: true
# STATUS: 0
# STDIO <<EOM
# EOM
ok 6 - RUNS true
# RUNNING: false
# STATUS: 1
# STDIO <<EOM
# EOM
ok 7 - NRUNS false
# RUNNING: echo -e foo\\nbar\\nbaz
# STATUS: 0
# STDIO <<EOM
# foo
# bar
# baz
# EOM
ok 8 - RUNS echo -e 'foo\nbar\nbaz'
# grep -q bar
ok 9 - GREP bar
# grep -q bar
ok 10 - OGREP bar
# \! grep -q .
ok 11 - NEGREP . # verify empty
ok 12 - DIFF <<EOF
# RUNNING: false
# STATUS: 1
# STDIO <<EOM
# EOM
not ok 13 - TODO RUNS false # TODO Test Know to fail
.t
名前を変更して拡張子を使用し、t
サブディレクトリに配置すると、 prove(1)
(Perlの一部)を使用して実行できます。
$ prove
t/test.t .. ok
All tests successful.
Files=1, Tests=13, 0 wallclock secs ( 0.03 usr 0.01 sys + 0.11 cusr 0.16 csys = 0.31 CPU)
Result: PASS
JUnit出力を生成するために設定OSHT_JUNIT
またはパスします。-j
JUnitは。と組み合わせることもできますprove(1)
。
私はこのライブラリを使用して、ファイルをソーシングしてからIS
/OK
とそのネガティブを使用してアサーションを実行することで関数をテストし、/を使用してスクリプトをRUN
実行しましたNRUN
。私にとって、このフレームワークは最小のオーバーヘッドで最大の利益を提供します。
Bashスクリプトをテストするのが「難しい」と言うのはなぜですか?
次のようなテストラッパーの何が問題になっていますか?
#!/bin/bash
set -e
errors=0
results=$($script_under_test $args<<ENDTSTDATA
# inputs
# go
# here
#
ENDTSTDATA
)
[ "$?" -ne 0 ] || {
echo "Test returned error code $?" 2>&1
let errors+=1
}
echo "$results" | grep -q $expected1 || {
echo "Test Failed. Expected $expected1"
let errors+=1
}
# And so on, et cetera, ad infinitum, ad nauseum
[ "$errors" -gt 0 ] && {
echo "There were $errors errors found"
exit 1
}
assert.shを試してみてください:
source "./assert.sh"
local expected actual
expected="Hello"
actual="World!"
assert_eq "$expected" "$actual" "not equivalent!"
# => x Hello == World :: not equivalent!
私はshell2junitがとても好きです。これは、BashスクリプトテストからJUnitのような出力を生成するユーティリティです。生成されたレポートは、 JenkinsやBamboo用のJUnitプラグインなどの継続的インテグレーションシステムで読み取ることができるため、これは便利です。
shell2junitはshunit2のような包括的なBashスクリプトフレームワークを提供していませんが、テスト結果の優れたレポートを作成できます。
bashtestを試してください。スクリプトをテストする簡単な方法です。たとえば、do-some-work.sh
いくつかの構成ファイルを変更するものがあります。たとえば、PASSWORD = 'XXXXX'
構成ファイルに新しい行、を追加します/etc/my.cfg
。
Bashコマンドを1行ずつ記述してから、出力を確認します。
インストール:
pip3 install bashtest
テストの作成は、bashコマンドを作成するだけです。
ファイルtest-do-some-work.bashtest
:
# Run the script
$ ./do-some-work.sh > /dev/null
# Testing that the line "PASSWORD = 'XXXXX'" is in the file /etc/my.cfg
$ grep -Fxq "PASSWORD = 'XXXXX'" /etc/my.cfg && echo "YES"
YES
テストを実行します。
bashtest *.bashtest
たぶん、これは使用することができます、または貢献することができます:
https://thorsteinssonh.github.io/bash_test_tools/
これは、 CIに適し、シェル環境が必要なユーザーに適していると私が想像するTAPプロトコルで結果を書き込むことを目的としています。シェル環境で実行されるものもあると思います。そのため、シェル環境でテストする必要があると主張する人もいるかもしれません。
ここに示す多くのソリューションを試しましたが、それらのほとんどがかさばりすぎて使いにくいことがわかったので、独自の小さなテストフレームワークを構築しました:https ://github.com/meonlol/t-bash
これは、 JUnitスタイルの基本セットを使用して、直接実行できるリポジトリ内の1つのファイルです。
私はこれをいくつかの内部プロジェクトで専門的に使用し、Bashスクリプトを非常に安定して回帰耐性を持たせることができました。
bash_unitを確認することをお勧めします。
Outthenticを見てください。シンプルで、多くの言語(Perl、Python、Ruby、Bashを選択)およびクロスプラットフォーム(LinuxおよびWindows)フレームワークで拡張可能であり、任意のコマンドラインアプリケーションをテストできます。
テストを作成しますmytest.sh
。特定の入力を使用してスクリプトを呼び出します。
テキストファイルを作成しますexpected/mytest.stdout
。これには、テストで期待される出力が含まれています。
それらをバージョン管理(存在する場合)にコミットします。
テストを実行し、出力を別のファイルにリダイレクトします。
mytest.sh > actual/mytest.stdout
次に、テキスト差分ツールを使用して、結果がどこから逸脱しているかを確認します。私はあなたがただできると思います
diff expected/mytest.stdout actual/mytest.stdout