我正在使用shUnit2在Bash shell脚本中进行单元测试。
我有这样的代码:
cat > /etc/somefile <<EOF
some file content
EOF
我想编写单元测试来测试此代码,但是要做到这一点,我需要避免文件I / O重定向。
我知道我可以重构代码以移动将文件输出重定向到函数内部的位,例如
cat_somefile() {
cat > /etc/somefile <<EOF
some file content
EOF
}
然后我可以在测试中对这个函数进行打桩。
虽然有什么方法可以测试此代码而不进行重构?
全部设置:
1 /授予sudo访问权限以运行chroot命令。
$ sudo visudo
...
%admin ALL = (ALL) NOPASSWD: /usr/sbin/chroot
2 /创建一个包含脚本和一个用于设置监狱的功能。
FAKE_ROOT=./fake_root copy_to_jail() { d=$(dirname $1) mkdir -p $FAKE_ROOT/$d cp -p $1 $FAKE_ROOT/$d } jail_files() { # All of these commands are used at least once by one of the # scripts under test. commands=" /bin/cat /bin/chmod /bin/date /bin/mkdir /bin/rm /usr/bin/awk /usr/bin/cut /usr/bin/tee " local OPTIND script wrappers while getopts "s:w:" o do case "${o}" in s) script="${OPTARG}" ;; w) wrappers="${wrappers} ${OPTARG}" ;; esac done shift $((OPTIND-1)) # Without /bin/sh the jail doesn't work. # I didn't spend time to figure out why. for f in /bin/sh $script $wrappers $commands do copy_to_jail $f done # We figure out all the library files we need to build # a working jail just by trying to start it, observing which file # it says is missing, copying the missing file, and repeating # until it starts. case $(uname -s) in Darwin) # Copy Bash 4 and GNU Sed. cp -p /usr/local/bin/bash $FAKE_ROOT/bin cp -p /usr/local/bin/gsed "$FAKE_ROOT/bin/sed" initial_libs=$( for f in /usr/local/bin/bash do otool -L $f | awk 'NR > 1 {print $1}' done | sort -u) initial_libs="/usr/lib/dyld $initial_libs" for f in $initial_libs do copy_to_jail $f done who_i_am=$(whoami) set -o pipefail while true do missing_lib=$(sudo chroot -u $who_i_am $FAKE_ROOT /bin/sh -c echo 2>&1 | \ awk '/dyld: Library not loaded:/ {print $5}') [ "$?" -eq 0 ] && break copy_to_jail $missing_lib done ;; *) echo "Platform $(uname -s) not supported" exit 1 ;; esac } clean_up_jail() { rm -rf $FAKE_ROOT }
3 /在测试文件中:
. shunit2/include.sh script_under_test=path/to/my/script.sh make_jail() { # Copy any binaries that the script depends on # to the jail. jail_files \ -s $script_under_test # Create any directories that are expected to exist. mkdir -p $FAKE_ROOT/etc/apt/preferences.d mkdir -p $FAKE_ROOT/etc/{default,init.d} mkdir -p $FAKE_ROOT/etc/apache2/sites-enabled mkdir -p $FAKE_ROOT/tmp ... # Set up any files with initial content. echo "some initial content" > $FAKE_ROOT/etc/hosts who_i_am=$(whoami) sudo chroot -u $who_i_am $FAKE_ROOT \ /bin/$(basename $script_under_test) > /dev/null } oneTimeSetUp() { make_jail } oneTimeTearDown() { clean_up_jail } # Write actual tests. test_something() { ... } test_something_else() { ... } # Call shUnit2. . shunit2
我将在某个阶段撰写有关此内容的博客文章。