Testing and shell-scripting reloaded: bash-unit

I already wrote about testing bash scripts automatically in this post: if you missed it, reading it can be useful to get the context.

A step forward

Moving a step forward, when you tests your bash scripts you can be interested both in mocking standard input and spying standard output (and standard error): here is how.

Spying standard output and error

You can write a test case that checks an assertion about produced output simply exploiting command substitution: you can write a test case that collects standard output (into the output variable) and makes an assertion about its content.

1
2
3
4
test_spying_stdout () {
output=$(echo -e "1 2 3 4 5 6")
echo $output | grep "1 2 3 4 5 6" > /dev/null
}

Simply adding some redirection stuff you can do the same about standard error:

1
2
3
4
test_spying_stderr () {
error=$(cat /proc/crypto no-file.txt 2>&1 > /dev/null)
echo $error | grep "no-file.txt: No such file or directory" > /dev/null
}

Mocking standard input

If you need to implement a test invoking a script that gets input from stding, both through redirection or through read command, you can provide mocked input providing a hardcoded version of stdin through <<EOF syntax:

1
2
3
4
5
6
7
8
test_mocking_stdin () {
cat <<EOF | grep "AAA" > /dev/null
XXX
YYY
AAA
ZZZ
EOF
}

With

1
2
3
4
  cat <<EOF | your_command
...
...
EOF

you’re instructing the shell to use the text stream provided after the command invocation and before the closing EOF token as stdin: now your_command can read from stdin getting the hardcoded, well known input you want to base your test case on.

bash-unit

Reached this point, I think we can extract a slightly reworked version of the script I have shown in the previous post into a reusable tool we can rely on to run our scripts’ test cases. With little imagination I called it bash-unit and published it here.

Simply put, it allows you to simply launch

1
bash-unit [test_cases_dir]

in order to execute the test suite: you find full installation instructions and test cases samples in the README file.