Release 0.42.0
This is a big reliability release. New workflow features sit on top of a large round of correctness work — several of the fixes came out of a single audit that uncovered one problem after another in the build, the runner and the installer.
New features
Replay only what just failed with --rerun-failed
Every run now records its failing tests to .bashunit/last-failed. Passing --rerun-failed (or BASHUNIT_RERUN_FAILED=true) replays exactly those tests instead of the whole suite — a much tighter edit-run loop while you fix a handful of failures. A fully green run clears the cache, an empty cache falls back to running everything, and it composes with --filter, --tag and --parallel. Add .bashunit/ to your .gitignore (#776).
bashunit tests/ # a few tests fail
bashunit --rerun-failed tests/ # replay just thoseCap parallel concurrency with --jobs auto
--jobs auto (or -j auto) caps parallel workers at the machine's CPU core count, portable across Linux, macOS and BSD. The default stays unlimited (#766).
watch works without a file watcher installed
The watch subcommand no longer requires inotifywait or fswatch. When neither is present it falls back to pure-shell polling instead of exiting, with the interval set by BASHUNIT_WATCH_INTERVAL (default 2 seconds) (#779).
Shell tab-completion
bashunit now ships bash and zsh tab-completion scripts under completions/ — subcommands, test flags with value hints, and assertion names — kept in sync with the CLI by an anti-drift CI test (#778).
Performance
- Multi-file runs are no longer quadratic in the number of files. Each file's test functions are unset once it has been processed, so test subshells stop forking an ever-growing shell. bashunit's own 63-file unit suite dropped from ~64s to ~22s sequential, and ~26s to ~7s in parallel (#829).
bashunit docis ~100× faster. It used to fork anecho | sedpipe per line of the assertion docs; a singleawkpass now prints the same output in about 50ms instead of ~5s (#832).- More broadly, the hot paths are now near fork-free, snapshot and
--tagscans are cached, and failure rendering is single-pass. On Bash 3.2: 100×10assert_equals~1.50s → ~0.76s, 500 snapshot assertions ~7.5s → ~3.0s.
Bug fixes
- Failing lifecycle hooks are now consistent. A failing
set_up_before_scriptorset_upused to behave three different ways depending on the shape of the hook and the Bash version — sometimes silently ignored, sometimes counted wrong with no message. Now every test in the file is marked failed with the hook's error, the totals stay consistent, and the suite continues to the next file. A strict test file can no longer abort the whole run mid-suite (#836). - Run-mode flags no longer leak into nested runs. Flags like
--parallel,--simple,--strict,--retry,--seedand the report paths were exported into the environment, so a script under test that itself called bashunit silently inherited the parent's configuration. They are now this-process-only;BASHUNIT_*=…configuration is unchanged (#834, #837). install.shfails fast. A failed download, clone, build or copy now aborts with a clear error instead of reporting success — a failed beta clone could previously run the build in the caller's directory (#840)../build.sh --verifyactually gates now, exiting non-zero when the built binary fails the suite, and the verification run no longer crashes mid-suite (#834)../bashunit benchworks again when run from a repository checkout (#834).- Snapshot placeholders (
::ignore::) now work on systems without perl; multi-line placeholders still need it (#823). - Runs no longer leak a scratch directory under
$TMPDIR/bashunit/run/— it is cleaned up on exit, including for--version/--help, subcommands and Ctrl-C (#811). --test-timeoutno longer occasionally reports a fast test as timed out.
Changes
build.shwas hardened: it runs underset -euo pipefail, derives the bundled file list from the entrypoint's ownsourceorder (one source of truth), guards against duplicate embeds and missing doc markers, dropseval, and gates every build behind abash -nsyntax check (#834).- Per-test timing now defaults to
auto: shown only when the shell has a fork-free clock, so a plain run stays fast on Bash 3.2.--profile,--verboseand the reports always measure (#765). assert_equals/assert_samefailures with multiline values now render a git word-diff below the header (opt out withBASHUNIT_NO_DIFF=true) (#777).
See the full changelog for 0.42.0 on GitHub.