当前位置:  开发笔记 > 编程语言 > 正文

shell脚本的单元测试

如何解决《shell脚本的单元测试》经验,为你挑选了4个好方法。

几年来我所使用的每一件产品都涉及一定程度的shell脚本(或Windows上的批处理文件,PowerShell等).尽管我们用Java或C++编写了大量代码,但似乎总有一些集成或安装任务最好用shell脚本完成.

因此,shell脚本成为已发布代码的一部分,因此需要像编译代码一样进行测试.有没有人有过一些shell脚本单元测试框架的经验,比如shunit2?我现在主要对Linux shell脚本感兴趣; 我想知道测试工具如何复制其他xUnit框架的功能和易用性,以及与CruiseControl或Hudson等连续构建系统集成是多么容易.



1> Pete TerMaat..:

更新2019-03-01:我的偏好现在是蝙蝠.我在小项目上使用了几年.我喜欢简洁明了的语法.我没有将它与CI/CD框架集成,但它的退出状态确实反映了套件的整体成功/失败,这比shunit2更好,如下所述.


以前的答案:

我正在将shunit2用于与Linux环境中的Java/Ruby Web应用程序相关的shell脚本.它易于使用,与其他xUnit框架没有很大的不同.

我没有尝试与CruiseControl或Hudson/Jenkins集成,但是通过其他方式实现持续集成我遇到了这些问题:

退出状态:当测试套件发生故障时,shunit2不会使用非零退出状态来通知故障.因此,您要么必须解析shunit2输出以确定套件的通过/失败,要么将shunit2更改为一些持续集成框架所期望的行为,通过退出状态传递通过/失败.

XML日志:shunit2不会生成JUnit样式的XML结果日志.



2> phil pirozhk..:

想知道为什么没人提到BATS.它是最新的,符合TAP标准.

描述:

#!/usr/bin/env bats

@test "addition using bc" {
  result="$(echo 2+2 | bc)"
  [ "$result" -eq 4 ]
}

跑:

$ bats addition.bats
 ? addition using bc

1 tests, 0 failures



3> haridsv..:

@ blake-mizerany的综述听起来不错,我将来应该使用它,但这是我用于创建单元测试的"穷人"方法:

将所有可测试的东西分开作为一个功能.

将函数移动到外部文件中,比如说,functions.sh并将source其移入脚本中.你可以用它source `dirname $0`/functions.sh来达到这个目的.

最后functions.sh,将您的测试用例嵌入以下if条件:

if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
fi

您的测试是对函数的文字调用,然后是对退出代码和变量值的简单检查.我想添加一个简单的实用函数,如下所示,以便于编写:

function assertEquals()
{
    msg=$1; shift
    expected=$1; shift
    actual=$1; shift
    if [ "$expected" != "$actual" ]; then
        echo "$msg EXPECTED=$expected ACTUAL=$actual"
        exit 2
    fi
}

最后,functions.sh直接运行以执行测试.

以下是展示方法的示例:

    #!/bin/bash
    function adder()
    {
        return $(($1+$2))
    }

    (
        [[ "${BASH_SOURCE[0]}" == "${0}" ]] || exit 0
        function assertEquals()
        {
            msg=$1; shift
            expected=$1; shift
            actual=$1; shift
            /bin/echo -n "$msg: "
            if [ "$expected" != "$actual" ]; then
                echo "FAILED: EXPECTED=$expected ACTUAL=$actual"
            else
                echo PASSED
            fi
        }

        adder 2 3
        assertEquals "adding two numbers" 5 $?
    )



4> vilpan..:

除了roundup和shunit2之外,我对shell单元测试工具的概述还包括assert.sh和shelltestrunner.

我大多同意综合作者对shunit2的批评(其中一些是主观的),所以在查看文档和示例后我排除了shunit2.虽然看起来很熟悉有一些jUnit的经验.

在我看来,shelltestrunner是我看过的最原始的工具,因为它使用简单的声明性语法来进行测试用例定义.像往常一样,任何抽象级别都会以一些灵活性为代价提供一些便利.尽管简单性很有吸引力,但我发现该工具对我的情况也有限制,主要是因为缺乏定义setup/tearDown操作的方法(例如,在测试之前操作输入文件,在测试后删除状态文件)等).

我起初有点困惑,assert.sh只允许断言输出或退出状态,而我需要两者.足够长,可以使用综合编写几个测试用例.但我很快发现综合set -e模式不方便,因为在某些情况下,预期非零退出状态作为除了stdout之外传递结果的一种方式,这使得测试用例在所述模式下失败.其中一个样本显示了解决方案:

status=$(set +e ; rup roundup-5 >/dev/null ; echo $?)

但是如果我需要非零退出状态和输出呢?我可以,当然,set +e调用之前和set -e之后或set +e整个测试案例.但这违反了综述的原则"一切都是断言".所以我觉得我开始反对这个工具了.

到那时我已经意识到assert.sh允许仅断言退出状态或输出的"缺点"实际上是一个非问题,因为我可以传递test一个像这样的复合表达式

output=$($tested_script_with_args)
status=$?
expected_output="the expectation"
assert_raises "test \"$output\" = \"$expected_output\" -a $status -eq 2"

由于我的需求非常基本(运行一套测试,显示一切正常或失败),我喜欢assert.sh的简单性,所以这就是我选择的.

推荐阅读
贾志军
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有