BATS 使用方式 & 心得

shell scripts通常做為系統排程自動工作或輔助系統管理的主要工具

本身不會包含太多邏輯,取而代之的是大量的環境變數設定、程式執行和狀態判斷

程式碼默默增長到數百行規模後也開始產生自動化測試的需求

比起本身assert的設計,更重要的是mock or stub會大量被使用

而這篇文章便是基於這個角度撰寫的工具簡介和使用後的心得


Bash Automated Testing System

雖然有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目錄殘留檔案