views:

415

answers:

4

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. The problem is it is hard to test the scripts.

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?

+1  A: 

There is actually a unit testing framework for shellscripts. I haven't used it myself, but it might be worth checking out.

Similar questions have been asked before:

ire_and_curses
A: 

I have found it hard to justify using bash for larger scripts when Python has such huge advantages:

  • Try/Except allows writing more robust scripts with the ability to undo changes in case of an error.
  • You don't have to use obscure syntax such as 'if [ x"$foo" = x"$bar"]; then ...' which is prone to errors.
  • Easy parsing of options and arguments using the getopt module (and there's an even easier module for parsing arguments, but the name escapes me).
  • Python allows you to work with lists/dicts and objects instead of basic strings and arrays.
  • Access to proper language tools such as regex, databases (sure you could pipe everything into the mysql command in bash, but it's not the nicest way to write code).
  • No need to worry about using the correct form of $* or "$*" or "$@" or $1 or "$1", spaces in filenames isn't an issue, etc, etc, etc.

Now I only use bash for the simplest of scripts.

too much php
+4  A: 

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

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
 }
Jim Dennis
First, bash scripts are not very readable. Second, expectations are complicated like checking if a lock file is created with the PID of the bash script that created it.
nimcap
A: 

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.

nimcap