Table-driven shell tests can store several case outcomes and count the failures in one loop.

Program

Play the script to choose whether one modeled case fails and watch the failure count change.

fail_index
table_cases.sh
Replay: real traced execution (multi-file project)
#!/usr/bin/env bash

fail_index=0
cases=("login:pass" "search:pass" "deploy:pass")
if [[ "$fail_index" -gt 0 ]]; then
    cases[$fail_index]="deploy:fail"
fi
failures=0
for case_result in "${cases[@]}"; do
    if [[ "$case_result" == *":fail" ]]; then
        failures=$((failures + 1))
    fi
done
echo "failures=$failures"
#!/usr/bin/env bash

fail_index=2
cases=("login:pass" "search:pass" "deploy:pass")
if [[ "$fail_index" -gt 0 ]]; then
    cases[$fail_index]="deploy:fail"
fi
failures=0
for case_result in "${cases[@]}"; do
    if [[ "$case_result" == *":fail" ]]; then
        failures=$((failures + 1))
    fi
done
echo "failures=$failures"
  1. fail_index ← 0

    3fail_index=04cases=("login:pass" "search:pass" "deploy:pass")
    values this step0fail_index
  2. cases ← login:pass search:pass deploy:pass

    3fail_index=04cases=("login:pass" "search:pass" "deploy:pass")5if [[ "$fail_index" -gt 0 ]]; then
    values this steplogin:pass search:pass deploy:passcases
  3. if [[ "$fail_index" -gt 0 ]]; then

    4cases=("login:pass" "search:pass" "deploy:pass")5if [[ "$fail_index" -gt 0 ]]; then6    cases[$fail_index]="deploy:fail"
    values this step0fail_index
  4. failures ← 0

    7fi8failures=09for case_result in "${cases[@]}"; do
    values this step0failures
  5. for case_result in "${cases[@]}"; do

    8failures=09for case_result in "${cases[@]}"; do10    if [[ "$case_result" == *":fail" ]]; then
    values this steplogin:pass search:pass deploy:passcases
  6. echo "failures=$failures"

    13done14echo "failures=$failures"
    outputfailures=0
    values this step0failures
  1. fail_index ← 2

    3fail_index=24cases=("login:pass" "search:pass" "deploy:pass")
    values this step2fail_index
  2. cases ← login:pass search:pass deploy:pass

    3fail_index=24cases=("login:pass" "search:pass" "deploy:pass")5if [[ "$fail_index" -gt 0 ]]; then
    values this steplogin:pass search:pass deploy:passcases
  3. if [[ "$fail_index" -gt 0 ]]; then

    4cases=("login:pass" "search:pass" "deploy:pass")5if [[ "$fail_index" -gt 0 ]]; then6    cases[$fail_index]="deploy:fail"
    values this step2fail_index
  4. cases ← login:pass search:pass deploy:fail

    5if [[ "$fail_index" -gt 0 ]]; then6    cases[$fail_index]="deploy:fail"7fi
    values this steplogin:pass search:pass deploy:failcases
  5. failures ← 0

    7fi8failures=09for case_result in "${cases[@]}"; do
    values this step0failures
  6. for case_result in "${cases[@]}"; do

    8failures=09for case_result in "${cases[@]}"; do10    if [[ "$case_result" == *":fail" ]]; then
    values this steplogin:pass search:pass deploy:failcases
  7. failures ← 1

    10if [[ "$case_result" == *":fail" ]]; then11    failures=$((failures + 1))12fi
    values this step1failures
  8. echo "failures=$failures"

    13done14echo "failures=$failures"
    outputfailures=1
    values this step1failures
table-driven test A table keeps case data separate from the loop that evaluates it.
glob pattern `*":fail"` matches any case result ending in `:fail`.
failure count Counting failures produces a single value for CI or a summary line.