Skip to content

Commit d7659da

Browse files
committed
fix: stop executing remaining commands in set_up/tear_down after first failure
1 parent 96f81db commit d7659da

3 files changed

Lines changed: 47 additions & 10 deletions

File tree

src/runner.sh

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -526,8 +526,9 @@ function runner::cleanup_on_exit() {
526526
local exit_code="$2"
527527

528528
set +e
529-
local teardown_status=0
530-
runner::run_tear_down "$test_file" || teardown_status=$?
529+
# Don't use || here - it disables ERR trap in the entire call chain
530+
runner::run_tear_down "$test_file"
531+
local teardown_status=$?
531532
runner::clear_mocks
532533
cleanup_testcase_temp_files
533534

@@ -743,20 +744,22 @@ function runner::execute_test_hook() {
743744
local hook_output_file
744745
hook_output_file=$(temp_file "${hook_name}_output")
745746

746-
# Enable errexit and errtrace to catch any failing command in the hook
747+
# Enable errexit and errtrace to catch any failing command in the hook.
748+
# The ERR trap saves the exit status to a global variable (since return value
749+
# from trap doesn't propagate properly), disables errexit (to prevent caller
750+
# from exiting) and returns from the hook function, preventing subsequent
751+
# commands from executing.
752+
# Variables set before the failure are preserved since we don't use a subshell.
753+
_BASHUNIT_HOOK_ERR_STATUS=0
747754
set -eE
748-
# Set up trap to catch errors and record the exit status
749-
trap 'status=$?; set +eE; trap - ERR' ERR
755+
trap '_BASHUNIT_HOOK_ERR_STATUS=$?; set +eE; trap - ERR; return $_BASHUNIT_HOOK_ERR_STATUS' ERR
750756

751757
{
752758
"$hook_name"
753759
} >"$hook_output_file" 2>&1
754760

755-
# Capture final status and clean up
756-
local block_exit=$?
757-
if [[ $status -eq 0 ]]; then
758-
status=$block_exit
759-
fi
761+
# Capture exit status from global variable and clean up
762+
status=$_BASHUNIT_HOOK_ERR_STATUS
760763
trap - ERR
761764
set +eE
762765

tests/acceptance/bashunit_setup_error_test.sh

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,3 +86,23 @@ function test_bashunit_when_set_up_with_intermediate_failing_command() {
8686
assert_contains "$assertions_summary" "$actual"
8787
assert_general_error "$(./bashunit --no-parallel --env "$TEST_ENV_FILE" "$test_file")"
8888
}
89+
90+
# Issue #517: When set_up fails, remaining commands should not execute
91+
function test_bashunit_set_up_stops_on_first_failure() {
92+
local test_file=./tests/acceptance/fixtures/test_bashunit_setup_stops_on_failure.sh
93+
local marker_file="/tmp/bashunit_setup_marker_test"
94+
95+
# Clean up any existing marker file
96+
rm -f "$marker_file"
97+
98+
set +e
99+
./bashunit --no-parallel --env "$TEST_ENV_FILE" "$test_file" >/dev/null 2>&1
100+
set -e
101+
102+
# The marker file should NOT exist because the touch command
103+
# should not have executed after the failing command
104+
assert_file_not_exists "$marker_file"
105+
106+
# Clean up
107+
rm -f "$marker_file"
108+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
#!/usr/bin/env bash
2+
3+
# Test fixture for issue #517: When set_up fails, remaining commands should not execute
4+
5+
function set_up() {
6+
# This command will fail
7+
false
8+
# This should NOT execute - if it does, the marker file will be created
9+
touch "/tmp/bashunit_setup_marker_test"
10+
}
11+
12+
function test_dummy() {
13+
assert_same "foo" "foo"
14+
}

0 commit comments

Comments
 (0)