Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .github/workflows/static_analysis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,6 @@ jobs:
uses: ludeeus/action-shellcheck@master
env:
SHELLCHECK_OPTS: -e SC1091 -e SC2155 -e SC2016
with:
ignore_names: test_bashunit_when_syntax_error.bash

1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
- Fix `clock::now` shell-time parsing when `EPOCHREALTIME` uses a comma decimal separator
- Fix LCOV and HTML coverage reports generating incomplete/empty output due to post-increment operator causing silent exit under `set -e` (#618)
- Enable parallel test execution on Alpine Linux; previously gated off due to race conditions, now resolved (#370)
- Fix syntax error in test file silently passing; now reported as a failing test (#220)

## [0.34.1](https://github.com/TypedDevs/bashunit/compare/0.34.0...0.34.1) - 2026-03-20

Expand Down
20 changes: 20 additions & 0 deletions docs/test-files.md
Original file line number Diff line number Diff line change
Expand Up @@ -129,3 +129,23 @@ function tear_down_after_script() {
}
```
:::

## Syntax errors in test files

If a test file contains a Bash syntax error, **bashunit** records a failing
test for that file instead of silently skipping the remaining tests. The exact
error message from Bash (including file path and line number) is shown in the
summary, and the suite exits with a non-zero status.

```
Running tests/example_test.sh
✗ Error: Source
tests/example_test.sh: line 10: syntax error near unexpected token `fi'
tests/example_test.sh: line 10: ` fi'

Tests: 1 failed, 1 total
Some tests failed
```

This guarantees a broken test file always fails the suite, so it never
passes by absence.
20 changes: 19 additions & 1 deletion src/runner.sh
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,26 @@ function bashunit::runner::load_test_files() {
scripts_ids[scripts_ids_count]="${BASHUNIT_CURRENT_SCRIPT_ID}"
scripts_ids_count=$((scripts_ids_count + 1))
bashunit::internal_log "Loading file" "$test_file"
local source_err_file source_err source_status
source_err_file="$(bashunit::temp_file "source_err")"
# shellcheck source=/dev/null
source "$test_file"
source "$test_file" 2>"$source_err_file"
source_status=$?
source_err=""
if [ -s "$source_err_file" ]; then
source_err="$(cat "$source_err_file")"
fi
rm -f "$source_err_file"
if [ "$source_status" -ne 0 ] || [ "$(printf '%s' "$source_err" \
| "$GREP" -cE 'syntax error|unexpected EOF' || true)" -gt 0 ]; then
local message="$source_err"
[ -z "$message" ] && message="Failed to source '$test_file' (exit $source_status)"
bashunit::runner::record_file_hook_failure \
"source" "$test_file" "$message" 1 true
bashunit::runner::clean_set_up_and_tear_down_after_script
bashunit::runner::restore_workdir
continue
fi
# Update function cache after sourcing new test file
_BASHUNIT_CACHED_ALL_FUNCTIONS=$(declare -F | awk '{print $3}')
# Check if any tests match the filter before rendering header or running hooks
Expand Down
28 changes: 28 additions & 0 deletions tests/acceptance/bashunit_syntax_error_test.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#!/usr/bin/env bash
set -euo pipefail

function set_up_before_script() {
TEST_ENV_FILE="tests/acceptance/fixtures/.env.default"
}

function strip_ansi() {
sed -E 's/\x1B\[[0-9;]*[A-Za-z]//g'
}

function test_bashunit_when_test_file_has_syntax_error() {
local test_file=./tests/acceptance/fixtures/test_bashunit_when_syntax_error.bash

local actual_raw
set +e
actual_raw="$(LC_ALL=C LANG=C ./bashunit \
--no-parallel --detailed --env "$TEST_ENV_FILE" "$test_file" 2>&1)"
set -e

local actual
actual="$(printf "%s" "$actual_raw" | strip_ansi)"

assert_contains "failed" "$actual"
assert_contains "Error" "$actual"
assert_general_error "$(LC_ALL=C LANG=C ./bashunit \
--no-parallel --env "$TEST_ENV_FILE" "$test_file" 2>&1)"
}
15 changes: 15 additions & 0 deletions tests/acceptance/fixtures/test_bashunit_when_syntax_error.bash
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#!/usr/bin/env bash

function test_good() {
assert_equals 1 1
}

function test_with_syntax_error() {
if [ 1 -eq 1 ]
echo "missing then keyword"
fi
}

function test_another() {
assert_equals 2 2
}
Loading