shUnit2とCircleCIでシェルスクリプトの単体テストをしてみた
シェルスクリプトでも単体テストを書いてCIした方が精神衛生上好ましいなと思い、
調べてみるとshUnit2という単体テストフレームワークがあったので、
これを使って単体テストとCIを実施してみました。
shUnit2
https://code.google.com/archive/p/shunit2/
CircleCI
https://circleci.com/
全体の流れは、以下の通りです。
- shUnit2のセットアップ
- シェルスクリプトのプロジェクト作成
- CircleCIの設定
この手順はMacOSXで実施しましたが、
bashが動く環境であれば同様の手順で実行できると思われます。
このエントリで作成したgithubリポジトリ:
https://github.com/takemikami/shunit-sample
shUnit2のセットアップ
セットアップ
まずは、shUnit2をセットアップします。
ダウンロードし、そのパスを環境変数「SHUNIT2_HOME」に設定するだけです。
以下のように、ダウンロード及び展開します。
$ cd ~/
$ wget https://storage.googleapis.com/google-code-archive-downloads/v2/code.google.com/shunit2/shunit2-2.1.6.tgz
$ mkdir ~/.shunit2
$ tar zxf shunit2-2.1.6.tgz -C ~/.shunit2
$ rm shunit2-2.1.6.tgz
以下のように、環境変数を設定します。
$ echo 'export SHUNIT2_HOME=$HOME/.shunit2/shunit2-2.1.6' >> ~/.bash_profile
$ . ~/.bash_profile
サンプルの実行
以下のように、
shUnit2のexamplesディレクトリから、作業ディレクトリにサンプルをコピーします。
$ cp $SHUNIT2_HOME/examples/equality_test.sh ./equality_test.sh
セットアップの手続きで設定した環境変数を使って、
shUnit2を実行するように、equality_test.sh
の最後の一行を変更します。
#! /bin/sh
# file: examples/equality_test.sh
testEquality()
{
assertEquals 1 1
}
# load shunit2
. $SHUNIT2_HOME/src/shunit2
以下のようにテストを実行します。
$ bash equality_test.sh
testEquality
Ran 1 test.
OK
テストの書き方は、次のドキュメントを参照します(基本的にJUnitと同じですが)。
shUnit2 2.1.x ドキュメント
https://sites.google.com/site/paclearner/shunit2-documentation
bashスクリプトのプロジェクト作成
gitリポジトリの作成
$ mkdir ~/shunit-sample && cd $_
$ git init
$ mkdir sh
$ mkdir -p test/sh
シェルスクリプトとテストコードの作成
以下のとおり、テスト対象のシェルスクリプトを作ります。
sh/sample.sh
#!/bin/bash
job1() {
echo "job1 exec"
return 1
}
job2() {
echo "job2 exec"
return 2
}
if [ $0 = $BASH_SOURCE ]; then
job1
job2
fi
# if [ $0 = $BASH_SOURCE ];
の箇所で、
# 直接シェルを実行した時のみメイン処理を実行するようにしています
#(インクルード時には実行しない)
以下のとおり、テストコードを作ります。
test/sh/test_sample.sh
. $(dirname $BASH_SOURCE)/../../sh/sample.sh
testJob1()
{
job1
assertEquals 1 $?
}
testJob2()
{
job2
assertEquals 2 $?
}
# load shunit2
. $SHUNIT2_HOME/src/shunit2
以下のように、テストを実行します。
$ bash test/sh/test_sample.sh
testJob1
job1 exec
testJob2
job2 exec
Ran 2 tests.
OK
ちなみに、単純にサンプルのシェルスクリプトを実行すると以下のようになります。
$ bash sh/sample.sh
job1 exec
job2 exec
githubにpush
コードをコミットし、githubにpushします。
$ git add .
$ git commit -a -m "initial commit"
$ git remote add origin git@github.com:※githubのリポジトリ※
$ git push -u origin master
CircleCIの設定
CircleCIにProjectを追加
CircleCI
https://circleci.com/
CircleCIにgithubのアカウントでログインし、
「ADD PROJECT」メニューから
先程pushしたリポジトリの「BuildProject」を追加します。
この状態だと「NO TESTS」と怒られます。
circle.ymlの追加
以下の通りcircle.ymlを作ります。
circle.yml
machine:
environment:
SHUNIT2_HOME: ${HOME}/.shunit2/shunit2-2.1.6
dependencies:
pre:
- "[ ! -e ~/.shunit2 ] && wget https://storage.googleapis.com/google-code-archive-downloads/v2/code.google.com/shunit2/shunit2-2.1.6.tgz && mkdir ~/.shunit2 && tar zxf shunit2-2.1.6.tgz -C ~/.shunit2 || echo 'ready'"
cache_directories:
- "~/.shunit2"
test:
override:
- bash test/sh/test_sample.sh
circle.ymlを追加し、githubにpushします。
$ git add circle.yml
$ git commit -a -m "add circle yaml"
$ git push
pushすると、CircleCI上でテストが実行され、
以下のように、単体テストが成功しているはずです。
これで精神衛生上好ましい感じに出来そうですね。