概要
最近開発したシェルスクリプトのテストツールとしてshellspecを活用している。
シェルスクリプトは、
- 処理が比較的高速
単体で並列化も可能 - 簡単
コマンド並べるだけ - 追加パッケージ不要
というメリットがあり、特にインフラ界隈ではしょっちゅう使用するものの、モジュール化しにくいので見通しが悪く、バグを作り込みやすい。
そして記述済みの部分に場当たり的に修正や機能追加を行ってブラックボックス化してしまうこともしばしば。
テストツールを使って、細かい処理毎に関数を設けてテストを繰り返すことで、品質の向上が期待できる。
また、リグレッションテストを容易にすることでリファクタリングのハードルを下げ、ブラックボックス化を抑止できる。
いざ使ってみたところ、テストツールに対する私の理解があまりなかったこともあって、テストの作成にかなり時間がかかってしまった。
ここでは、テストで確認したい内容の実現方法について自分用にまとめる。
When句で実施した処理の結果をコマンドで確認する。
When call/runで関数/コマンドを実行したあと、別のコマンドで結果を確認する場合。例えば、サブプロセスを立ち上げるシェルスクリプトを実行して、プロセスが存在しているか調べる。
追記:作者の方からコメントいただいたので記載見直ししました。
Describe "コマンド結果確認"
check_subprocess(){
[[ $(pgrep -f subprocess.sh | wc -l) -gt 0 ]] && echo OK
}
It "サブプロセス起動"
When run ./start_subprocess.sh
The result of "check_subprocess()" should eq OK
End
End
関数以外の処理をスキップさせる
Include句でシェルスクリプトを読み込むと、関数内に記述していない処理は実行されてしまう。
# !/bin/bash
function hoge(){
echo "hoge"
}
hoge
echo "fuga" >&2
Describe "test"
Describe "test"
Include ./test.sh
It "hoge()"
When call hoge
The output should eq "hoge"
End
End
End
以下の実行結果を見ると、テストそのものはOKとなっており問題はないのだが、"fuga"が出力されてしまっていることがわかる。
Running: /bin/bash [bash 5.0.3(1)-release]
fuga
Unexpected output to the stderr at line 2-4 in 'spec/hello_spec.sh'
.
Finished in 0.26 seconds (user 0.26 seconds, sys 0.05 seconds)
1 example, 0 failures
An unexpected error occurred or output to the stderr. [0] [0] [102]
Fatal error occurred, terminated with exit status 102.
${__SOURCED__:+return}を関数外処理の始まりに記載する。
shellspec実行時はここで処理が打ち切られるので関数外処理が実行されずにすむ。
# !/bin/bash
function hoge(){
echo "hoge"
}
# shellspecテスト時は以下の処理は実行しない。
${__SOURCED__:+return}
hoge
echo "fuga" >&2
動作するシェルを指定する。
.shellspecファイルに以下を追記する。
--shell bash
パターンをまとめて列挙する
Describe 'DHCPCDは起動していて、wpa_supplicantは停止していることを確認する。'
Parameters
"#1" "dhcpcd" 0
"#2" "wpa_supplicant" 3
End
Example "example $1"
When run sudo systemctl status $2
The status should eq $3
End
End
標準出力が指定した行を含むかチェックする。
Describe "IP addr check"
grep_eth0(){
# $1に標準出力、$2にエラー出力、$3に返り値が入る。
echo "$1" | grep "eth0" | awk '{if($1=="inet")print $2}'
}
It "eth0に規定のIPアドレスが設定されているか確認する。"
When run ip a
The result of "grep_eth0()" should eq "192.168.3.142/24"
End
End
以下、おいおい追記していく