feat(assert): add assert_command_available - #1033
Conversation
1b18889 to
126b369
Compare
|
Reviewed and pushed two follow-up commits to this branch. Blocker fixed (f03f8db). Same class of regression already pinned for Also in that commit:
Docs (01f3442). Added the name to the "Exit codes" bullet in The Local gate green: full suite, |
01f3442 to
9d89d1c
Compare
bashunit::assertion_failed is the facade for user-defined custom assertions; it adds a stack frame on top of bashunit::assert::fail_with, whose label fallback compensates for exactly one. An assertion failing with no test_* frame on the stack (e.g. inside set_up) was therefore labelled "Bashunit::assertion failed" instead of "Assert command available" -- the same class of regression already pinned for bashunit::assert::label in bashunit_hook_failure_test.sh. Call bashunit::assert::fail_with / bashunit::state::add_assertions_passed directly like every other assertion in the file, and cover the facade frame in bashunit_hook_failure_test.sh. Also: - drop the trailing space in the failure condition, which doubled the space before the actual value - accept the conventional label override as $2 - replace the assert_command_not_found "symmetry" test, which only restated that a missing command exits 127, with a counter-movement test and a custom-label test - reword the docs link so `bashunit doc` renders it like the others Claude-Session: https://claude.ai/code/session_01VdeSjVXBGPWELdq5iDdczY
The skill file already bumped the assertion count but left the new name out of the "Exit codes" bullet, and that list is what an agent reads to avoid inventing assertion names. Claude-Session: https://claude.ai/code/session_01VdeSjVXBGPWELdq5iDdczY
…rage - trim the doc block to the house Arguments form; the note about calling fail_with instead of the assertion_failed facade duplicated fail_with's own documented contract - name the local `command`, matching the documented signature and the doubles modules - drop the hook-failure acceptance test: it spends a full CLI run pinning the facade frame depth for an assertion that never routes through the facade, and the two existing guards already pin fail_with's depth generically - build the arity probe's argument list from the required count instead of branching on it, so a new arity needs no new branch - assert the inverse relationship with assert_command_not_found in both directions (issue acceptance criterion)
9d89d1c to
8b3c115
Compare
Chemaclass
left a comment
There was a problem hiding this comment.
Reviewed after rebasing onto main and refactoring on top of the original commits.
Blockers: none.
Checked
- Bash 3.0+: no
declare -A,[[ ]],${var,,}, negative indexing or&>>. The one new array (argsinarity_test.sh) is appended witharr[${#arr[@]}]=and expanded as"${args[@]+"${args[@]}"}", so the empty case does not tripset -uon Bash 3.x — verified with/bin/bash ./bashunit --stricton 3.2.57. - Availability has one definition: the assertion delegates to
bashunit::is_command_available, so builtins and shell functions behave identically to the helper, and the command is resolved rather than executed. - Failure output follows the
fail_withvoice of the neighbouring file/folder assertions and names the command. Custom label goes in$2, matching the rest ofsrc/assert/core.sh. - Missing argument is a usage error (exit 2), per the #983 precedent, and the arity provider covers it. Mutation check: relaxing the guard to
-lt 0turns the arity test red, so the case is real. - Docs,
bashunit docsnapshot, both completion scripts, the agent skill catalogue, the assertion counts and the changelog are all updated../build.shplustests/acceptance/bashunit_test.shconfirm the built binary's docs match dev docs. make saandmake lintare clean; full and--parallelsuites pass locally.
Nit, not acted on: Expected 'jq' / to be available but 'not found' reads a little stiff, but it is the same shape as to exist but 'do not exist' in src/assert/files.sh, so it stays consistent with the family.
Approving; merging once every CI job is green.
Background
Related #1027
bashunit already exposes
bashunit::is_command_available, but users could not assert that a required command resolves with a diagnostic that names the missing command. The workaround —assert_true "bashunit::is_command_available jq"— reported the failure as a boolean over an opaque string.Changes
assert_command_available <command>on top of the existing availability helper, so there is one definition of "available". A missing argument is a usage error (feat(assert): a missing argument reports a failed assertion, not a usage error #983 precedent); an optional second argument overrides the failure label, matching the rest ofsrc/assert/core.shassert_command_not_foundin both directionstests/unit/assert/arity_test.sh: it now builds the "one argument short" call from the declared arity instead of branching on it, so the 1-argument case needed no new branchbashunit docsnapshot, both completion scripts, the changelog, the agent skill catalogue and the assertion countsMaintainer notes
Rebased onto
main(conflict was the## Unreleasedchangelog block against #1007, #1008 and #1035) and refactored on top of the contributor's commits:Arguments:form — the note about callingbashunit::assert::fail_withinstead of thebashunit::assertion_failedfacade repeatedfail_with's own documented contracttests/acceptance/bashunit_hook_failure_test.shcase. It spent a full CLI run pinning the facade's frame depth for an assertion that never routes through the facade, and the two existing guards in that file already pinfail_with's depth genericallyassert_command_availableandassert_command_not_foundnever agree about the same command)Validation
./bashunit tests/— 1786 passed, 13 skipped, 4 incomplete, 2 snapshot./bashunit --parallel tests/— 1747 passed, 11 skipped, 4 incomplete, 2 snapshot/bin/bash ./bashunit --strict tests/unit/assert/arity_test.shon Bash 3.2 — exercises the empty-arrayset -uguard in the new arity loopmake saandmake lint— OK./build.sh+tests/acceptance/bashunit_test.sh— built binary docs match dev docs-lt 0turns the arity test red, so it is not vacuousChecklist
CHANGELOG.mdto reflect the new feature or fix