在 shUnit2 中重定向文件输出的单元测试 bash 脚本

2024-04-13

我正在使用 shUnit2 在 Bash shell 脚本中进行单元测试。

我有这样的代码:

cat > /etc/somefile <<EOF
some file content
EOF

我想编写单元测试来测试这段代码,但要做到这一点,我需要避免文件 I/O 重定向。

我意识到我可以重构代码以移动在函数内部重定向文件输出的位,例如

cat_somefile() {
  cat > /etc/somefile <<EOF
some file content
EOF
}

然后我可以在测试中存根这个函数。

有没有办法在不重构的情况下测试这段代码?


正如 @chepner 所建议的(另请参阅ref https://github.com/zofrex/bourne-shell-unit-testing) chroot 可以在这里提供帮助。

要设置这一切:

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

我会在某个阶段写一篇关于此的博客文章。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在 shUnit2 中重定向文件输出的单元测试 bash 脚本 的相关文章

随机推荐

  • 如何编辑swift错误断点?

    我想设置 Swift 错误断点来处理 Swift Error错误类型迅速 但我没有得到 What to set as Type value in BreakPoint 如果您只是创建一个 Swift 错误断点 它会在任何符合 ErrorTy
  • 为什么ostringstream在多线程环境下不能很好的工作

    也许有些事情很奇怪 当我在多线程环境中使用STL ostringstream 类时 我发现每个线程的执行时间随着线程数量的增加而线性增加 我不知道为什么会这样 我尝试检查 ostringstream 源代码 但找不到任何同步代码 ostri
  • 在android中围绕两个手指的中点缩放

    我有一个HorizontalScrollView其中有多个视图 我已经实施了pinch zoom gesture其中我的两根手指之间的多个视图被缩放 但我面临一个小问题 当我进行捏缩放时 捏缩放的中点正在移动 但为了用户体验 我希望该点保持
  • Next.js 从 Docker 容器无限重载

    我正在尝试制作一个简单的 Next js 应用程序 它使用 Firebase 身份验证并从 Docker 容器运行 以下内容在本地运行良好 从构建的 docker 容器运行 然而 当我部署到 Heroku 或 Google Cloud Ru
  • UIImageView 的触摸向上和触摸向下操作

    我想要实现的是 当用户触摸 UIImageView 时设置 Image1 当用户抬起手指时设置 Image2 我只能用此代码获取 UIGestureRecognizerState Ended var tap UITapGestureReco
  • 提高 python 脚本的吞吐量

    我正在通过 dig 处理来自 DNSBL 的数千个域名列表 创建 URL 和 IP 的 CSV 这是一个非常耗时的过程 可能需要几个小时 我的服务器的 DNSBL 每十五分钟更新一次 有没有办法可以提高 Python 脚本的吞吐量以跟上服务
  • 如何检查日期范围是否存在

    正如你从标题中可能注意到的 我的问题很难表达 但有一个问题 我有包含一些数据的 MySQL 表 在注册表中 我必须指定预订开始和结束时间 如何查询指定时间是否已登记预订 例如 我不应该能够添加从 13 20 开始到 15 00 结束的新预订
  • Azure API 管理和 API 版本控制

    Azure API 管理如何帮助我管理不同版本的 API 并将所选操作从旧版本的 API 重新路由到新版本的 API 有两种方法可以实现这一目标 您可以使用不包含版本段的服务 URL 配置 API 例如 https my api https
  • 将多个文件连接成一个文件对象,而不创建新文件

    这个问题与Python 连接文本文件 https stackoverflow com questions 13613336 python concatenate text files 我有一个清单file names like file1
  • 如何在 python-gensim 中使用潜在狄利克雷分配(LDA)来抽象二元组主题而不是一元组?

    LDA 原始输出 一元语法 主题1 水肺 水 蒸汽 潜水 主题2 二氧化物 植物 绿色 碳 所需输出 二元组主题 主题1 水肺潜水 水蒸气 主题2 绿色植物 二氧化碳 任何想法 鉴于我有一个名为docs 包含文档中的单词列表 我可以使用 n
  • 在 C# 中获取两个时间之间的时间跨度?

    我有两个文本框 一种用于准时打卡 另一种用于打卡下班 时间将采用以下格式 Hours Minutes 假设我早上 7 00 打卡上班 下午 2 00 打卡下班 使用我当前的代码 我得到了 2 小时的差异 但实际上应该是 7 小时 我将如何在
  • 使用 Photoshop 脚本显示/隐藏图层的功能 (JSX)

    我正在编写一个脚本 它将循环遍历图层 修剪它们并导出 到目前为止 我已经拥有完成此脚本所需的大部分元素 我唯一找不到的是如何显示 隐藏单个图层 我找到了显示 隐藏所有图层的功能 但没有找到单个图层的功能 selectAllLayers se
  • Delphi 中的 Web 服务超时错误

    我有一个发出 SOAP 请求的客户端应用程序 我已将超时设置为 20 分钟 但是 有时我会看到 10 秒后发生超时错误 我的代码中有以下内容 RIO HTTPWebNode ReceiveTimeout 1200000 我需要设置Conne
  • 使用 android espresso 访问自定义可扩展列表中的子项

    我正在尝试访问自定义可扩展列表中的子项 该列表如下所示 自定义可扩展列表 http foodaversions com aversions cropped png 我可以通过以下方式成功访问组 Espresso onView allOf w
  • beautifulsoup:导入错误:没有名为 html.entities 的模块

    我试图让这个模块在服务器上工作 但我在标题中收到错误 我的脚本 from bs4 import BeautifulSoup 当我运行它时 aclark tycho python test py Traceback most recent c
  • 将项目附加到 WPF 中的数据绑定 ItemsControl

    我有一个组合框 它与项目的 ObservableCollection 进行数据绑定 我想要一个默认选定的项目 无 它将我绑定到 SelectedValue 的属性的值设置为 null 我认为应该有一种方法可以通过 Style DataTem
  • 如何在 Hibernate 中创建/调用 sql 视图

    这是在中创建的视图document hbm xml
  • 从 DateTime 系列中的多个 CSV 文件设置 MultiIndex DataFrame

    我有一个 CSV 格式的时间序列价格数据列表 其读法如下 asxList ANZ NAB WBC for asxCode in asxList ohlcData pd DataFrame from csv asxCode CSV heade
  • Elixir GenServer 并行handle_call

    Phoenix框架上有一个应用程序 需要 GenServer 它将检查一些值 这些值的验证从控制器开始 来自客户端的请求 GenServer 值检查 客户端接收响应 一旦handle call是同步的 那么当10个客户端同时调用10个han
  • 在 shUnit2 中重定向文件输出的单元测试 bash 脚本

    我正在使用 shUnit2 在 Bash shell 脚本中进行单元测试 我有这样的代码 cat gt etc somefile lt