本文主要翻譯自shUnit2的README文檔休弃。
摘要
shUnit2是一個為bash shell腳本設(shè)計的xUnit類型的單元測試框架建椰,使用方式和JUnit撒穷、PyUnit......類似。如果你曾經(jīng)使用過類似的單元測試框架芳肌,上手將會容易很多碾局。
介紹
據(jù)說在log4sh(一種類似log4j基于shell的日志框架)做自動化測試時荆残,發(fā)現(xiàn)了各種兼容性問題,開發(fā)者最后決定開發(fā)出一款shell單元測試框架净当,于是有了shUnit2内斯。
之前的代碼倉庫在code.google.com/p/shunit2,google code關(guān)閉以后開發(fā)者將其鏡像到github像啼,最新的2.1版本最后一次修改提交是2017年1月俘闯。
支持的操作系統(tǒng)
- Cygwin
- FreeBSD (user supported)
- Linux (Gentoo, Ubuntu)
- Mac OS X
- Solaris 8, 9, 10 (inc. OpenSolaris)
支持的shell
- Bourne Shell (sh)
- BASH - GNU Bourne Again SHell (bash)
- DASH (dash)
- Korn Shell (ksh)
- pdksh - Public Domain Korn Shell (pdksh)
- zsh - Zsh (zsh) (since 2.1.2) please see the Zsh shell errata for more information
詳見代碼倉庫的 (doc/RELEASE_NOTES-X.X.X.txt)
新手入門
代碼倉庫的example包含了幾個參考范例,我們可以試著執(zhí)行一下忽冻,我是在CentOS 7環(huán)境下運(yùn)行的真朗。
#! /bin/sh
# file: examples/equality_test.sh
testEquality()
{
assertEquals 1 1
}
# load shunit2
. ../src/shunit2
執(zhí)行測試腳本,你將看到如下結(jié)果:
testEquality
Ran 1 test.
OK
以上范例沒有實際的被測試腳本僧诚,但是依然輸出的測試結(jié)果遮婶,所有內(nèi)容都是shUnit2
生成的。shUnit2
具體的測試步驟如下:
-
source shunit2
以后湖笨,單元測試將會開始執(zhí)行旗扑,一開始會掃描代碼中所有test
開頭的函數(shù),并將其加入單元測試列表慈省。 - 一個測試集合開始測試前會執(zhí)行
oneTimeSetUp
函數(shù)臀防,oneTimeSetUp
函數(shù)內(nèi)部可以編寫一些全局的初始條件,該函數(shù)在本次測試過程中僅執(zhí)行一次。對應(yīng)的是所有測試用例結(jié)束后袱衷,將會執(zhí)行oneTimeTearDown
函數(shù)捎废,在這里可以執(zhí)行一些狀態(tài)恢復(fù)的操作。 - 每個
test
用例函數(shù)被執(zhí)行前致燥,都會執(zhí)行setUp
函數(shù)登疗,測試結(jié)束會執(zhí)行tearDown
函數(shù),完整的單元測試用例執(zhí)行過程即:setUp() > test() > tearDown()
篡悟。 - 測試完成后谜叹,shUnit2將會輸出測試報告匾寝。
現(xiàn)在我們來看一個失敗的測試:
#! /bin/sh
# file: examples/party_test.sh
testEquality()
{
assertEquals 1 1
}
testPartyLikeItIs1999()
{
year=`date '+%Y'`
assertEquals "It's not 1999 :-(" \
'1999' "${year}"
}
# load shunit2
. ../src/shunit2
這個測試的結(jié)果一定是失敗的搬葬,因為年份錯了。
testEquality
testPartyLikeItIs1999
ASSERT:It's not 1999 :-( expected:<1999> but was:<2017>
Ran 2 tests.
FAILED (failures=1)
但是你會發(fā)現(xiàn)我們可以在測試框架提供的assertEquals函數(shù)中插入一些文本信息艳悔,另外無論是字符串還是數(shù)字的比較急凰,assertEquals函數(shù)都能很好的兼容。
函數(shù)說明
通常字符串我們需要使用單引號'或者雙引號"來引用猜年。
Asserts[斷言]
所有函數(shù)如下抡锈,從字面意思都很好理解:
assertEquals [message] expected actual
assertNotEquals [message] expected actual
assertSame [message] expected actual 等價于assertEquals
assertNotSame [message] unexpected actual 等價于assertNotEquals
assertNull [message] value
assertNotNull [message] value
assertTrue [message] condition
assertTrue "[ 34 -gt 23 ]"
assertTrue 'test failed' "[ -r /some/non-existant/file ]"
assertTrue 'test failed' '[ 1 -eq 1 -a 2 -eq 2 ]'
assertFalse [message] condition
Failures[失敗]
和斷言不同,F(xiàn)ailures函數(shù)不會對期望值和實際值進(jìn)行比較乔外,純粹就是報告測試失敗床三。通常用于復(fù)雜的邏輯測試,Assert的函數(shù)無法滿足測試需求杨幼,我們想用自己的代碼自行測試撇簿,而對該單元測試做一個簡單的標(biāo)記。
fail [message]
failNotEquals [message] unexpected actual
failSame [message] expected actual
failNotSame [message] expected actual
Setup/Teardown
oneTimeSetUp
oneTimeTearDown
setUp
tearDown
這4個函數(shù)在上面介紹過了差购。
Skipping
startSkipping 強(qiáng)制跳過剩余測試
endSkipping
isSkipping
Suites
標(biāo)準(zhǔn)的測試集合中四瘫,測試用例需要以test開頭,如果想測試一些非標(biāo)準(zhǔn)命名的函數(shù)欲逃,就需要用到以下函數(shù)找蜜。記住,通常我們不希望這樣使用稳析。
suite
suite_addTest name
高級用法
一些常用的宏
預(yù)定義
Constant | Value |
---|---|
SHUNIT_VERSION | The version of shUnit2 you are running. |
SHUNIT_TRUE | Standard shell true value (the integer value 0). |
SHUNIT_FALSE | Standard shell false value (the integer value 1). |
SHUNIT_ERROR | The integer value 2. |
SHUNIT_TMPDIR | Path to temporary directory that will be automatically cleaned up upon exit of shUnit2. |
用戶自定義
Constant | Value |
---|---|
SHUNIT_PARENT | The filename of the shell script containing the tests. This is needed specifically for Zsh support. |
特殊
${ASSERT_EQUALS}: 包含行數(shù)信息的宏洗做,可替換assert函數(shù)。
#! /bin/sh
# file: examples/lineno_test.sh
testLineNo()
{
# this assert will have line numbers included (e.g. "ASSERT:[123] ...") if
# they are supported.
echo "_ASSERT_EQUALS_ macro value: ${_ASSERT_EQUALS_}"
${_ASSERT_EQUALS_} '"not equal"' 1 2
# this assert will not have line numbers included (e.g. "ASSERT: ...")
assertEquals 'not equal' 1 2
}
# load shunit2
. ../src/shunit2
輸出
testLineNo
_ASSERT_EQUALS_ macro value: eval assertEquals --lineno "${LINENO:-}"
ASSERT:[9] not equal expected:<1> but was:<2>
ASSERT:not equal expected:<1> but was:<2>
Ran 1 test.
FAILED (failures=2)
測試Skipping
腳本
# available as examples/math.inc
add_generic()
{
num_a=$1
num_b=$2
expr $1 + $2
}
add_bash()
{
num_a=$1
num_b=$2
echo $(($1 + $2))
}
單元測試用例
#! /bin/sh
# available as examples/math_test.sh
testAdding()
{
result=`add_generic 1 2`
assertEquals \
"the result of '${result}' was wrong" \
3 "${result}"
# disable non-generic tests
[ -z "${BASH_VERSION:-}" ] && startSkipping
result=`add_bash 1 2`
assertEquals \
"the result of '${result}' was wrong" \
3 "${result}"
}
oneTimeSetUp()
{
# load include to test
. ./math.inc
}
# load and run shUnit2
. ../src/shell/shunit2
在Bash shell的執(zhí)行結(jié)果:
testAdding
Ran 1 test.
OK
在Unix shell執(zhí)行結(jié)果卻是:
testAdding
Ran 1 test.
OK (skipped=1)
Skipping可以使用startSkipping()彰居、endSkipping()和isSkipping()這三個函數(shù)進(jìn)行控制诚纸。
我是咕咕雞,一個還在不停學(xué)習(xí)的全棧工程師裕菠。
熱愛生活咬清,喜歡跑步,家庭是我不斷向前進(jìn)步的動力。