0

I have a test script written in bash where each test is placed in a function. The script loops through the list of functions, and runs them one after the other. I would like a test function to fail as soon as an error occurs.

#!/bin/bash
set -e

function test1 () {
   false; # i'd like the first command to fail inside the test function to
          # fail the entire test, simulating
          # what -e does at the top level. because the call to this function
          # is on the left side of a ||, -e is "ignored". and the function does
          # not stop unless I catch the error explicitly and return.
   echo "test success" # this gets printed
}

tests=(test1) # test2, test3, …

for testfunc in "${tests[@]}"; do
    $testfunc || { echo "$testfunc fail";  continue; }
    echo "$testfunc ok"
done

Is there some combination of traps, -e, -E, or subshells that will allow the function to run as if it was in -e mode, while at the same time allowing the main script continue running remaining tests after one test fails?

Hopefully there is a way to do this without checking every single command inside the test functions with && and ||.

init_js
  • 4,143
  • 2
  • 23
  • 53

1 Answers1

0

Instead of checking every single command inside every test function, temporarily disable the exit-on-error flag for the duration of the call to the test function, capture its exit status, and reenable the exit-on-error after.

So the loop becomes:

for testfunc in "${tests[@]}"; do
    set +e; (set -e; $testfunc; ); test_result="$?"
    set -e
    if [[ "$test_result" -ne 0 ]]; then
        echo "$testfunc fail"
    else
        echo "$testfunc ok"
    fi
done

One caveat with doing this is that the function runs in a subshell, which may affect variables being set inside the function, or trap functions which may or may not be inherited.

based on: https://stackoverflow.com/a/11092989/5556676

and also similar to https://stackoverflow.com/a/15302061/5556676 , except that this one uses the subshell in a parameter expansion, which is slightly more contrived.

init_js
  • 4,143
  • 2
  • 23
  • 53