Java code。を壊す可能性のあるすべてをテストしようとしているので、それらのbashスクリプトが壊れる可能性があるため、テストする必要があります。
問題は、bashスクリプトをテストするのが難しいことです。
Bashスクリプトをテストする方法またはベストプラクティスはありますか?または、bashスクリプトの使用をやめて、テスト可能な代替ソリューションを探す必要がありますか?
ディスカッショングループから次の回答を得ました。
外部ファイルからプロシージャ(関数、名前が何であれ)をインポート(インクルード、何でも)することができます。それがテストスクリプトを書くための鍵です。スクリプトを独立したプロシージャに分割し、実行中のスクリプトとテストスクリプトの両方にインポートし、実行中のスクリプトを可能な限りシンプルにします。
この方法は、スクリプトの依存性注入に似ており、妥当なように思えます。 bashスクリプトを避け、よりテストしやすく曖昧さの少ない言語を使用することをお勧めします。
実際には、 shunit2 、Bourneベースのシェルスクリプト用のxUnitベースのユニットテストフレームワークがあります。私は自分で使用していませんが、チェックアウトする価値があるかもしれません。
同様の質問が以前に聞かれました:
[〜#〜] tap [〜#〜] -準拠Bashテスト:Bash自動テストシステム
TAP(Test Anything Protocol)は、テストハーネス内のテストモジュール間のシンプルなテキストベースのインターフェイスです。 TAPはPerlのテストハーネスの一部として始まりましたが、現在はC、C++、Python、PHP、Perl、Java、JavaScriptなどで実装されています。
Nikita Sobolevは、いくつかの異なるbashテストフレームワークを比較した優れたブログ投稿を書いています。 Testing Bash applications
せっかちな人のために:ニキータの結論は Bats を使用することでしたが、ニキータは Bats-core プロジェクトを逃したようです。 Batsプロジェクトは2013年以降積極的にメンテナンスされていません。
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
}
[〜#〜] osht [〜#〜] !について誰も話していなかったとは信じられません。 bothの両方と互換性があり、純粋なシェル(つまり、他の言語が関与していない)であり、スタンドアロンでも動作し、シンプルで直接的なものです。
テストは次のようになります(プロジェクトページから抜粋したスニペット):
_#!/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
_
最後のテストは「not ok」と表示されますが、TODO
であるため終了コードは0です。詳細を設定することもできます:
_$ 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
_
_OSHT_JUNIT
_を設定するか、_-j
_を渡してJUnit出力を生成します。 JUnitはprove(1)
と組み合わせることもできます。
このライブラリを使用して、ファイルをソースし、IS
/OK
とそのネガでアサーションを実行して関数をテストし、RUN
/NRUN
を使用してスクリプトを実行しました。私にとって、このフレームワークは最小のオーバーヘッドで最大の利益をもたらします。
assert.sh を試してください
source "./assert.sh"
local expected actual
expected="Hello"
actual="World!"
assert_eq "$expected" "$actual" "not equivalent!"
# => x Hello == World :: not equivalent!
それが役に立てば幸い!
bashtest を試してください。スクリプトをテストする簡単な方法です。たとえば、いくつかの設定ファイルを変更するdo-some-work.sh
があります。たとえば、構成ファイルPASSWORD = 'XXXXX'
に新しい行/etc/my.cfg
を追加します。
行ごとにbashコマンドを記述してから、出力を確認します。
インストール:
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
Shell2junit は、BashスクリプトテストからJUnitのような出力を生成するユーティリティです。生成されたレポートは、JenkinsやBambooのJUnitプラグインなどの継続的な統合システムで読み取れるため、便利です。
Shell2junitは shunit2 のような包括的なBashスクリプトフレームワークを提供していませんが、テスト結果のNiceレポートを作成できます。
たぶんこれを使用するか、貢献することができます
https://thorsteinssonh.github.io/bash_test_tools/
CIに適していると思うシェルプロトコルで結果を書き込むことを意図しており、シェル環境が必要なものに適しています。シェル環境で実行されるものがあると思うので、シェル環境でテストする必要があると主張するかもしれません。
shellspec を作成したのは、使いやすく便利なツールが欲しかったからです。
それは純粋なPOSIXシェルスクリプトによって書かれました。 shunit2以上の多くのシェルでテストしました。 bats/bats-coreよりも強力な機能を備えています。
たとえば、ネストされたブロック、モック/スタブ、スキップ/ペンディング、パラメーター化されたテスト、アサーション行番号、行番号による実行、並列実行、ランダム実行、TAP/JUnitフォーマッター、カバレッジとCI統合、プロファイラーなどをサポート。
プロジェクトページのデモを参照してください。
ここで紹介した多くのソリューションを試してみましたが、それらのほとんどがかさばって使いにくいことがわかったため、独自の小さなテストフレームワークを構築しました: https://github.com/meonlol/t-bash
JUnitスタイルのアサートの基本セットを使用して、単純に直接実行できるリポジトリ内のファイルは1つだけです。
私はいくつかの内部プロジェクトでそれを専門的に使用し、bashスクリプトを非常に安定して回帰耐性を持たせることができました。
あなたはbash_unitを見てみたいかもしれません:
Outthentic をご覧ください。多くの言語(Perl、Python、Ruby、Bashを選択可能)およびクロスプラットフォーム(Linux、Windows)フレームワークで拡張可能で、コマンドラインアプリケーションをテストできます。