先日、「shUnit2を使おう」という以下のLTをしてきました。
http://www.slideshare.net/cottondesu/shell-02-shunit2
shUnit2を使ってシェルのテストするまでLTをしましたが、
本当はこのLTには続きあります。
動作確認する時間、スライドを作成する時間がなかったので実現
できなかったのですが、GithubとCircleCIが連携し
CircleCIでshUnit2のシェルテストを行うことです。
目的
Githubにpushし、CircleCIでshUnit2のテストを実施する
環境
- Mac
- shUnit2
- Github
- CircleCI
shUnit2のインストール
以下のURLを開く
https://code.google.com/archive/p/shunit2/
Downloadsからshunit2-2.1.6.tgzをダウンロードします。
ターミナルから以下のコマンドを実行しフォルダを作成、
ダウンロードしたtgzファイルを展開します。
$ mkdir ~/.shunit2
$ tar zxf shunit2-2.1.6.tgz -C ~/.shunit2
以下のように環境変数(bash)を設定します。
$ echo 'export SHUNIT2_HOME=$HOME/.shunit2/shunit2-2.1.6' >> ~/.bash_profile
$ . ~/.bash_profile
sampleのテストコードは.shUnit2のexamplesディレクトリに
格納されているのでそちらでテストコードの書き方を確認ください。
bashスクリプトのプロジェクト作成
テスト対象のシェルスクリプトとテストコードが必要になります。
ここではテストコードの書き方は省きます。
私の場合、シェルスクリプトがGithubにおいてあるのでこちらを使います。
シェルスクリプトのテスト対象ファンクション部分
# モード選択
select_mode() {
if [[ "$1" =~ ^[1-2] ]]; then
return 0
else
return 1
fi
}
# meetup番号入力
input_meetupnum(){
if [[ "$1" =~ ^[0-9]+$ ]]; then
return 0
else
return 1
fi
}
# フォルダ存在チェック
is_filefolder(){
if [ ! -e "$1" ]; then
return 1
else
return 0
fi
}
テストコード
# !/bin/bash
# shellcheck source=./../../shell_create_kzrb_meetup/create_kzrb_meetup.sh
. "$(dirname "${BASH_SOURCE:-$0}")/../../shell_create_kzrb_meetup/create_kzrb_meetup.sh"
testSelectMode1(){
select_mode 1
assertEquals 0 $?
}
testSelectMode2(){
select_mode 2
assertEquals 0 $?
}
testSelectModeNg(){
select_mode 3
assertEquals 1 $?
}
testInputMeetupNum1(){
input_meetupnum 1
assertEquals 0 $?
}
testInputMeetupNum40(){
input_meetupnum 40
assertEquals 0 $?
}
testInputMeetupNumNg(){
input_meetupnum a
assertEquals 1 $?
}
testIsFile(){
is_filefolder "$0"
assertEquals 0 $?
}
testIsFileNg(){
is_filefolder "index.md"
assertEquals 1 $?
}
testIsFolder(){
is_filefolder ../test
assertEquals 0 $?
}
testIsFolderNg(){
is_filefolder test
assertEquals 1 $?
}
# shellcheck source=$HOME/.shunit2/shunit2-2.1.6/src/shunit2
. "$SHUNIT2_HOME/src/shunit2"
因みに上記のfunction_test.shをshellcheckするとnoteが2件でます。
shellcheck -xで実行すると57行目の1件のみnoteで出ます。
$HOMEを実際のパスに置き換えるとnoteが消えます。
Githubにpush
私の場合は既にGithubにシェルスクリプトが格納されているので
テストコードを追加してpushします。
$ git add test/function_test.sh
$ git commit -m "テストコードを追加"
$ git push origin master
CircleCIの設定
CircleCI
https://circleci.com/
- CircleCIにgithubのアカウントでログインする
- 左側のメニューにある[ADD PROJECT]を選択する
- pushしたリポジトリの「BuildProject」を選択する。
3.を行うとすぐさまbuildが実施されますが、
「NO TESTS」となります。testが実施されていませんからね。
testが実施されるように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/function_test.sh
test:の所でpush時に実行されるテストコードを指定します。
私の場合は、test/function_test.sh となります。
作成したcircle.ymlをpushする
$ git add circle.yml
$ git commit -m "add circle yml"
$ git push origin master
pushすると、CircleCI上でshUnit2によるテストが実行されます。
ここで成功したよドヤって言いたかったんですが、私のテストコードが
悪かったせいでFAILEDになってしまいました。
ローカル環境でのテスト実施はtestフォルダに移動して
テストコードを実施していました。
$ sh function_test.sh
上の階層(shell_create_kzrb_meetup)に移動して
テストコードを実施すると、CircleCIで実施した時と同じ
FAILEDが再現できました。
$ sh test/function_test.sh
ファイル存在やフォルダ存在などパスを確認するテストコードを
作成するときは実行するカレントフォルダを意識する必要があります。
我が身を持って大変勉強になりました。
以下のようにテストコードを直します。
testIsFolder(){
is_filefolder ../test
assertEquals 0 $?
}
testIsFolderNg(){
is_filefolder test
assertEquals 1 $?
}
testIsFolder(){
is_filefolder test
assertEquals 0 $?
}
testIsFolderNg(){
is_filefolder exsample
assertEquals 1 $?
}
として直してcommit、pushします。
$ git add test/function_test.sh
$ git commit -m "テストコードの修正"
$ git push origin master
無事、単体テストが成功しました。
本当は成功例のみを載せたほうが良いのかもしませんが
失敗例含めて少しでも役に立てば有難いです。