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)
- Parallel test execution is now enabled on Alpine Linux (#370)
- 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
0.34.1 - 2026-03-20
- Add risky test detection for tests with zero assertions (shown as warning, does not fail)
- 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
0.34.0 - 2026-03-17
- Add
--watchmode andwatch [path]subcommand to re-run tests on file changes- Uses
inotifywaiton Linux orfswatchon macOS; clear install hint if unavailable
- Uses
- Add
--jobs Nflag to limit parallel test concurrency - Add
--tagand--exclude-tagCLI flags for filtering tests by# @tagannotations - Add TAP version 13 output format via
--output tapfor CI/CD integration - Add source context display in failure summaries showing relevant assertion lines
- Add date comparison assertions:
assert_date_equals,assert_date_before,assert_date_after,assert_date_within_range,assert_date_within_delta- Auto-detects epoch seconds, ISO 8601, space-separated datetime, and timezone offsets
- Add
assert_have_been_called_nth_withfor verifying spy arguments on the Nth invocation - Add
assert_string_matches_formatandassert_string_not_matches_formatwith format placeholders (%d,%s,%f,%i,%x,%e,%%) - Add JSON assertions:
assert_json_key_exists,assert_json_contains,assert_json_equals(requiresjq) - Add duration assertions:
assert_duration,assert_duration_less_than,assert_duration_greater_than
- Split Windows CI test jobs into parallel chunks to avoid timeouts
- Optimize clock: prioritize EPOCHREALTIME over subprocess-based fallbacks
- Cache function discovery to avoid duplicate pipeline per test file
- Reduce subshells in test execution hot path
- Batch coverage recording with in-memory buffering
- Cache
unameresult at source time to eliminate repeated subprocess forks - Replace
bcandawksubprocesses with native bash arithmetic in clock and duration formatting - Cache
base64 -wflag support at load time instead of detecting per test - Use direct variable access for assertion state instead of getter subshells in runner hot path
- Fix misleading error message for
assert_not_sameandassert_not_equalson failure (#604) - Mocking
mktempno longer breaks spy creation (#602) - JUnit XML report now conforms to the standard schema
- Remove non-standard attributes from
<testsuite>and<testcase> - Add
errors="0"attribute and<failure>/<skipped>child elements per spec skippedcount now includes both skipped and incomplete tests- Convert
timevalues from milliseconds to seconds (float) - Strip ANSI escape sequences and invalid XML control characters from failure messages
- Include actual failure messages in
<failure>body
- Remove non-standard attributes from
- Add unit tests for
env.sh,math.sh,colors.sh,test_title.sh,console_header.sh, anddoc.sh
0.33.0 - 2026-02-15
- Lower minimum Bash version requirement from 3.2 to 3.0
- Improve parallel test execution performance (30-40% faster on large test suites)
- Display test output (stdout/stderr) on failure for runtime errors
- Enabled by default; disable with
--no-output-on-failureorBASHUNIT_SHOW_OUTPUT_ON_FAILURE=false
- Enabled by default; disable with
- Add
--no-progressflag to suppress real-time progress display (Issue #503)- Also available via
BASHUNIT_NO_PROGRESS=trueenvironment variable
- Also available via
- Support
# bashunit: no-parallel-testsdirective to opt out of test-level parallelism
- Data providers now work without the
functionkeyword on test functions (Issue #586) - Install tests now pass in sandboxed/no-network environments (Issue #582)
- Parallel test execution now works correctly in strict mode (
bash -e -o pipefail)
0.32.0 - 2026-01-12
- Hook output now displays with right-aligned timing and bullet prefix (
● set_up_before_script 2.03s)
- Better code coverage HTML report
- Auto-discover coverage paths from test file names when
BASHUNIT_COVERAGE_PATHSis not settests/unit/assert_test.shautomatically trackssrc/assert.sh- Removes the need for manual
--coverage-pathsconfiguration in most cases
--coverage-report-htmlnow defaults tocoverage/htmlwhen no directory is specified
- Coverage now excludes control flow keywords (
then,else,fi,do,done,esac,;;, case patterns) from line tracking - Coverage HTML report now correctly handles namespaced functions with colons (e.g.,
bashunit::assert::equals) - Coverage data no longer lost when running
coverage_test.shalongside other tests
0.31.0 - 2025-12-19
- Display
set_up_before_scriptandtear_down_after_scriptexecution with duration- Shows "Running hook_name... done (Xs)" during test runs
- Helps identify slow setup/teardown operations
- Suppressed in failures-only and parallel modes
- Add code coverage tracking with
--coverageflag (Issue #190)- Tracks line coverage using Bash DEBUG trap mechanism
- Configurable source paths via
--coverage-paths(default:src/) - Configurable exclusions via
--coverage-exclude(default:tests/*,vendor/*,*_test.sh,*Test.sh) - LCOV format output via
--coverage-report(default:coverage/lcov.info) - HTML coverage report via
--coverage-report-html <dir>with line-by-line highlighting - Minimum coverage threshold via
--coverage-min(fails if below) - Console-only mode with
--no-coverage-report - Color-coded console output with configurable thresholds (50%/80%)
- Fix
benchcommand not working in standalone/installed bashunit (missingbenchmark.shin build) - Fix
helper::get_latest_tagreturning version with^{}suffix from annotated git tags
0.30.0 - 2025-12-14
- Display execution time in minutes format when tests run over 60 seconds (e.g., "2m 1s")
- Display individual test duration in human-readable format (ms, s, or m s) instead of always milliseconds
- Add
--failures-onlyflag to suppress passed/skipped/incomplete tests and show only failures - Add
--no-colorflag to disable ANSI color output (also supportsNO_COLORenv var per no-color.org standard) - Add multiple assertions support in standalone mode:
bashunit assert "cmd" exit_code "1" contains "error" - Add
release.shscript to automate the release process with dry-run support
- BREAKING: Rename
--preserve-envflag to--skip-env-filefor clearer semantics - BREAKING: Rename
BASHUNIT_PRESERVE_ENVenvironment variable toBASHUNIT_SKIP_ENV_FILE - Improve documentation for
--skip-env-fileclarifying that shell functions are not inherited - Add tip to Bootstrap documentation promoting it as the solution for function availability in tests
- Clarify that exit code assertions check $? instead of executing commands
- Internal flaky tests when running
--strict - Visible stdout/stderr during normal execution
set_up_before_scriptandtear_down_after_script
0.29.0 - 2025-12-08
- Add bootstrap argument passing support via
--env "file.sh arg1 arg2"orBASHUNIT_BOOTSTRAP_ARGS - Add
--preserve-envflag to skip.envloading and use shell environment only - Add
-l, --loginflag to run tests in login shell context - Add
--strictflag to enable strict shell mode (set -euo pipefail) for tests - Add
BASHUNIT_STRICT_MODEconfiguration option (default:false) - Add
-R, --run-allflag to run all assertions even when one fails - Add
BASHUNIT_STOP_ON_ASSERTION_FAILUREconfiguration option (default:true)
- BREAKING: Namespace all internal functions and variables to prevent collisions with user code
- All helper functions now use
bashunit::prefix (e.g.,skip→bashunit::skip) - All internal functions now use
bashunit::prefix (e.g.,helper::trim→bashunit::helper::trim) - All internal variables now use
_BASHUNIT_prefix (e.g.,_TESTS_PASSED→_BASHUNIT_TESTS_PASSED) - All
assert_*functions remain unchanged (public API)
- All helper functions now use
- Improve
assertcommand output: showassert <fn>instead of internal function name in failure messages - Custom assertions now display the correct test function name in failure messages
- Data providers now work when
set_up_before_scriptchanges directory - Subsequent test files now run when
set_up_before_scriptchanges directory - Catch intermediate failing commands in
set_up_before_scriptandtear_down_after_script
0.28.0 - 2025-12-01
- Add inline filter syntax to run specific tests from a file
path::function_name- filter tests by function namepath:line_number- run the test containing the specified line
- Add
--show-skippedand--show-incompleteoptions to display skipped/incomplete tests at the end
- BREAKING: Introduce subcommand-based CLI architecture
bashunit test [path]- run tests (default, backwards compatible withbashunit [path])bashunit bench [path]- run benchmarks (replaces--bench)bashunit doc [filter]- show assertion docs (replaces--doc)bashunit init [dir]- initialize project (replaces--init)bashunit learn- interactive tutorial (replaces--learn)bashunit upgrade- upgrade to latest (replaces--upgrade)
- BREAKING: Tests now stop at first assertion failure within a test function
- Matches PHPUnit and Jest default behavior
- Subsequent assertions in the same test are skipped after a failure
- Other test functions continue to run normally
- Stop executing remaining commands in
set_up/tear_downafter first failure - Count all tests as failed when
set_up_before_scriptfails
- Optimize assertion guard: use integer comparison instead of string comparison
0.27.0 - 2025-11-26
- Add
--learninteractive tutorial with 10 progressive lessons for hands-on learning - Add comprehensive "Common Patterns" documentation with real-world testing examples
- Pass arguments to mocked functions
- Fix lifecycle hooks not catching intermediate failing commands in
set_upandtear_down
- Simplify CI: use only
-latestrunners for Ubuntu and macOS, remove deprecatedmacos-13
- Optimize temp directory creation: initialize once at startup instead of per temp file
- Optimize parallel result aggregation: use bash redirection instead of spawning
tailsubprocess - Optimize state access: cache state values to avoid repeated subshell invocations
0.26.0 - 2025-11-02
- Add
assert_unsuccessful_codeassertion to check for non-zero exit codes - Fix bench tests missing test_file var
- Fix compatibility with older python versions for clock::now
- Fix
data_setwith arguments containing spaces - Eliminated redundant
declare -F | awkcalls that were happening for every test/bench file - Replaced tail and process with Bash parameter expansion
0.25.0 - 2025-10-05
- Add AI developer tools integration and guidelines
- Add Project-wide
copilot-instructions.md - Add
AGENTS.mdfor external developer tools integration - Add tasks storage policy clarifying
.tasks/(versioned) vs.task/(git-ignored)
- Add Project-wide
- Include
set_test_titlehelper in the single-file library - Fix lifecycle hooks capture-and-report flow errors
set_up,tear_down,set_up_before_script,tear_down_after_script
- Fix false negative from
assert_have_been_called_withwith pipes - Fix preservation of trailing whitespace in final argument to
data_set - Fix unbound variable error in
parse_data_provider_argswithset -u - Fix wrong assertion_failed name of test on failure
- Fix test name interpolation on failure
0.24.0 - 2025-09-14
- Improve
assert_have_been_called_withwith strict argument matching - Make Windows install clearer in the docs by adding an option for Linux/Mac and another one for Windows.
- Add data_set function for empty values and values with spaces/tabs/newlines
- Document workaround for function name collisions when sourcing scripts
- Fix
temp_dirandtemp_filedata not being cleaned up when created inset_up_before_script - Fix
/tmp/bashunit/parallelnot being cleaned after test run
0.23.0 - 2025-08-03
- Update docs mocks usage
- Skip report tracking unless a report output is requested
- Add support for
.bashtest files - Add runtime check for Bash >= 3.2
- Add fallback for
clock::nowwith seconds resolution only - Add
set_test_titleto allow custom test titles - Add
assert_execto validate exit code, stdout and stderr at once
0.22.3 - 2025-07-27
- Fix NixOS support
- Fix parallel and
compgen - Use
command -vinstead ofwhich
- Fix parallel and
0.22.2 - 2025-07-26
- Fix broken core snapshot tests
- Improve NixOS support
- Add line number to failing tests
0.22.1 - 2025-07-23
- Fix prevents writing in src dir during tests
- Fix negative widths with rpad
- Fix internal assert_line_count and call_test_functions
- Improve suffix assertion checks to use shell pattern matching
- Include calling function name in dev log output for easier debugging
- Add more internal dev log messages and prefix them with [INTERNAL]
- Toggle internal log messages with
BASHUNIT_INTERNAL_LOG=true|false
- Toggle internal log messages with
0.22.0 - 2025-07-20
- Fix process time always shows as 0 ms
- Fixed terminal width detection first tput and fall back stty
- Refactor clock optimizing the implementation used to get the time
- Add
--init [dir]option to get you started quickly - Optimize
--helpmessage - Add
--no-outputoption
0.21.0 - 2025-06-18
- Fix typo "to has been called"
- Add weekly downloads to the docs
- Fix parallel runner
- Count data providers when counting total tests
- Add benchmark feature
- Support placeholder
::ignore::in snapshots - Add project overview docs
- Improve clock performance
- Make install.sh args more flexible
- Improve Windows detection allowing parallel tests on Git Bash, MSYS and Cygwin
- Add more CI jobs for different ubuntu and macos versions
0.20.0 - 2025-06-01
- Fix asserts on test doubles in subshell
- Allow interpolating arguments in data providers output
- Deprecate
# data_providerin favor of# @data_provider - Allow
assert_have_been_called_withto check arguments of specific calls - Enable parallel tests on Windows
- Add
assert_not_called - Improve
helper::find_total_testsperformance - Added
assert_match_snapshot_ignore_colors - Optimize
runner::parse_result_sync - Fix
parse_result_paralleltemplate
0.19.1 - 2025-05-23
- Replace
#!/bin/bashwith#!/usr/bin/env bash - Usage printf with awk, which correctly handles float rounding and improves portability
0.19.0 - 2025-02-19
- Fixed false negative with
set -e - Fixed name rendered when having
test_test_* - Fixed duplicate function detection
- Fixed display test with multiple outputs in multiline
- Improved output: adding a space between each test file
- Removed
BASHUNIT_DEV_MODEin favor ofBASHUNIT_DEV_LOG - Added source file and line on global dev function
log
0.18.0 - 2024-10-16
- Added
-p|--parallelto enable running tests in parallel- Enabled only in macOS and Ubuntu
- Added
assert_file_containsandassert_file_not_contains - Added
assert_trueandassert_false - Added
BASHUNIT_DEV_LOG - Added global util functions
- current_dir
- current_filename
- caller_filename
- caller_line
- current_timestamp
- is_command_available
- random_str
- temp_file
- temp_dir
- cleanup_temp_files
- log
- Add default env values:
BASHUNIT_DEFAULT_PATH="tests"BASHUNIT_BOOTSTRAP="tests/bootstrap.sh"
- Add check that git is installed to
install.sh - Add
-vvv|--verboseto display internal details of each test - Fixed
-S|--stop-on-failurebehaviour - Improved time taken display
- Improved clean up temporal files and directories
- Improved CI test speed by running them in parallel
- Removed git dependency for stable installations
- Rename option
--verboseto--detailed- which is the default display behaviour, the opposite as
--simple
- which is the default display behaviour, the opposite as
- Added
assert_not_same
0.17.0 - 2024-10-01
- Fixed simple output for non-successful states
- Added support for Alpine (Linux Distro)
- Added optional file-path as 2nd arg to
--debugoption - Added runtime duration per test
- Added defer expressions with when using standalone assertions
- Added failing tests after running the entire suite
- Improved runtime errors handling
- Simplified total tests display on the header
- Renamed
BASHUNIT_TESTS_ENVtoBASHUNIT_BOOTSTRAP - Better handler runtime errors
- Display failing tests after running the entire suite
- Added defer expressions with
evalwhen using standalone assertions - Fixed simple output for non-successful states
- Remove deprecated assertions
- Some required dependencies now optional: perl, coreutils
- Upgrade and install script can now use
wgetifcurlis not installed - Tests can be also be timed by making use of
EPOCHREALTIMEon supported system - Switch to testing the environment of capabilities
- rather than assuming various operating systems and Linux distributions have programs installed
0.16.0 - 2024-09-15
- Fixed
clock::nowcan't locate Time when is not available - Fixed failing tests when
command not foundandunbound variable - Fixed total tests wrong number
- Update GitHub actions installation steps documentation
- Added
assert_files_equals,assert_files_not_equals - Added
BASHUNIT_TESTS_ENV
0.15.0 - 2024-09-01
- Fixed
--filter|-fto work withtest_*matching function name input. - Added assertions to log file
- Rename the current
assert_equalstoassert_same - Rename
assert_equals_ignore_colorstoassert_equalsand ignore all special chars - Data providers support multiple arguments
- Remove
multi-invokersin favor ofdata providers - Removing trailing slashes
/from the test directories naming output. - Align "Expected" and "but got" on
assert_*fails message. - Change
-vas shortcut for--version - Add
-vvvas shortcut for--verbose - Fix wrong commit id when installing beta
- Add display total tests upfront when running bashunit
- Add
BASHUNIT_suffix to all .env config keys- BASHUNIT_SHOW_HEADER
- BASHUNIT_HEADER_ASCII_ART
- BASHUNIT_SIMPLE_OUTPUT
- BASHUNIT_STOP_ON_FAILURE
- BASHUNIT_SHOW_EXECUTION_TIME
- BASHUNIT_DEFAULT_PATH
- BASHUNIT_LOG_JUNIT
- BASHUNIT_REPORT_HTML
0.14.0 - 2024-07-14
- Fix echo does not break test execution results
- Add bashunit facade to enable custom assertions
- Document how to verify the
sha256sumof the final executable - Generate checksum on build
- Enable display execution time on macOS with
SHOW_EXECUTION_TIME - Support for displaying the clock without
perl(for non-macOS) - Enable strict mode
- Add
--log-junit <log.xml>option - Add
-r|--report-html <report.html>option - Add
--debugoption - Add
dumpandddfunctions for local debugging
0.13.0 - 2024-06-23
- Allow calling assertions standalone outside tests
- Add the latest version when installing beta
- Add
assert_line_count - Add hash to the installation script when installing a beta version
- Add GitHub Actions to installation doc
0.12.0 - 2024-06-11
- Add missing assertion in non-stable versions
- Fix test with
rmcommand in macOS - Add multi-invokers; consolidate parameterized-testing documentation
- Add
fail()function - Remove all test mocks after each test case
0.11.0 - 2024-03-02
- Add
--upgradeoption to./bashunit - Remove support to deprecated
setUp,tearDown,setUpBeforeScriptandtearDownAfterScriptfunctions - Optimize test execution time
- Test functions are now run in the order they're defined in a test file
- Increase contrast of test results
0.10.1 - 2023-11-13
- Fix find tests inside folder
- Add current date on beta installation version
0.10.0 - 2023-11-09
- Installer no longer needs git
- Add
assert_contains_ignore_case - Add
assert_equals_ignore_colors - Add
assert_match_snapshot - Add
SHOW_EXECUTION_TIMEto environment config - Add docs for environment variables
- Improve data provider output
- Add .env variable
DEFAULT_PATH - Improve duplicated function names output
- Allow installing (non-stable) beta using the installer
0.9.0 - 2023-10-15
- Optimised docs Fonts (Serving directly from origin instead of Google Fonts proxy)
- Add Brew installation to docs
- Add
--helpoption - Add
-e|--envoption - Add
-S|--stop-on-failureoption - Add data_provider
- Add blog posts to the website
- Add
assert_string_not_starts_with - Add
assert_string_starts_with - Add
assert_string_ends_with - Add
assert_string_not_ends_with - Add
assert_less_than - Add
assert_less_or_equal_than - Add
assert_greater_than - Add
assert_greater_or_equal_than
0.8.0 - 2023-10-08
- Rename these functions from camelCase to snake_case:
setUp->set_uptearDown->tear_downsetUpBeforeScript->set_up_before_scripttearDownAfterScript->tear_down_after_script
- Add --version option
- Add -v|--verbose option
- Add ASCII art logo
- Find all test on a directory
- Add skip and todo functions
- Add SIMPLE_OUTPUT to
.env - Allow using
mainorlatestwhen using install.sh
0.7.0 - 2023-10-02
- Added
--simpleargument for a simpler output - Manage error when test execution fails
- Split install and build scripts
- Added these functions
mockspyassert_have_been_calledassert_have_been_called_withassert_have_been_called_timesassert_file_existsassert_file_not_existsassert_is_file_emptyassert_is_fileassert_directory_existsassert_directory_not_existsassert_is_directoryassert_is_directory_emptyassert_is_directory_not_emptyassert_is_directory_readableassert_is_directory_not_readableassert_is_directory_writableassert_is_directory_not_writable
- Rename assertions from camelCase to snake_case:
assertEquals->assert_equalsassertNotEquals->assert_not_equalsassertEmpty->assert_emptyassertNotEmpty->assert_not_emptyassertContains->assert_containsassertNotContains->assert_not_containsassertMatches->assert_matchesassertNotMatches->assert_not_matchesassertExitCode->assert_exit_codeassertSuccessfulCode->assert_successful_codeassertGeneralError->assert_general_errorassertCommandNotFound->assert_command_not_foundassertArrayContains->assert_array_containsassertArrayNotContains->assert_array_not_contains
0.6.0 - 2023-09-19
- Added
assertExitCode - Added
assertSuccessfulCode - Added
assertGeneralError - Added
assertCommandNotFound - Added
assertArrayContains - Added
assertArrayNotContains - Added
assertEmpty - Added
assertNotEmpty - Added
setUp,setUpBeforeScript,tearDownandtearDownAfterScriptfunction execution before and/or after test and/or script execution - Improved the readability of the assert by using guard clause
- Update documentation
- Add support for the static analysis on macOS
- Fix bug with watcher for the development of bashunit
- Fix error on count assertions
- Added pipeline to add contributors to the readme
- Added documentation with VitePress
- Stop runner when found duplicate test functions
0.5.0 - 2023-09-10
- Added logo
- Added
assertNotEquals - Added
assertMatches - Added
assertNotMatches - Added
make test/watchto run your test every second - Added time taken to run the test in ms (only to Linux)
- Simplified assertions over test results
- Added acceptance test to the library
- Added pre-commit to the project
- Allow parallel tests to run base on a .env configuration enabled by default
- Added static analysis tools to the deployment pipelines
- New summary output
0.4.0 - 2023-09-08
- Better output colors and symbols
- Add option
--filterto./bashunitscript- Trigger tests filtered by name
- Change the output styles
- Emojis
- Colors
- Bolds
- Added count to all test
0.3.0 - 2023-09-07
- Added
assertContains - Added
assertNotContains - Display Passed tests in green, and Failed tests in red
- Avoid stop running tests after a failing one test
0.2.0 - 2023-09-05
- Fix keeping in memory test func after running them
- Create a
./bashunitentry point - Change ROOT_DIR to BASHUNIT_ROOT_DIR
- Allow writing test with camelCase as well
- Allow running example log_test from anywhere
0.1.0 - 2023-09-04
- Added
assertEqualsfunction