我有一个shell脚本,我想用shUnit测试.脚本(和所有功能)都在一个文件中,因为它使安装更容易.
示例 script.sh
#!/bin/sh
foo () { ... }
bar () { ... }
code
Run Code Online (Sandbox Code Playgroud)
我想编写第二个文件(不需要分发和安装)来测试中定义的函数 script.sh
就像是 run_tests.sh
#!/bin/sh
. script.sh
# Unit tests
Run Code Online (Sandbox Code Playgroud)
现在的问题在于.(或source在Bash中).它不仅解析函数定义,还执行脚本中的代码.
由于没有参数的脚本没有任何坏处,我可以
. script.sh > /dev/null 2>&1
Run Code Online (Sandbox Code Playgroud)
但如果有更好的方法来实现我的目标,我就会徘徊.
编辑
我建议的解决方法在源脚本调用的情况下不起作用,exit所以我必须捕获退出
#!/bin/sh
trap run_tests ERR EXIT
run_tests() {
...
}
. script.sh
Run Code Online (Sandbox Code Playgroud)
run_tests调用该函数但是只要我重定向source命令的输出,脚本中的函数就不会被解析,并且在陷阱处理程序中不可用
这有效,但我得到的输出script.sh:
#!/bin/sh
trap run_tests ERR EXIT
run_tests() {
function_defined_in_script_sh
}
. script.sh
Run Code Online (Sandbox Code Playgroud)
这不打印输出但是我得到一个错误,该函数未定义:
#!/bin/sh
trap run_tests ERR EXIT
run_tests() {
function_defined_in_script_sh
}
. script.sh | grep OUTPUT_THAT_DOES_NOT_EXISTS
Run Code Online (Sandbox Code Playgroud)
这不会打印输出,并且run_tests根本不会调用陷阱处理程序:
#!/bin/sh
trap run_tests ERR EXIT
run_tests() {
function_defined_in_script_sh
}
. script.sh > /dev/null
Run Code Online (Sandbox Code Playgroud)
and*_*otn 68
根据bash联机帮助页面的"Shell Builtin命令"部分,.aka source也会获取一个可选的参数列表,这些参数将传递给源代码.你可以使用它来引入一个do-nothing选项.例如,script.sh可能是:
#!/bin/sh
foo() {
echo foo $1
}
main() {
foo 1
foo 2
}
if [ "${1}" != "--source-only" ]; then
main "${@}"
fi
Run Code Online (Sandbox Code Playgroud)
并且unit.sh可能是:
#!/bin/bash
. ./script.sh --source-only
foo 3
Run Code Online (Sandbox Code Playgroud)
然后script.sh将正常运行,并将unit.sh访问所有函数,script.sh但不会调用main()代码.
请注意,额外的参数source不在POSIX中,所以/bin/sh可能无法处理它 - 因此#!/bin/bash在开头unit.sh.
Doc*_*ger 19
从Python中学到了这个技术,但这个概念在bash或任何其他shell中运行得很好......
我们的想法是将脚本的主代码部分转换为函数.然后在脚本的最后,我们放置一个'if'语句,只有在我们执行脚本时才调用该函数,但如果我们来源它则不会.然后我们从'runtests'脚本中显式调用script()函数,该脚本已经获取了'script'脚本,因此包含了它的所有功能.
这依赖于以下事实:如果我们获取脚本,bash维护的环境变量$0(正在执行的脚本的名称)将是调用(父)脚本的名称(runtests在本例中),而不是源脚本.
(我已经重命名script.sh,只是script因为这.sh是多余的,让我困惑.:-)
以下是两个脚本.一些笔记......
$@计算作为单个字符串传递给函数或脚本的所有参数.相反,如果我们使用$*,所有参数将被连接成一个字符串.RUNNING="$(basename $0)"是必需的,因为$0始终至少包括当前目录前缀,如./script.if [[ "$RUNNING" == "script" ]]....script只有script直接从命令行运行才能调用script()函数的魔力
.脚本
#!/bin/bash
foo () { echo "foo()"; }
bar () { echo "bar()"; }
script () {
ARG1=$1
ARG2=$2
#
echo "Running '$RUNNING'..."
echo "script() - all args: $@"
echo "script() - ARG1: $ARG1"
echo "script() - ARG2: $ARG2"
#
foo
bar
}
RUNNING="$(basename $0)"
if [[ "$RUNNING" == "script" ]]
then
script "$@"
fi
Run Code Online (Sandbox Code Playgroud)
runtests
#!/bin/bash
source script
# execute 'script' function in sourced file 'script'
script arg1 arg2 arg3
Run Code Online (Sandbox Code Playgroud)
如果您正在使用Bash,则可以使用BASH_SOURCE数组来完成@andrewdotn方法的类似解决方案(但不需要额外的标志或取决于脚本名称).
script.sh:
#!/bin/bash
foo () { ... }
bar () { ... }
main() {
code
}
if [[ "${#BASH_SOURCE[@]}" -eq 1 ]]; then
main "$@"
fi
Run Code Online (Sandbox Code Playgroud)
run_tests.sh:
#!/bin/bash
. script.sh
# Unit tests
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
43409 次 |
| 最近记录: |