Skip to content

Commit ba36df0

Browse files
authored
feat(runner): --fail-on-risky to fail tests with no assertions (#629)
1 parent 1bcd003 commit ba36df0

12 files changed

Lines changed: 104 additions & 2 deletions

.env.example

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ BASHUNIT_SHOW_EXECUTION_TIME= # Default: true
2323
BASHUNIT_SHOW_SKIPPED= # Default: false (show skipped test details)
2424
BASHUNIT_SHOW_INCOMPLETE= # Default: false (show incomplete test details)
2525
BASHUNIT_FAILURES_ONLY= # Default: false (only show failures)
26+
BASHUNIT_FAIL_ON_RISKY= # Default: false (treat no-assertion tests as failed)
2627
BASHUNIT_NO_COLOR= # Default: false (disable colors)
2728

2829
#───────────────────────────────────────────────────────────────────────────────

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
### Added
66
- Allow `bashunit::spy` to accept an optional exit code (e.g. `bashunit::spy thing 1`) or custom implementation function (e.g. `bashunit::spy thing mock_thing`) (#600)
77
- Allow most assert functions to accept an optional trailing label parameter to override the failure message title (e.g. `assert_same "a" "$b" "checking user name"`) (#77)
8+
- Add `--fail-on-risky` flag and `BASHUNIT_FAIL_ON_RISKY` env var to treat risky tests (no assertions) as failures (#115)
89

910
### Fixed
1011
- Fix `--stop-on-failure` not stopping when a test errors with a runtime error (e.g. `command not found`, `illegal option`) (#383)

docs/command-line.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ bashunit test tests/ --parallel --simple
7676
| `--debug [file]` | Enable shell debug mode |
7777
| `--no-output` | Suppress all output |
7878
| `--failures-only` | Only show failures |
79+
| `--fail-on-risky` | Treat risky tests (no assertions) as failures |
7980
| `--no-progress` | Suppress real-time progress, show only summary |
8081
| `--show-output` | Show test output on failure (default) |
8182
| `--no-output-on-failure` | Hide test output on failure |

docs/configuration.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -353,6 +353,22 @@ BASHUNIT_NO_OUTPUT=true
353353
```
354354
:::
355355

356+
## Fail on risky
357+
358+
> `BASHUNIT_FAIL_ON_RISKY=true|false`
359+
360+
Treat risky tests (tests with zero assertions) as failures instead of warnings. `false` by default.
361+
362+
When enabled, a test that finishes without running any assertion is reported as failed, and the run exits with a non-zero status.
363+
364+
Similar as using `--fail-on-risky` option on the command line.
365+
366+
::: code-group
367+
```bash [Example]
368+
BASHUNIT_FAIL_ON_RISKY=true
369+
```
370+
:::
371+
356372
## Failures only
357373

358374
> `BASHUNIT_FAILURES_ONLY=true|false`

src/console_header.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,7 @@ Options:
122122
--debug [file] Enable shell debug mode
123123
--no-output Suppress all output
124124
--failures-only Only show failures (suppress passed/skipped/incomplete)
125+
--fail-on-risky Treat risky tests (no assertions) as failures
125126
--no-progress Suppress real-time progress, show only final results
126127
--show-output Show test output on failure (default: enabled)
127128
--no-output-on-failure Hide test output on failure

src/env.sh

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ _BASHUNIT_DEFAULT_NO_COLOR="false"
6565
_BASHUNIT_DEFAULT_SHOW_OUTPUT_ON_FAILURE="true"
6666
_BASHUNIT_DEFAULT_NO_PROGRESS="false"
6767
_BASHUNIT_DEFAULT_OUTPUT_FORMAT=""
68+
_BASHUNIT_DEFAULT_FAIL_ON_RISKY="false"
6869

6970
: "${BASHUNIT_PARALLEL_RUN:=${PARALLEL_RUN:=$_BASHUNIT_DEFAULT_PARALLEL_RUN}}"
7071
: "${BASHUNIT_PARALLEL_JOBS:=0}"
@@ -87,6 +88,7 @@ _BASHUNIT_DEFAULT_OUTPUT_FORMAT=""
8788
: "${BASHUNIT_SHOW_OUTPUT_ON_FAILURE:=${SHOW_OUTPUT_ON_FAILURE:=$_BASHUNIT_DEFAULT_SHOW_OUTPUT_ON_FAILURE}}"
8889
: "${BASHUNIT_NO_PROGRESS:=${NO_PROGRESS:=$_BASHUNIT_DEFAULT_NO_PROGRESS}}"
8990
: "${BASHUNIT_OUTPUT_FORMAT:=${OUTPUT_FORMAT:=$_BASHUNIT_DEFAULT_OUTPUT_FORMAT}}"
91+
: "${BASHUNIT_FAIL_ON_RISKY:=${FAIL_ON_RISKY:=$_BASHUNIT_DEFAULT_FAIL_ON_RISKY}}"
9092
# Support NO_COLOR standard (https://no-color.org)
9193
if [ -n "${NO_COLOR:-}" ]; then
9294
BASHUNIT_NO_COLOR="true"
@@ -186,6 +188,10 @@ function bashunit::env::is_tap_output_enabled() {
186188
[ "$BASHUNIT_OUTPUT_FORMAT" = "tap" ]
187189
}
188190

191+
function bashunit::env::is_fail_on_risky_enabled() {
192+
[ "$BASHUNIT_FAIL_ON_RISKY" = "true" ]
193+
}
194+
189195
function bashunit::env::active_internet_connection() {
190196
if [ "${BASHUNIT_NO_NETWORK:-}" = "true" ]; then
191197
return 1

src/main.sh

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,9 @@ function bashunit::main::cmd_test() {
119119
--failures-only)
120120
export BASHUNIT_FAILURES_ONLY=true
121121
;;
122+
--fail-on-risky)
123+
export BASHUNIT_FAIL_ON_RISKY=true
124+
;;
122125
--show-output)
123126
export BASHUNIT_SHOW_OUTPUT_ON_FAILURE=true
124127
;;

src/parallel.sh

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,11 @@ function bashunit::parallel::aggregate_test_results() {
9090
# Check for risky test (zero assertions, no error)
9191
local total_for_test=$((failed + passed + skipped + incomplete + snapshot))
9292
if [ "$total_for_test" -eq 0 ] && [ "${exit_code:-0}" -eq 0 ]; then
93-
bashunit::state::add_tests_risky
93+
if bashunit::env::is_fail_on_risky_enabled; then
94+
bashunit::state::add_tests_failed
95+
else
96+
bashunit::state::add_tests_risky
97+
fi
9498
continue
9599
fi
96100

src/runner.sh

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -857,6 +857,22 @@ function bashunit::runner::run_test() {
857857

858858
# Check for risky test (zero assertions)
859859
if [ "$total_assertions" -eq 0 ]; then
860+
if bashunit::env::is_fail_on_risky_enabled; then
861+
local risky_msg="Test has no assertions (risky)"
862+
bashunit::state::add_tests_failed
863+
bashunit::console_results::print_error_test "$fn_name" "$risky_msg"
864+
bashunit::reports::add_test_failed "$test_file" "$label" "$duration" "$total_assertions" "$risky_msg"
865+
bashunit::runner::write_failure_result_output "$test_file" "$fn_name" "$risky_msg"
866+
bashunit::internal_log "Test failed (risky)" "$label"
867+
if bashunit::env::is_stop_on_failure_enabled; then
868+
if bashunit::parallel::is_enabled; then
869+
bashunit::parallel::mark_stop_on_failure
870+
else
871+
exit "$EXIT_CODE_STOP_ON_FAILURE"
872+
fi
873+
fi
874+
return
875+
fi
860876
bashunit::state::add_tests_risky
861877
if ! bashunit::env::is_failures_only_enabled; then
862878
bashunit::console_results::print_risky_test "${label}" "$duration"

tests/acceptance/bashunit_risky_test.sh

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,3 +36,51 @@ function test_bashunit_risky_test_does_not_fail() {
3636
assert_contains "risky" "$actual"
3737
assert_not_contains "failed" "$actual"
3838
}
39+
40+
function test_bashunit_fail_on_risky_flag_makes_risky_fail() {
41+
local test_file=./tests/acceptance/fixtures/test_bashunit_risky_no_assertions.sh
42+
43+
local actual_raw
44+
set +e
45+
actual_raw="$(BASHUNIT_STRICT_MODE=false ./bashunit \
46+
--no-parallel --fail-on-risky --skip-env-file --env "$TEST_ENV_FILE" "$test_file")"
47+
set -e
48+
49+
local actual
50+
actual="$(printf "%s" "$actual_raw" | strip_ansi)"
51+
52+
assert_contains "1 failed" "$actual"
53+
assert_not_contains "1 risky" "$actual"
54+
assert_general_error "$(BASHUNIT_STRICT_MODE=false ./bashunit \
55+
--no-parallel --fail-on-risky --skip-env-file --env "$TEST_ENV_FILE" "$test_file")"
56+
}
57+
58+
function test_bashunit_fail_on_risky_env_var_makes_risky_fail() {
59+
local test_file=./tests/acceptance/fixtures/test_bashunit_risky_no_assertions.sh
60+
61+
local actual_raw
62+
set +e
63+
actual_raw="$(BASHUNIT_STRICT_MODE=false BASHUNIT_FAIL_ON_RISKY=true ./bashunit \
64+
--no-parallel --skip-env-file --env "$TEST_ENV_FILE" "$test_file")"
65+
set -e
66+
67+
local actual
68+
actual="$(printf "%s" "$actual_raw" | strip_ansi)"
69+
70+
assert_contains "1 failed" "$actual"
71+
}
72+
73+
function test_bashunit_fail_on_risky_works_in_parallel() {
74+
local test_file=./tests/acceptance/fixtures/test_bashunit_risky_no_assertions.sh
75+
76+
local actual_raw
77+
set +e
78+
actual_raw="$(BASHUNIT_STRICT_MODE=false ./bashunit \
79+
--parallel --fail-on-risky --skip-env-file --env "$TEST_ENV_FILE" "$test_file")"
80+
set -e
81+
82+
local actual
83+
actual="$(printf "%s" "$actual_raw" | strip_ansi)"
84+
85+
assert_contains "1 failed" "$actual"
86+
}

0 commit comments

Comments
 (0)