Testing Shell Scripts
Table Cases
Count Failures
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.
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"
fail_index ← 0
3fail_index=04cases=("login:pass" "search:pass" "deploy:pass")values this step0fail_indexcases ← login:pass search:pass deploy:pass
3fail_index=04cases=("login:pass" "search:pass" "deploy:pass")5if [[ "$fail_index" -gt 0 ]]; thenvalues this steplogin:pass search:pass deploy:passcasesif [[ "$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_indexfailures ← 0
7fi8failures=09for case_result in "${cases[@]}"; dovalues this step0failuresfor case_result in "${cases[@]}"; do
8failures=09for case_result in "${cases[@]}"; do10 if [[ "$case_result" == *":fail" ]]; thenvalues this steplogin:pass search:pass deploy:passcasesecho "failures=$failures"
13done14echo "failures=$failures"outputfailures=0values this step0failures
fail_index ← 2
3fail_index=24cases=("login:pass" "search:pass" "deploy:pass")values this step2fail_indexcases ← login:pass search:pass deploy:pass
3fail_index=24cases=("login:pass" "search:pass" "deploy:pass")5if [[ "$fail_index" -gt 0 ]]; thenvalues this steplogin:pass search:pass deploy:passcasesif [[ "$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_indexcases ← login:pass search:pass deploy:fail
5if [[ "$fail_index" -gt 0 ]]; then6 cases[$fail_index]="deploy:fail"7fivalues this steplogin:pass search:pass deploy:failcasesfailures ← 0
7fi8failures=09for case_result in "${cases[@]}"; dovalues this step0failuresfor case_result in "${cases[@]}"; do
8failures=09for case_result in "${cases[@]}"; do10 if [[ "$case_result" == *":fail" ]]; thenvalues this steplogin:pass search:pass deploy:failcasesfailures ← 1
10if [[ "$case_result" == *":fail" ]]; then11 failures=$((failures + 1))12fivalues this step1failuresecho "failures=$failures"
13done14echo "failures=$failures"outputfailures=1values 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.