我进入legacy shell脚本的unit testing。Shell脚本单元测试:如何模拟复杂的应用程序
在现实世界中的脚本通常被用来调用实用程序 像find
,tar
,cpio
,grep
,sed
,rsync
,date
等含有很多选择一些比较复杂的命令行。有时会构造和使用正则表达式或通配符模式。
的例如:这通常是由cron中定期调用的shell脚本必须从一台计算机的一些巨大的目录树镜像到另一个使用实用工具rsync任务。
#!/usr/bin/env bash
...
function mirror() {
...
COMMAND="rsync -aH$VERBOSE$DRY $PROGRESS $DELETE $OTHER_OPTIONS \
$EXCLUDE_OPTIONS $SOURCE_HOST:$DIRECTORY $TARGET"
...
if eval $COMMAND
then ...
else ...
fi
...
}
...
正如迈克尔羽毛在他的名著Working Effectively with Legacy Code写道,良好的单元测试的运行速度非常快,不接触网络,文件 - : 几个类型的文件和目录应该从 镜像过程中被排除在外系统或打开任何数据库。
继迈克尔羽毛建议这里使用的技术是:dependency injection。这里要替换的对象是应用程序rsync
。
我最初的想法:在我的shell脚本测试框架(我用bats)我操纵$PATH
的方式,一个mockuprsync
被发现的,而不是 真正rsync
效用。这个mockup对象可以检查提供的命令行参数和选项。与script under test的这部分中使用的其他实用程序类似。
我以前在脚本编写领域遇到的实际问题经验往往是由文件或目录名称中的特殊字符,引用或编码问题,缺少ssh密钥,错误权限等引起的错误。这些类型的错误将会逃脱这种单元测试技术。 (我知道:对于这些问题中的一些问题,单元测试根本不是治愈方法)。
另一个缺点是为rsync
或find
等复杂实用程序编写mockup容易出错并且是一项单调乏味的工程任务。
我相信上面描述的情况已经足够普遍,其他人可能会遇到类似的问题。谁有一些聪明的想法,并且会在意与我分享这些想法?
单元测试后,需要系统测试。也许建立一个简单的测试网络,其中包含每个有问题的文件,目录,缺失的密钥等。 – tripleee
使用与实际场景内联的“tee”来捕获被调用的命令响应,然后使用这些文件在测试利用场景中播放,也许用一个记录收到的参数的脚本,并盲目地发送罐装响应。 –
@Keith Tyler:这是一个非常整洁的想法:很显然,这种技术需要事先编写一些系统测试(但是当开始摆弄旧版脚本时,在开始重构脚本之前至少编写一些这样的测试无论如何都是一件好事理念)。赞成这个建议。 – pefu