✨ Improvements
assert_is_symlink,assert_is_not_symlinkandassert_symlink_toassert on a symbolic link itself, which every other filesystem assertion follows through to the target (#981)assert_trueandassert_falseaccept a command with its arguments —assert_true test -d /tmp. A single argument keeps its previous meaning (#994)- Named snapshot assertions support multiple snapshots per test; mismatches show the resolved path and
--snapshot-updatehint (#986)
🛠️ Changes
assert_true/assert_falsereportunknown command/not executableinstead of a bare exit code 127 or 126 (#982)- Core comparison assertions report missing required arguments as usage errors instead of comparing against empty values (#983)
- Performance: Literal snapshots bypass placeholder regex processing unless they contain a placeholder (about 13x faster) (#985)
- Performance:
assert_within_deltauses fixed-point arithmetic for common values, with abc/awkfallback for unsupported inputs (about 6.6x faster) (#979) - Performance: Spy assertions and call counters use builtins instead of
catand command substitutions (about 6.5x faster) (#978) - Performance:
assert_contains_ignore_caseuses Bash'snocasematchwhere available, falling back totron Bash 3.0 (about 10x faster) (#977) - Build: standalone binaries omit source comments while preserving heredoc content and source markers, reducing the current artifact by about 22% (#990)
- Internal: Split
src/runner.shandsrc/coverage.shinto focused modules with no behavior change; see ADR-010 (#924, #925)
🐛 Bug Fixes
- Snapshot placeholders no longer match anything at all without
perl; thegrepfallback treated a multi-line pattern as separate alternatives, and now usesawkover the whole value (#1002) - Snapshots resolve correctly for an absolute test path; the
./prefix made them cwd-relative, so a stray snapshot was recorded and every snapshot assertion passed (#1002) assert_falseno longer passes when the command does not exist; exit codes 127 and 126 fail both boolean assertions, because the command never ran (#982)assert_have_been_called_timesandassert_have_been_called_nth_withreport a usage error for a non-numeric count instead of leaking a rawinteger expression expected(#984)- A failing test whose output quotes a shell-error phrase is no longer also reported as a runtime error (#992)
- Runtime errors are recognised from the exit code when the diagnostic text is translated or redirected away (#998)
assert_within_deltaaccepts a leading+on any operand (#979)- Invalid
BASHUNIT_SHARD_INDEX/BASHUNIT_SHARD_TOTALvalues now fail with a clear error instead of reaching raw arithmetic or reporting no tests (#969) - Date assertions reject unparseable values instead of crashing or treating them as epoch 0 (#968)
assert_json_equalsrejects invalid JSON instead of considering two unparseable values equal (#967)- Parallel runs preserve results from same-named test files in different directories (#959)
- Coverage no longer counts variable assignments as functions or emits malformed LCOV records for assignments containing
|(#936) - The nightly coverage workflow discovers nested unit tests while excluding coverage meta-tests and fixtures (#980)
build.shdeduplicates embedded files by repository-relative path, preventing duplicate or missing modules with the same filename (#923)bashunit docno longer errors when the default bootstrap file is missing (#929)
👥 Contributors
Checksum
SHA256: 19983f26299825ff26cfbb90e6b3b6e86fc8044168191d3e8b86f615313a80a9
Full Changelog: 0.44.0...0.45.0