bash - Shell 脚本单元测试 : How to mockup a complex utility program

标签 bash shell unit-testing bats-core

我很喜欢 unit testing一些legacy 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
      ...
  }
  ...

正如 Michael Feathers 在他的名著 Working Effectively with Legacy Code 中所写的那样, 一个好的单元测试运行得非常快,不会接触网络、文件系统或打开任何数据库。

根据 Michael Feathers 的建议,此处使用的技术是:dependency injection .此处要替换的对象是实用程序 rsync

我的第一个想法:在我的 shell 脚本测试框架(我使用 bats )中,我以 mockup 的方式操作 $PATH rsync 被发现而不是 真正的 rsync 工具。这mockup对象可以检查提供的命令行参数和选项。与本部分中使用的其他实用程序类似 script under test .

我过去在这个脚本领域遇到的实际问题通常是由文件或目录名称中的特殊字符引起的错误、引号或编码问题、缺少 ssh key 、错误权限等。这些类型的错误会逃脱这种单元测试技术。 (我知道:对于其中一些问题,单元测试根本无法解决)。

另一个缺点是写一个mockup对于像 rsyncfind 这样的复杂实用程序来说,它很容易出错,而且本身就是一项乏味的工程任务。

我相信上面描述的情况很普遍,其他人可能也遇到过类似的问题。谁有一些聪明的想法并愿意在这里与我分享?

最佳答案

您可以使用函数模拟任何命令,如下所示:

function rsync() {
    # mock things here if necessary
}

然后导出函数并运行单元测试:

export -f rsync
unittest

关于bash - Shell 脚本单元测试 : How to mockup a complex utility program,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36219223/

相关文章:

java - 来自与测试类不同的类的模拟方法

Bash:如何测试 mkdir 命令的失败?

c - Bash for Windows 10 gcc 不会编译粘贴到根目录中的 c 文件

用于从某些子目录中删除特定文件的 Bash 脚本

用于编译测试的 CMake 和 CMocka 标准断言

java - 如何在不运行的情况下将测试类打包到jar中?

multithreading - 如何以多线程或高效方式执行 "git pull"?

linux - 通过管道 awk 进行排序无法正确排序

json - 修改JSON jq中的键值数组

bash - 如何从 find 命令中排除特定目录的子目录?