目前我正在做一些从bash执行的单元测试。单元测试在bash脚本中初始化、执行和清理。该脚本通常包含init()、execute()和cleanup()函数。但它们不是强制性的。我想测试它们是否有定义。
我以前通过greping和seding源代码做到了这一点,但这似乎是错误的。还有更优雅的方式吗?
编辑:下面这句话很有魔力:
fn_exists()
{
LC_ALL=C type $1 | grep -q 'shell function'
}
目前我正在做一些从bash执行的单元测试。单元测试在bash脚本中初始化、执行和清理。该脚本通常包含init()、execute()和cleanup()函数。但它们不是强制性的。我想测试它们是否有定义。
我以前通过greping和seding源代码做到了这一点,但这似乎是错误的。还有更优雅的方式吗?
编辑:下面这句话很有魔力:
fn_exists()
{
LC_ALL=C type $1 | grep -q 'shell function'
}
当前回答
测试不同的解决方案:
#!/bin/bash
test_declare () {
declare -f f > /dev/null
}
test_declare2 () {
declare -F f > /dev/null
}
test_type () {
type -t f | grep -q 'function'
}
test_type2 () {
[[ $(type -t f) = function ]]
}
funcs=(test_declare test_declare2 test_type test_type2)
test () {
for i in $(seq 1 1000); do $1; done
}
f () {
echo 'This is a test function.'
echo 'This has more than one command.'
return 0
}
post='(f is function)'
for j in 1 2 3; do
for func in ${funcs[@]}; do
echo $func $post
time test $func
echo exit code $?; echo
done
case $j in
1) unset -f f
post='(f unset)'
;;
2) f='string'
post='(f is string)'
;;
esac
done
例如:输出
test_declare (f is function) real 0m0,055s user 0m0,041s sys 0m0,004s exit code 0 test_declare2 (f is function) real 0m0,042s user 0m0,022s sys 0m0,017s exit code 0 test_type (f is function) real 0m2,200s user 0m1,619s sys 0m1,008s exit code 0 test_type2 (f is function) real 0m0,746s user 0m0,534s sys 0m0,237s exit code 0 test_declare (f unset) real 0m0,040s user 0m0,029s sys 0m0,010s exit code 1 test_declare2 (f unset) real 0m0,038s user 0m0,038s sys 0m0,000s exit code 1 test_type (f unset) real 0m2,438s user 0m1,678s sys 0m1,045s exit code 1 test_type2 (f unset) real 0m0,805s user 0m0,541s sys 0m0,274s exit code 1 test_declare (f is string) real 0m0,043s user 0m0,034s sys 0m0,007s exit code 1 test_declare2 (f is string) real 0m0,039s user 0m0,035s sys 0m0,003s exit code 1 test_type (f is string) real 0m2,394s user 0m1,679s sys 0m1,035s exit code 1 test_type2 (f is string) real 0m0,851s user 0m0,554s sys 0m0,294s exit code 1
所以declare -F似乎是最好的解决方案。
其他回答
测试不同的解决方案:
#!/bin/bash
test_declare () {
declare -f f > /dev/null
}
test_declare2 () {
declare -F f > /dev/null
}
test_type () {
type -t f | grep -q 'function'
}
test_type2 () {
[[ $(type -t f) = function ]]
}
funcs=(test_declare test_declare2 test_type test_type2)
test () {
for i in $(seq 1 1000); do $1; done
}
f () {
echo 'This is a test function.'
echo 'This has more than one command.'
return 0
}
post='(f is function)'
for j in 1 2 3; do
for func in ${funcs[@]}; do
echo $func $post
time test $func
echo exit code $?; echo
done
case $j in
1) unset -f f
post='(f unset)'
;;
2) f='string'
post='(f is string)'
;;
esac
done
例如:输出
test_declare (f is function) real 0m0,055s user 0m0,041s sys 0m0,004s exit code 0 test_declare2 (f is function) real 0m0,042s user 0m0,022s sys 0m0,017s exit code 0 test_type (f is function) real 0m2,200s user 0m1,619s sys 0m1,008s exit code 0 test_type2 (f is function) real 0m0,746s user 0m0,534s sys 0m0,237s exit code 0 test_declare (f unset) real 0m0,040s user 0m0,029s sys 0m0,010s exit code 1 test_declare2 (f unset) real 0m0,038s user 0m0,038s sys 0m0,000s exit code 1 test_type (f unset) real 0m2,438s user 0m1,678s sys 0m1,045s exit code 1 test_type2 (f unset) real 0m0,805s user 0m0,541s sys 0m0,274s exit code 1 test_declare (f is string) real 0m0,043s user 0m0,034s sys 0m0,007s exit code 1 test_declare2 (f is string) real 0m0,039s user 0m0,035s sys 0m0,003s exit code 1 test_type (f is string) real 0m2,394s user 0m1,679s sys 0m1,035s exit code 1 test_type2 (f is string) real 0m0,851s user 0m0,554s sys 0m0,294s exit code 1
所以declare -F似乎是最好的解决方案。
你可以用四种方法检查它们
fn_exists() { type -t $1 >/dev/null && echo 'exists'; }
fn_exists() { declare -F $1 >/dev/null && echo 'exists'; }
fn_exists() { typeset -F $1 >/dev/null && echo 'exists'; }
fn_exists() { compgen -A function $1 >/dev/null && echo 'exists'; }
来自我对另一个答案的评论(当我回到这个页面时,我总是忽略这个答案)
$ fn_exists() { test x$(type -t $1) = xfunction; }
$ fn_exists func1 && echo yes || echo no
no
$ func1() { echo hi from func1; }
$ func1
hi from func1
$ fn_exists func1 && echo yes || echo no
yes
这告诉你它是否存在,但不是说它是一个函数
fn_exists()
{
type $1 >/dev/null 2>&1;
}
借鉴其他解决方案和评论,我得出了以下结论:
fn_exists() {
# appended double quote is an ugly trick to make sure we do get a string -- if $1 is not a known command, type does not output anything
[ `type -t $1`"" == 'function' ]
}
用作……
if ! fn_exists $FN; then
echo "Hey, $FN does not exist ! Duh."
exit 2
fi
它检查给定的参数是否是一个函数,并避免重定向和其他grepping。