shell scripts通常做為系統排程自動工作或輔助系統管理的主要工具
本身不會包含太多邏輯,取而代之的是大量的環境變數設定、程式執行和狀態判斷
程式碼默默增長到數百行規模後也開始產生自動化測試的需求
比起本身assert的設計,更重要的是mock or stub會大量被使用
而這篇文章便是基於這個角度撰寫的工具簡介和使用後的心得
雖然有4000start,但有一段時間都沒人在維護了
bats-core 最近遷移的新repo
Install
我從github下載安裝
https://github.com/sstephenson/bats#installing-bats-from-source
安裝並不一定要放在/usr/local,只要管理方便就行
$ git clone https://github.com/sstephenson/bats.git
$ cd bats
$ ./install.sh /usr/local
移動到自己的project中,執行內建測試案例,確認環境設定正常
mv test/..
rm -rf bats
cd test
./bats.bats
常用lib
bats本身的功能不多,但有幾個相關lib可以輔助
https://github.com/ztombol/bats-support https://github.com/ztombol/bats-assert https://github.com/jasonkarns/bats-mock
我使用的方式是用submodule拉到自己的專案資料夾下使用
mkdir lib
git submodule add https://github.com/ztombol/bats-support.git lib/support
git submodule add https://github.com/ztombol/bats-assert.git lib/assert
git submodule add https://github.com/jasonkarns/bats-mock.git lib/mock
Usage
網路上有個可供參考的帶測試專案
https://github.com/pimterry/notes/blob/master/test/test-ls.bats
他使用到的比較多為執行自己程式後確認輸出
Mock
shell script有很多需要呼叫外部程式的部份
以我的需求來說會需要測試當ps後,偵測還在執行的程式,並發送指令
那就需要偽造ps的輸出,以及假設shell script會呼叫 pkill -SIGUSR1 xxx
搭配mocking可以作這部份的處理
但mocking只能偽造執行程式,無法偽造shell script內的函式
優點:
偽造輸出、假設args和執行次數
缺點:
測試失敗時的訊息不夠多,有可能是args不匹配、呼叫次數不對(只顯示unstub failed)
測試失敗的遺留訊息可能影響到下次執行,造成奇怪的結果 (workaround: 清除tmp底下所有殘留檔案)
以下為example code
#!/usr/bin/env bats
load lib/support/load
load lib/assert/load
load lib/mock/stub
@test "ami root? (mocking result)" {
stub whoami \
"echo root"
run whoami
assert_success
assert_output "root"
unstub whoami
}
@test "run ps once? (expect ran)" {
stub ps \
"true"
run ps
unstub ps
}
@test "run cat file? (expect args)" {
stub cat \
"file : echo file is here"
run cat file
unstub cat
}
mock常見的錯誤訊息
mock失敗,執行到真實的程式 => 檢查binstub是否有執行權限
unstub failed => 清除TMP目錄殘留檔案