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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
- The `--parallel` unsupported-OS warning no longer claims Alpine is excluded: Alpine has been a supported parallel platform since the race conditions were fixed, the message was simply never updated

### Fixed
- An unknown option is now rejected with a clear error and a non-zero exit instead of being silently filed under test paths. A mistyped flag used to degrade the run while still reporting success: `bashunit --parralel tests/` ran sequentially and exited `0`, and `bashunit --filterr foo tests/` swallowed both the flag and its value and ran the whole suite. Applies to `test` and `bench`; the `assert` subcommand parses its own arguments and is unchanged (#871)
- The quickstart's sample output showed durations as `16 ms` / `90 ms`; bashunit prints `16ms` / `90ms`
- `.env.example` documented `BASHUNIT_SHOW_EXECUTION_TIME` as defaulting to `true`; the actual default has been `auto` since #765
- bashunit now aborts with an actionable error when its scratch directories under `TMPDIR` cannot be created. Previously the run continued with every failure/skip collector writing nowhere, so a failing suite still exited non-zero but lost its assertion detail and leaked raw `src/runner.sh: line N: ...: Not a directory` errors instead of reporting the cause
Expand Down
20 changes: 20 additions & 0 deletions src/main.sh
Original file line number Diff line number Diff line change
@@ -1,5 +1,15 @@
#!/usr/bin/env bash

##
# Prints an "unknown option" error and exits non-zero.
# Arguments: $1 - the offending argument, $2 - subcommand to name in the hint
##
function bashunit::main::abort_unknown_option() {
printf "%sError: unknown option '%s'. Run 'bashunit %s --help' to list the available options.%s\n" \
"${_BASHUNIT_COLOR_FAILED}" "$1" "$2" "${_BASHUNIT_COLOR_DEFAULT}" >&2
exit 1
}

##
# Validates a `--shard <index>/<total>` spec and exports the parts, or prints an
# error and exits non-zero. Requires numeric index/total with 1 <= index <= total.
Expand Down Expand Up @@ -329,6 +339,13 @@ function bashunit::main::cmd_test() {
fi
_bashunit_coverage_opt_set=true
;;
-*)
# Anything option-shaped reaching here matched no branch above. It used to
# be filed under test paths, so a typo degraded the run silently and still
# exited 0: `--parralel` ran sequentially, `--filterr x` ran the whole
# suite (#871). Test paths never start with a dash.
bashunit::main::abort_unknown_option "$1" "test"
;;
*)
raw_args[raw_args_count]="$1"
raw_args_count=$((raw_args_count + 1))
Expand Down Expand Up @@ -529,6 +546,9 @@ function bashunit::main::cmd_bench() {
bashunit::console_header::print_bench_help
exit 0
;;
-*)
bashunit::main::abort_unknown_option "$1" "bench"
;;
*)
raw_args[raw_args_count]="$1"
raw_args_count=$((raw_args_count + 1))
Expand Down
66 changes: 66 additions & 0 deletions tests/acceptance/bashunit_unknown_option_test.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
#!/usr/bin/env bash
set -euo pipefail

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

# An unmatched option used to fall through to the test-path list, so the run
# continued with the flag silently ignored and still exited 0 (#871).
function test_bashunit_fails_when_given_an_unknown_option() {
local ec=0
local output
output=$(./bashunit --env "$TEST_ENV_FILE" --parralel "$TEST_FILE" 2>&1) || ec=$?

assert_general_error "" "" "$ec"
assert_contains "--parralel" "$output"
}

function test_bashunit_reports_an_unknown_option_before_running_any_test() {
local output
output=$(./bashunit --env "$TEST_ENV_FILE" --parralel "$TEST_FILE" 2>&1 || true)

assert_not_contains "All tests passed" "$output"
}

# The value of a mistyped value-taking flag must not be mistaken for a test path.
function test_bashunit_fails_when_given_an_unknown_option_that_takes_a_value() {
local ec=0
local output
output=$(./bashunit --env "$TEST_ENV_FILE" --filterr nope "$TEST_FILE" 2>&1) || ec=$?

assert_general_error "" "" "$ec"
assert_contains "--filterr" "$output"
}

function test_bashunit_still_accepts_a_known_option_with_a_path() {
local ec=0
local output
output=$(./bashunit --env "$TEST_ENV_FILE" --no-parallel "$TEST_FILE" 2>&1) || ec=$?

assert_successful_code "" "" "$ec"
assert_contains "All tests passed" "$output"
}

function test_bashunit_bench_fails_when_given_an_unknown_option() {
local bench_dir
bench_dir="$(bashunit::temp_dir)"
printf '#!/usr/bin/env bash\nfunction bench_sample() { :; }\n' >"$bench_dir/sample_bench.sh"

local ec=0
local output
output=$(./bashunit bench --nonsense-flag "$bench_dir" 2>&1) || ec=$?

assert_general_error "" "" "$ec"
assert_contains "--nonsense-flag" "$output"
}

function test_bashunit_still_accepts_a_bare_path() {
local ec=0
local output
output=$(./bashunit --env "$TEST_ENV_FILE" "$TEST_FILE" 2>&1) || ec=$?

assert_successful_code "" "" "$ec"
assert_contains "All tests passed" "$output"
}
Loading