多年来,我从事的几乎所有产品都涉及到一定程度的Shell脚本(或Windows上的批处理文件,PowerShell等)。 即使我们使用Java或C ++编写了大量代码,但似乎总是存在一些集成或安装任务,而这些任务或任务可以通过Shell脚本更好地完成。
因此,shell脚本成为附带代码的一部分,因此需要像已编译的代码一样进行测试。 有没有人对其中的一些shell脚本单元测试框架有经验,例如shunit2? 目前,我主要对Linux shell脚本感兴趣。 我想知道测试工具能够很好地复制其他xUnit框架的功能和易用性,以及与持续构建系统(如CruiseControl或Hudson)进行集成的难易程度。
综述为您确定了一些任务/标签。 一旦克服了学习障碍,它就会非常有用。 我个人更喜欢haridsvs方法,因为它不需要我安装另一个pkg。 我已经将此方法应用于外壳脚本和python测试。
您还可以检查bashtest实用程序:github.com/pahaz/bashtest(这是编写bash测试的简单方法)
查看几乎所有可能工具的概述:medium.com/wemake-services/
@sobolevn非常好的文章,谢谢!
更新2019-03-01:我的偏好是现在蝙蝠。我在小型项目上使用了几年。我喜欢简洁明了的语法。我尚未将其与CI / CD框架集成在一起,但是它的退出状态确实反映了套件的整体成功/失败,这比shunit2更好,如下所述。
上一个答案:
我正在将shunit2用于与Linux环境中的Java / Ruby Web应用程序相关的shell脚本。它易于使用,并且与其他xUnit框架没有很大的不同。
我没有尝试与CruiseControl或Hudson / Jenkins集成,但是在通过其他方式实施持续集成时遇到了以下问题:
退出状态:当测试套件失败时,shunit2不会使用非零退出状态来传达失败。因此,您要么必须解析shunit2输出以确定套件的通过/失败,要么更改shunit2使其表现出某些连续集成框架所期望的行为,并通过退出状态传达通过/失败。
XML日志:shunit2不会生成JUnit样式的XML结果日志。
皮特,我即将发布一个单元测试库,该库适用于bash和ksh,使用非常简单。您可以在某个地方向我发送指向Junit样式的XML日志的链接,以便我可以看到其中包含的内容吗?如果> 0的测试失败退出1,您是否还希望退出单个失败的测试或退出测试的退出状态?现在,我的方法是可以调用一个函数来获取通过/失败的测试数量。
@EthanPost我不再使用/要求XML日志。您可以通过搜索诸如" xunit xml format"之类的内容来找到帮助。这样的事情:xunit.github.io/docs/format-xml-v2.html
shunit现在也以正确的退出代码退出:github.com/kward/shunit2/blob/
想知道为什么没人提到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
BATS +1!从github指标(12个贡献者,将近2000个星)来看,这是大多数人选择作为bash xUnit测试运行程序的工具。
+1:我前一段时间使用了BATS,但并没有完全感到不知所措。今天找到了这份出色的(独立的?)《入门指南》文档,一直沿用至今,现已在BATS上完全出售。
蝙蝠住在这里github.com/bats-core/bats-core
当我读完这个答案时,我的第一个冲动是"不,维护者没有响应问题,并且存在一些严重的错误,但是后来我发现,自从我上次使用它以来,它就已经被分叉了"。
@ blake-mizerany的综述听起来很棒,以后我应该使用它,但这是我用于创建单元测试的"穷人"方法:
将所有可测试的功能分开。
将函数移至外部文件,例如将functions.sh和source移至脚本中。您可以将source `dirname $0`/functions.sh用于此目的。
在functions.sh的结尾,如果有条件,则将测试用例嵌入以下内容:
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 $?
)
很好,谢谢-我非常喜欢针对Shell脚本的结构化编程方法。
很好的观察:将所有可测试的功能分开。即使您尚未为它编写测试,它也很重要。这是提高代码可读性的主要因素。几年前,我开始根据此原理编写(ksh)脚本。将所有内容编写为函数。
@HenkLangeveld是否会导致exit 0也导致" sourcee"(一个采购此资源)退出?我认为您正在这里寻找return。
@haridsv好问题。当您获取文件源时,您不想运行测试。通过将所有与测试相关的代码收集到一个子外壳中,我们不会破坏使用者的运行时环境。 exit 0仅终止子外壳。
@HenkLangeveld糟糕,您是对的,我没有注意您添加的括号。
太好了感谢您的详细解释。
围捕:
http://bmizerany.github.com/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的简单性,因此我选择了它。
您应该尝试使用assert.sh lib,非常方便,易于使用
local expected actual
expected="Hello"
actual="World!"
assert_eq"$expected""$actual""not equivalent!"
# => x Hello == World :: not equivalent!
寻找了一个简单的shell单元测试框架后,该框架可以为Jenkins生成xml结果并且没有真正找到任何东西,然后我写了一个。
它在sourceforge上-项目的名称是jshu。
http://sourceforge.net/projects/jshu
我最近发布了称为shellspec的新测试框架。
https://shellspec.info/
https://github.com/ko1nksm/shellspec
shellspec是BDD样式测试框架。
它适用于POSIX兼容的shell脚本,包括bash,破折号,ksh,busybox等。
当然,退出状态反映了规范运行的结果
并且具有符合TAP的格式化程序。
specfile接近自然语言,易于阅读,
以及与Shell脚本兼容的语法。
#shellcheck shell=sh
Describe 'sample'
Describe 'calc()'
calc() { echo"$(($*))"; }
It 'calculates the formula'
When call calc 1 + 2
The output should equal 3
End
End
End
版本0.16.0中支持的JUnit格式化程序。并支持覆盖率,并行执行等。