From f04fc9a12a4ecd068068b30b885216534cf2b0c5 Mon Sep 17 00:00:00 2001 From: Chemaclass Date: Thu, 13 Aug 2026 22:50:43 +0200 Subject: [PATCH] docs(assert): document how to assert a captured exit code assert_successful_code, assert_unsuccessful_code, assert_general_error and assert_command_not_found read $?. Under set -e -- which --strict turns on for every test -- that cannot be used directly: the non-zero exit aborts the test before the assertion runs, so the code must be captured, and capturing it sets $? to zero. Both assert_general_error assert_general_error "$code" then assert the wrong thing silently, the second being the natural spelling. The working form takes the code as the third argument, and was undocumented. Appended at the end of each section rather than after the intro line: the `bashunit doc` renderer truncates a section, so inserting earlier dropped the existing assert_exec tip from CLI output. With the block at the end the doc snapshot is byte-identical. Not changing $1 to mean the captured code: assert_general_error "$(cmd)" is an established idiom here that relies on $?, and it would silently change meaning whenever that output is a bare integer. Closes #1169 --- docs/assertions.md | 76 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 76 insertions(+) diff --git a/docs/assertions.md b/docs/assertions.md index 8abf9045e..9eeac0baf 100644 --- a/docs/assertions.md +++ b/docs/assertions.md @@ -837,6 +837,25 @@ function test_failure() { ``` ::: +::: warning Under `set -e`, pass the code as the third argument +A non-zero exit aborts the test before the assertion runs, so the code has to +be captured first — and capturing it sets `$?` to zero: + +```bash +local code=0 +some_command || code=$? + +assert_successful_code # reads $? — the assignment's 0 +assert_successful_code "$code" # the first argument is ignored, same result + +assert_successful_code "" "" "$code" # correct: read from the third argument +``` + +`assert_exit_code` takes a captured code the same way, but its first argument +is the *expected* code: `assert_exit_code 7 "" "$code"`. +::: + + ## assert_unsuccessful_code > `assert_unsuccessful_code` @@ -882,6 +901,25 @@ function test_failure() { ``` ::: +::: warning Under `set -e`, pass the code as the third argument +A non-zero exit aborts the test before the assertion runs, so the code has to +be captured first — and capturing it sets `$?` to zero: + +```bash +local code=0 +some_command || code=$? + +assert_unsuccessful_code # reads $? — the assignment's 0 +assert_unsuccessful_code "$code" # the first argument is ignored, same result + +assert_unsuccessful_code "" "" "$code" # correct: read from the third argument +``` + +`assert_exit_code` takes a captured code the same way, but its first argument +is the *expected* code: `assert_exit_code 7 "" "$code"`. +::: + + ## assert_general_error > `assert_general_error` @@ -927,6 +965,25 @@ function test_failure() { ``` ::: +::: warning Under `set -e`, pass the code as the third argument +A non-zero exit aborts the test before the assertion runs, so the code has to +be captured first — and capturing it sets `$?` to zero: + +```bash +local code=0 +some_command || code=$? + +assert_general_error # reads $? — the assignment's 0 +assert_general_error "$code" # the first argument is ignored, same result + +assert_general_error "" "" "$code" # correct: read from the third argument +``` + +`assert_exit_code` takes a captured code the same way, but its first argument +is the *expected* code: `assert_exit_code 7 "" "$code"`. +::: + + ## assert_command_available > `assert_command_available "command"` @@ -985,6 +1042,25 @@ function test_failure_with_existing_command() { ``` ::: +::: warning Under `set -e`, pass the code as the third argument +A non-zero exit aborts the test before the assertion runs, so the code has to +be captured first — and capturing it sets `$?` to zero: + +```bash +local code=0 +some_command || code=$? + +assert_command_not_found # reads $? — the assignment's 0 +assert_command_not_found "$code" # the first argument is ignored, same result + +assert_command_not_found "" "" "$code" # correct: read from the third argument +``` + +`assert_exit_code` takes a captured code the same way, but its first argument +is the *expected* code: `assert_exit_code 7 "" "$code"`. +::: + + ## assert_file_exists > `assert_file_exists "file"`