Releases: TypedDevs/bashunit
Release list
0.42.0
🐛 Bug Fixes
- A failing
set_up_before_script/set_upnow fails every test in the file with the hook's error, keeps the totals consistent, and lets the suite continue — a strict test file can no longer abort the whole run mid-suite (#836) - Run-mode flags (
--parallel,--simple,--strict,--retry,--seed, report paths, …) no longer leak through the environment into nested bashunit runs, so a script under test that calls bashunit gets default behavior;BASHUNIT_*=…configuration is unchanged (#834, #837) install.shfails fast: a failed download, clone, build or copy aborts with a clear error instead of reporting success, and a failed beta clone no longer runsbuild.shin the caller's directory (#840)./build.sh --verifyexits non-zero when the built binary fails the suite, and the verification run no longer crashes mid-suite from tests resolving repo paths against the build folder (#834)./bashunit benchworks again from a repository checkout (the dev entrypoint never sourcedsrc/benchmark.sh) (#834)- Snapshot placeholders (
::ignore::) now work on systems without perl; multi-line placeholders still need perl (#823) - Runs no longer leak a scratch directory under
$TMPDIR/bashunit/run/— it is removed on exit, including--version/--help, subcommands and Ctrl-C (#811) bashunit::helper::get_function_line_numberno longer disablesextdebugfor its caller (#808)--test-timeoutno longer intermittently reports a fast test as timed out; the watchdog signals by pid and skips a test that already completed
✨ Improvements
watchsubcommand no longer fails when neitherinotifywaitnorfswatchis installed — it falls back to pure-shell polling (interval viaBASHUNIT_WATCH_INTERVAL, default2s) instead of exiting (#779)- Shell tab-completion scripts for bash and zsh under
completions/(subcommands,testflags with value hints, assertion names), kept in sync by an anti-drift CI test (#778) --rerun-failed(BASHUNIT_RERUN_FAILED) replays only the previously failing tests, recorded in.bashunit/last-failed; composes with--filter/--tag/--paralleland falls back to the full suite when empty (add.bashunit/to.gitignore) (#776)- Optional nightly
coverage.ymlworkflow publishes a shields.io coverage badge from--coverageover the unit suite; schedule/manual only, never gates merges (#754) --jobs auto/-j autocaps parallel concurrency at the CPU core count (portable across Linux/macOS/BSD); the default stays unlimited (#766)
🛠️ Changes
build.shhardened: runs underset -euo pipefail, derives the embed list from the entrypoint'ssourceorder (single source of truth), guards against duplicate embeds and missing doc markers, dropseval, and gates every build behindbash -n(#834)bashunit docno longer forks anecho | sedpipe per line of the assertion docs: a single awk pass prints the same bytes in ~50ms instead of ~5s (#832)- Multi-file runs are no longer quadratic in file count; bashunit's own 63-file unit suite: ~64s -> ~22s sequential, ~26s -> ~7s parallel (#829)
- Major performance work with no behaviour change (near fork-free hot paths, cached snapshot/
--tagscans, single-pass failure rendering). On bash 3.2: 100x10assert_equals~1.50s -> ~0.76s, 500 snapshot assertions ~7.5s -> ~3.0s, 100 tagged tests ~2.92s -> ~0.68s, acceptance suite ~61s -> ~17s (#761-#764, #772-#775, #798, #801-#807, #809, #810, #813, #817) - Per-test timing now defaults to
auto(BASHUNIT_SHOW_EXECUTION_TIME=true|false|auto): shown only when the clock is fork-free, avoidingperlforks on bash 3.2;--profile/--verbose/reports still measure (seeadrs/adr-008-auto-skip-per-test-timing.md) (#765) assert_equals/assert_samefailures with multiline values now render a git word-diff below the header (requires git, opt out withBASHUNIT_NO_DIFF=true, respects--no-color); machine reports keep the raw values (#777)
👥 Contributors
Checksum
SHA256: a0e39761363d8b6876059cd5927cd4bed1b578be616c5490a8bf4102284a308c
Full Changelog: 0.41.0...0.42.0
0.41.0
✨ Improvements
--retry <n>/BASHUNIT_RETRYre-runs a failed test up to N times; passes if any attempt passes, annotates retried tests, and works with--paralleland--stop-on-failure(#737)--random-orderwith--seed <n>/BASHUNIT_SEEDrandomizes test file and function order to surface inter-test coupling; prints the seed for reproducible replay and works with--parallel(#738)--shard <index>/<total>runs a deterministic, non-overlapping subset of the test files to split a suite across parallel CI runners; composes with--parallel(#739)--report-tap <file>writes a TAP v13 report to a file (complements the streaming--output tap) (#740)--report-json <file>writes results as JSON (summary counts + per-test records); nojqdependency (#741)assert_file_permissions <mode> <file>asserts a file's octal permission mode; portable across GNU/BSDstat(#742)assert_array_length <n> <array>asserts an array has exactlynelements (#743)assert_within_delta <expected> <actual> <delta>asserts a number is within a tolerance; supports floats (#744)
🐛 Bug Fixes
watchsubcommand failed withbashunit::watch::run: command not foundin the released binary becausesrc/watch.shwas missing from the build; it is now bundled (#735)
🛠️ Changes
- Faster test execution by removing subprocess forks from hot paths (no behaviour change)
👥 Contributors
Checksum
SHA256: 146c9b1f5462633d40c377ab0548bbd1a720ce365f49ef6942621192b4d15f79
Full Changelog: 0.40.0...0.41.0
0.40.0
✨ Improvements
--test-timeout <seconds>flag andBASHUNIT_TEST_TIMEOUTenv var to abort a test that runs longer than N seconds, mark it failed and continue. Disabled by default; no externaltimeoutneeded, works on Bash 3.2+ (#721)
🐛 Bug Fixes
- A non-zero test exit no longer leaks into later tests in the same file (per-test exit code is now reset)
- Coverage now counts backslash line-continuation lines as covered (#722)
- Spying/mocking the
printfbuiltin no longer breaks coverage collection: the buffer is flushed withbuiltin printf(#724)
🛠️ Changes
- URLs now point to the new primary domain
bashunit.com(oldbashunit.typeddevs.comredirects) - Docs site deploys to GitHub Pages on the
bashunit.comcustom domain (deploy-gh-pages.yml)
Removed
- Weekly-downloads chart on the docs homepage (non-portable data source)
👥 Contributors
Checksum
SHA256: 0ee0474803b6e88e7dfa4f4c2486ea8f8e53fd8324134a9fe604ec3df8b5e72c
Full Changelog: 0.39.1...0.40.0
0.39.1
🐛 Bug Fixes
bashunit upgraderesolved the floatingv0Action tag as the latest version, breaking upgrades; it now only considers exact-version tags
👥 Contributors
Checksum
SHA256: 0cb0153ebcf7198371051332b8e8fce36c47b514eef9bb362148f404837c2e82
Full Changelog: 0.39.0...0.39.1
0.39.0
✨ Improvements
- GitHub Action
argsinput: when set, runsbashunit <args>after installing, so a workflow can install and run the suite in a single step - Floating major tag for the GitHub Action: the release process now force-moves
v0to each release, so workflows can pinTypedDevs/bashunit@v0to track the latest release within a major (#700) bashunit initnow scaffolds a.github/workflows/tests.ymlCI workflow using the official action (existing files are left untouched) (#702)--report-junit <file>flag as an alias of--log-junit, for naming parity with--report-html(#705)
🛠️ Changes
- The GitHub Action's
versioninput now defaults to the version pinned at the action ref instead oflatest, so pinning the action by SHA pins a visible bashunit version install.shnow verifies the release checksum by default (setBASHUNIT_VERIFY_CHECKSUM=falseto opt out); it soft-skips with a warning when a checksum asset is unavailable unless verification was explicitly requested (#703)--log-ghaannotations now include the failing test'sline(::error file=…,line=…), so they pin to the exact line in a pull request's "Files changed" tab (#704)
👥 Contributors
Checksum
SHA256: 37c228533b5e565147b4daaadfb2a1fe5227aa268de7dc41dd967fa85cab288f
Full Changelog: 0.38.0...0.39.0
0.38.0
✨ Improvements
- Official
TypedDevs/bashunitGitHub Action: composite install action, pinnable by commit SHA for immutable installs (version,directory,add-to-path,verify-checksuminputs;path,versionoutputs) (#695) install.shsha256 checksum verification viaBASHUNIT_VERIFY_CHECKSUM=true, validating the download against the releasechecksumasset (#695)
🐛 Bug Fixes
install.shfails loudly (non-zero exit, no stub binary) on a failed download and retries transient failures, instead of silently reporting success (#695)install.shcreates nested target directories (mkdir -p) (#695)
👥 Contributors
Checksum
SHA256: b1364d4874e61bc8cee4d9dea15844badebdbcc855d4d5b5439c9f4ae8b2204c
Full Changelog: 0.37.0...0.38.0
0.37.0
✨ Improvements
--profilereports the slowest tests (BASHUNIT_PROFILE_COUNT, default 10) (#678)- Readable snapshot diff when
gitis unavailable (#679) - Failure output shows the test
file:line(#680) .bashunitrcproject config file (#681)- Killed tests report the cause: timeout, SIGINT, SIGKILL/OOM, SIGTERM (#683)
🐛 Bug Fixes
--strictskips Bash 3.0's brokenpipefail(pipefailonly on Bash >= 3.1)bashunit watchforwards--filterand other flags correctly (#682)learnand coverage usemktemp -dfor temp directoriesparallel::cleanuprefuses torm -rfoutside*/bashunit/parallel/*
Internal
- Global-slot return pattern for hot-path helpers;
_BASHUNIT_SPY_*namespace (#674) - Windows acceptance CI: matrix shards now cover every test file (
bashunit_test.sh,coverage_*,install,mockwere silently skipped) and job labels show only the shard name
⚡ Performance
- Faster runtime-error detection: single
caseglob (#668) - Cache coverage-enabled flag in hot path (#664)
- Parallel runner uses
wait -non Bash 4.3+ instead of polling (#667) - Hot-path result helpers return via global slots, dropping a fork per call (#662)
- Drop
grep/random_strforks ingenerate_idandnormalize_variable_name(#663)
👥 Contributors
Checksum
SHA256: 18f1e8354213001b80e37c722b8520ebe26ce10fce11cb20ee471ddc96a21b11
Full Changelog: 0.36.0...0.37.0
0.36.0
🐛 Bug Fixes
bashunit upgradeexits non-zero with a clear error when the download fails (no more false success message)
✨ Improvements
--show-outputdisplays captured test output on assertion failures (#637)- npm registry distribution:
npm install -g bashunit(#244) bashunit::env::supports_colorandbashunit::io::clear_screenhelpers (#247)- LCOV reports now include
FN,FNDA,FNFandFNHfunction records, consumed bygenhtml, Codecov and Coveralls - LCOV reports now include
BRDA,BRFandBRHbranch records forif/elif/elsechains andcasepatterns (seeadrs/adr-007-branch-coverage-mvp.md) BASHUNIT_COVERAGE_SHOW_FUNCTIONS=trueadds a per-function coverage block to the text reportBASHUNIT_COVERAGE_SHOW_UNCOVERED=trueadds an "Uncovered Lines" block to the text report, with consecutive line numbers compressed into ranges
🛠️ Changes
- Docs moved into their own npm workspace under
docs/(usecd docs && npm ciormake docs/install) - Pre-commit hook skips the test suite when no shell files are staged
- ANSI escapes route through
_BASHUNIT_COLOR_*constants (#247)
⚡ Performance
- Faster coverage report generation: single-pass file scan, native bash regex, cached file stats (#636)
Internal
bashunit::runner::run_testsplit into nine named helpers (no behavior change)release.shhandlesdocs/package.jsonas a first-class release file- Structural test guards root
package.jsonagainst regaining dependencies or scripts
👥 Contributors
Checksum
SHA256: 29bffc3d492296c859640f7425a66f7ae0549e667e5265e3e84859a828edbf64
Full Changelog: 0.35.0...0.36.0
0.35.0
✨ Improvements
bashunit::spyaccepts an optional exit code or custom implementation function (#600)- Assert functions accept an optional trailing label to override the failure title (#77)
--fail-on-riskyflag andBASHUNIT_FAIL_ON_RISKYenv var treat no-assertion tests as failures (#115)--log-gha <file>flag andBASHUNIT_LOG_GHAenv var emit GitHub Actions workflow commands so failed, risky and incomplete tests show up as inline PR annotations (#280)assert_execaccepts--stdin,--stdout-contains,--stdout-not-contains,--stderr-containsand--stderr-not-containsflags to test interactive prompt commands and substring output (#301)
🛠️ Changes
- Parallel test execution is now enabled on Alpine Linux (#370)
🐛 Bug Fixes
- Dim/faint labels now render as gray (SGR 90) so keywords like
ExpectedandTests:stay colored in GitHub Actions logs (#323) - Syntax error in a test file now fails the suite instead of passing silently (#220)
--stop-on-failurenow stops on runtime errors such ascommand not foundorillegal option(#383)- Spying on
echoorprintfno longer hangs via infinite recursion (#607) - LCOV and HTML coverage reports no longer produce empty output under
set -e(#618) clock::nowhandlesEPOCHREALTIMEvalues that use a comma decimal separator- Invalid
.env.examplecoverage threshold entry; CI now copies.env.exampleto.envso config parse errors are caught - Coverage no longer counts case patterns with trailing comments (e.g.
*thing) # note) or loop terminators with redirections/pipes (e.g.done < file,done <<<"$var",done | sort) as executable lines (#634) assert_trueandassert_falsenow report empty strings as assertion failures instead of trying to execute them
👥 Contributors
Checksum
SHA256: bfe9f69bda77034234a38f26182cc34e1f7648d846dab57a513a14cf91977544
Full Changelog: 0.34.1...0.35.0
0.34.1
✨ Improvements
- Add risky test detection for tests with zero assertions (shown as warning, does not fail)
🐛 Bug Fixes
- Fix
sourceof non-existent file inset_up()silently passing all tests (#611) - Fix
set_uprunning before strict mode — unbound variables in hooks now detected with--strict - Fix
sourcefailure intear_down(),set_up_before_script(), andtear_down_after_script()silently passing - Add missing runtime error patterns: ambiguous redirect, integer expression expected, too many arguments, value too great, not a valid identifier, unexpected EOF
👥 Contributors
Checksum
SHA256: b620423b0fb201ff1c8d2c04735061cdea4237be84007348218a7e8d8522d8d0
Full Changelog: 0.34.0...0.34.1