併せて読みたい: ShellScript - そのシェルスクリプトのあるディレクトリに移動する - Qiita [キータ]
とあるプロジェクトが,
APP_ROOT
|- a.sh
`- test/
|- run.sh
|- a.txt
|- a-expected.txt
`- shunit2
という構成になっているとします.a.sh
を実行すると test/a.txt
の内容が変わって test/a-expected.txt
と一致することをテストしたいとします.このとき test/run.sh
は以下のようになりました.
#! /bin/sh
TEST_DIR=`dirname $0`
setUp()
{
PREV_DIR=$PWD
cd $TEST_DIR
cp a.txt a.txt.bk
}
tearDown()
{
if [ -f a.txt.bk ]; then
mv a.txt.bk a.txt
fi
cd $PREV_DIR
}
testA()
{
../a.sh
diff a.txt a-expected.txt
assertEquals 0 $?
}
# load shunit2
. $TEST_DIR/shunit2
サンプルなんかでは最後の行は . ./shunit2
と書かれているんですが,test/run.sh
をどこから実行してもいいようにしたかった (思えばこれがそもそもどうでもいいかもしれませんが…) ので,まずそれを . $TEST_DIR/shunit2
とします.TEST_DIR
の取得方法は先述のエントリの通りですね.
ここからがアレでした.
そもそも cd $TEST_DIR
して . ./shunit2
にすればええやん?と思ってたのですが,なんと shUnit2 さんは SHUNIT_PARENT
なる変数を用いて shunit2
のあるディレクトリを監視し,そこから grep でテストスクリプト (今回なら run.sh
) の中身を見てよしなにしてくれる仕様になってます.
そうすると何が起こるかって,今自分で cd $TEST_DIR
して test
の中にいるのに,そこから test/run.sh
というパスになるファイルを扱おうとしてくれるわけです.はい,当然見つからないですね../run.sh
なら良かったんですが.
※うちの shunit2
は自分で make build
して作ったものですからもしかしたら微妙な差異はあるのかもです.
※うちの環境での話をするなら,shunit2
内での件の grep は 934 行目で,SHUNIT_PARENT
の設定は 36 行目からの処理で行われていました.
ということは,cd $TEST_DIR
するのはテストの実行時だけにしなければなりません.
なので上記のように setUp
内で cd $TEST_DIR
を行う必要があるわけです.
で,次に cd $TEST_DIR
しっぱなしでいるとテストが追加されたときにまずいことになります.最初の 1 つのテストはいいんですが,次のテストで再び cd $TEST_DIR
しようとしても今既にそこに居るので「そんなファイル or ディレクトリ無いです」って言われます.エラーにこそなりませんが出力が汚くなります.警告の表示を無視するとかプログラマとしてやりたくないですよね.なので一々 setUp
時点での $PWD
を記録しておいて,tearDown
内で戻るわけです.
ん?じゃあ oneTimeSetUp
使ってそこで cd $TEST_DIR
すればいいじゃんって?
ダメなんです… 先述の grep の処理はなんと oneTimeSetUp
の「後」に行われるんです… なんてこった.
そういうわけで,こういう形に落ち着いたわけです.
うーん,テストの書き方が難しいというのはテストという目的としてどうなのか… 検算のやり方が本来の答えを導き出す手法未満の難易度じゃないとテストって意味が無い気がするんですよね…