单元测试 bash 脚本

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1339416/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-09 18:27:43  来源:igfitidea点击:

Unit Testing bash scripts

bashtestingtddautomated-testsextreme-programming

提问by nimcap

We have a system that has some bash scripts running besides Java code. Since we are trying to Test Everything That Could Possibly Break, and those bash scripts may break, we want to test them.

我们有一个系统,除了 Java 代码之外,还有一些 bash 脚本在运行。由于我们正在尝试测试所有可能中断的内容,而那些 bash 脚本可能会中断,因此我们想测试它们。

The problem is it is hard to test bash scripts.

问题是很难测试 bash 脚本。

Is there a way or a best practice to test bash scripts? Or should we quit using bash scripts and look for alternative solutions that are testable?

有没有办法或最佳实践来测试 bash 脚本?还是我们应该停止使用 bash 脚本并寻找可测试的替代解决方案?

采纳答案by nimcap

I got the following answer from a discussion group:

我从一个讨论组得到以下答案:

it's possible to import (include, whatever) a procedure (function, whatever it's named) from an external file. That's the key to writing a testing script: you break up your script into independent procedures that can then be imported into both your running script and your testing script, and then you have your running script be as simple as possible.

可以从外部文件导入(包括,无论如何)一个过程(函数,无论它叫什么名字)。这是编写测试脚本的关键:将脚本分解为独立的过程,然后可以将这些过程导入到运行脚本和测试脚本中,然后使运行脚本尽可能简单。

This method is like dependency injection for scripts, and sounds reasonable. Avoiding bash scripts and using more testable and less obscure language is preferable.

这种方法就像脚本的依赖注入,听起来很合理。避免使用 bash 脚本并使用更可测试和更少晦涩的语言是可取的。

回答by ire_and_curses

There is actually a shunit2, an xUnit based unit test framework for Bourne based shell scripts. I haven't used it myself, but it might be worth checking out.

实际上有一个shunit2,一个基于 xUnit 的单元测试框架,用于基于 Bourne 的 shell 脚本。我自己没有使用过它,但它可能值得一试。

Similar questions have been asked before:

之前也有人问过类似的问题:

回答by Janus Troelsen

TAP-compliant Bash testing: Bash Automated Testing System

符合 TAP的 Bash 测试:Bash 自动化测试系统

TAP, the Test Anything Protocol, is a simple text-based interface between testing modules in a test harness. TAP started life as part of the test harness for Perl but now has implementations in C, C++, Python, PHP, Perl, Java, JavaScript, and others.

TAP,即测试任何协议,是测试工具中测试模块之间的一个简单的基于文本的接口。TAP 最初是作为 Perl 测试工具的一部分,但现在已在 C、C++、Python、PHP、Perl、Java、JavaScript 和其他语言中实现。

bats-core

蝙蝠核心

回答by cb2

Nikita Sobolev wrote an excellent blog post comparing a few different bash test frameworks: Testing Bash applications

Nikita Sobolev 写了一篇优秀的博客文章,比较了几个不同的 bash 测试框架:测试 Bash 应用程序

For the impatient: Nikita's conclusion was to use Batsbut it appears that Nikita missed the Bats-coreproject which appear to me to be the one to use going forward as the original Bats project has not been actively maintained since 2013.

对于不耐烦的人:Nikita 的结论是使用Bats,但 Nikita 似乎错过了Bats 核心项目,在我看来,该项目是继续使用的项目,因为自 2013 年以来原始 Bats 项目一直没有得到积极维护。

回答by spbnick

Epoxyis a Bash test framework I designed mainly for testing other software, but I use it to test bash modules as well, including itselfand Carton.

Epoxy是一个 Bash 测试框架,我主要设计用于测试其他软件,但我也用它来测试 bash 模块,包括它自己Carton

Main advantages are relatively low coding overhead, unlimited assertion nesting and flexible selection of assertions to verify.

主要优点是相对较低的编码开销、无限的断言嵌套和灵活选择要验证的断言。

I made a presentationcomparing it to BeakerLib- a framework used by some at Red Hat.

我做了一个演讲,将它与BeakerLib进行了比较——这是 Red Hat 一些人使用的框架。

回答by Jim Dennis

Why do you say that it's "hard" to test bash scripts?

为什么说测试 bash 脚本“很难”?

What's wrong with test wrappers like:

测试包装器有什么问题,例如:

 #!/bin/bash
 set -e
 errors=0
 results=$($script_under_test $args<<ENDTSTDATA
 # inputs
 # go
 # here
 #
 ENDTSTDATA
 )
 [ "$?" -ne 0 ] || {
     echo "Test returned error code $?" 2>&1
     let errors+=1
     }

 echo "$results" | grep -q $expected1 || {
      echo "Test Failed.  Expected $expected1"
      let errors+=1
 }
 # and so on, et cetera, ad infinitum, ad nauseum
 [ "$errors" -gt 0 ] && {
      echo "There were $errors errors found"
      exit 1
 }

回答by Koichi Nakashima

I created shellspecbecause I wanted a easy-to-use and useful tool.

我创建shellspec是因为我想要一个易于使用且有用的工具。

It written by pure POSIX shell script. It has tested with many shells more than shunit2. It has powerful features than bats/bats-core.

它由纯 POSIX shell 脚本编写。它已经用超过 shunit2 的许多 shell 进行了测试。它具有比 bats/bats-core 更强大的功能。

For example, support nested block, easy to mock/stub, easy to skip/pending, parameterized tests, assertion line number, execute by line number, parallel execution, random execution, TAP/JUnit formatter, coverage and CI integration, profiler and etc.

例如,支持嵌套块、易于模拟/存根、易于跳过/挂起、参数化测试、断言行号、按行号执行、并行执行、随机执行、TAP/JUnit 格式化程序、覆盖率和 CI 集成、分析器等.

See the demo on the project page.

请参阅项目页面上的演示。

回答by Daniel C. Sobral

I can't believe no one talked about OSHT! It's compatible with bothTAP and JUnit, it's pure shell (that is, no other languages involved), it works standalone too, and it's simple and direct.

我不敢相信没有人谈论OSHT!这是兼容两种TAP和JUnit,这是纯粹的外壳(即,没有其他语言参与),它的工作原理独立过,而且它的简单和直接。

Testing looks like this (snippets taken from the project page):

测试看起来像这样(摘自项目页面的片段):

#!/bin/bash
. osht.sh

# Optionally, indicate number of tests to safeguard against abnormal exits
PLAN 13

# Comparing stuff
IS $(whoami) != root
var="foobar"
IS "$var" =~ foo
ISNT "$var" == foo

# test(1)-based tests
OK -f /etc/passwd
NOK -w /etc/passwd

# Running stuff
# Check exit code
RUNS true
NRUNS false

# Check stdio/stdout/stderr
RUNS echo -e 'foo\nbar\nbaz'
GREP bar
OGREP bar
NEGREP . # verify empty

# diff output
DIFF <<EOF
foo
bar
baz
EOF

# TODO and SKIP
TODO RUNS false
SKIP test $(uname -s) == Darwin

A simple run:

一个简单的运行:

$ bash test.sh
1..13
ok 1 - IS $(whoami) != root
ok 2 - IS "$var" =~ foo
ok 3 - ISNT "$var" == foo
ok 4 - OK -f /etc/passwd
ok 5 - NOK -w /etc/passwd
ok 6 - RUNS true
ok 7 - NRUNS false
ok 8 - RUNS echo -e 'foo\nbar\nbaz'
ok 9 - GREP bar
ok 10 - OGREP bar
ok 11 - NEGREP . # verify empty
ok 12 - DIFF <<EOF
not ok 13 - TODO RUNS false # TODO Test Know to fail

The last test shows as "not ok", but the exit code is 0 because it's a TODO. One can set verbose as well:

最后一个测试显示为“not ok”,但退出代码为 0,因为它是一个TODO. 也可以设置详细:

$ OSHT_VERBOSE=1 bash test.sh # Or -v
1..13
# dcsobral \!= root
ok 1 - IS $(whoami) != root
# foobar =\~ foo
ok 2 - IS "$var" =~ foo
# \! foobar == foo
ok 3 - ISNT "$var" == foo
# test -f /etc/passwd
ok 4 - OK -f /etc/passwd
# test \! -w /etc/passwd
ok 5 - NOK -w /etc/passwd
# RUNNING: true
# STATUS: 0
# STDIO <<EOM
# EOM
ok 6 - RUNS true
# RUNNING: false
# STATUS: 1
# STDIO <<EOM
# EOM
ok 7 - NRUNS false
# RUNNING: echo -e foo\nbar\nbaz
# STATUS: 0
# STDIO <<EOM
# foo
# bar
# baz
# EOM
ok 8 - RUNS echo -e 'foo\nbar\nbaz'
# grep -q bar
ok 9 - GREP bar
# grep -q bar
ok 10 - OGREP bar
# \! grep -q .
ok 11 - NEGREP . # verify empty
ok 12 - DIFF <<EOF
# RUNNING: false
# STATUS: 1
# STDIO <<EOM
# EOM
not ok 13 - TODO RUNS false # TODO Test Know to fail

Rename it to use a .textension and put it in a tsubdirectory, and you can use prove(1)(part of Perl) to run it:

重命名它以使用.t扩展名并将其放在t子目录中,您可以使用prove(1)(Perl 的一部分)来运行它:

$ prove
t/test.t .. ok
All tests successful.
Files=1, Tests=13,  0 wallclock secs ( 0.03 usr  0.01 sys +  0.11 cusr  0.16 csys =  0.31 CPU)
Result: PASS

Set OSHT_JUNITor pass -jto produce JUnit output. JUnit can also be combined with prove(1).

设置OSHT_JUNIT或传递-j以生成 JUnit 输出。JUnit 也可以与prove(1).

I have used this library both testing functions by sourcing their files and then running assertions with IS/OKand their negatives, and scripts by using RUN/NRUN. For me, this framework provides the most gain for the least overhead.

我使用了这个库,通过获取它们的文件然后使用IS/OK和它们的否定运行断言来测试功能,并使用RUN/运行脚本NRUN。对我来说,这个框架以最少的开销提供了最大的收益。

回答by Steve HHH

I quite like shell2junit, a utility to generate JUnit-like output from Bash script tests. This is useful because the report generated can then be read by continuous integration systems, such as the JUnit plug-ins for Jenkins and Bamboo.

我非常喜欢shell2junit,这是一个从 Bash 脚本测试生成类似 JUnit 的输出的实用程序。这很有用,因为生成的报告可以被持续集成系统读取,例如 Jenkins 和 Bamboo 的 JUnit 插件。

While shell2junit doesn't provide the comprehensive Bash scripting framework like shunit2, it does allow you have nice reporting of the test results.

虽然 shell2junit 没有像shunit2那样提供全面的 Bash 脚本框架,但它确实允许您很好地报告测试结果。

回答by pahaz

Try bashtest. It`s simple way to test your scripts. For example, you have do-some-work.shwhich change some config files. For example, add new line PASSWORD = 'XXXXX'to config file /etc/my.cfg.

试试bashtest。这是测试脚本的简单方法。例如,您do-some-work.sh更改了一些配置文件。例如,PASSWORD = 'XXXXX'在配置文件中添加新行/etc/my.cfg

You write bash commands line by line and then check output.

您逐行编写 bash 命令,然后检查输出。

Install:

安装:

pip3 install bashtest

Create tests is a just writing bash commands.

创建测试只是编写 bash 命令。

File test-do-some-work.bashtest:

文件test-do-some-work.bashtest

# run the script  
$ ./do-some-work.sh > /dev/null

# testing that the line "PASSWORD = 'XXXXX'" is in the file /etc/my.cfg   
$ grep -Fxq "PASSWORD = 'XXXXX'" /etc/my.cfg && echo "YES"
YES

Run tests:

运行测试:

bashtest *.bashtest

You can find some examples hereand here

你可以在这里这里找到一些例子