bashunit uses a subcommand-based CLI. Each command has its own options and behavior.
bashunit test [path] [options] # Run tests (default)
bashunit bench [path] [options] # Run benchmarks
bashunit watch [path] [options] # Watch files, re-run tests on change
bashunit assert <fn> <args> # Run standalone assertion
bashunit doc [filter] # Show assertion documentation
bashunit init [dir] # Initialize test directory
bashunit learn # Interactive tutorial
bashunit upgrade # Upgrade to latest version
bashunit --help # Show help
bashunit --version # Show version| Syntax | Meaning |
|---|---|
<arg> |
Required - must be provided |
[arg] |
Optional - can be omitted (uses default) |
bashunit test [path] [options]bashunit [path] [options]
Run test files. This is the default command - you can omit test for convenience.
::: code-group
# Run all tests in directory
bashunit test tests/
# Shorthand (same as above)
bashunit tests/
# Run specific test file
bashunit test tests/unit/example_test.sh
# Run with filter
bashunit test tests/ --filter "user"
# Run with options
bashunit test tests/ --parallel --simple:::
| Option | Description |
|---|---|
-a, --assert <fn> <args> |
Run a standalone assert function |
-e, --env, --boot <file> |
Load custom env/bootstrap file (supports args) |
-f, --filter <name> |
Only run tests matching name |
--tag <name> |
Only run tests with matching @tag (repeatable) |
--exclude-tag <name> |
Skip tests with matching @tag (repeatable) |
--output <format> |
Output format (tap for TAP version 13) |
-w, --watch |
Watch files and re-run tests on change |
--log-junit <file> |
Write JUnit XML report |
-j, --jobs <N> |
Run tests in parallel with max N concurrent jobs |
-p, --parallel |
Run tests in parallel |
--no-parallel |
Run tests sequentially |
-r, --report-html <file> |
Write HTML report |
-R, --run-all |
Run all assertions (don't stop on first failure) |
-s, --simple |
Simple output (dots) |
--detailed |
Detailed output (default) |
-S, --stop-on-failure |
Stop on first failure |
--show-skipped |
Show skipped tests summary at end |
--show-incomplete |
Show incomplete tests summary at end |
-vvv, --verbose |
Show execution details |
--debug [file] |
Enable shell debug mode |
--no-output |
Suppress all output |
--failures-only |
Only show failures |
--no-progress |
Suppress real-time progress, show only summary |
--show-output |
Show test output on failure (default) |
--no-output-on-failure |
Hide test output on failure |
--strict |
Enable strict shell mode |
--skip-env-file |
Skip .env loading, use shell environment only |
-l, --login |
Run tests in login shell context |
--no-color |
Disable colored output |
--coverage |
Enable code coverage tracking |
--coverage-paths <paths> |
Paths to track (default: auto-discover) |
--coverage-exclude <pat> |
Exclusion patterns |
--coverage-report [file] |
LCOV output path (default: coverage/lcov.info) |
--coverage-report-html [dir] |
Generate HTML report (default: coverage/html) |
--coverage-min <percent> |
Minimum coverage threshold |
--no-coverage-report |
Console output only, no LCOV file |
bashunit test -a|--assert function "arg1" "arg2"
Run a core assert function standalone without a test context.
::: code-group
bashunit test --assert equals "foo" "bar"✗ Failed: Main::exec assert
Expected 'foo'
but got 'bar'
:::
bashunit test -f|--filter "test name"
Run only tests matching the given name.
::: code-group
bashunit test tests/ --filter "user_login":::
bashunit test --tag <name>bashunit test --exclude-tag <name>
Filter tests by # @tag annotations. Both flags are repeatable. --tag uses OR
logic across names; --exclude-tag wins when a test matches both.
::: code-group
# @tag slow
function test_heavy_computation() {
...
}
# @tag integration
function test_api_call() {
...
}bashunit test tests/ --tag slow
bashunit test tests/ --tag slow --tag integration
bashunit test tests/ --exclude-tag integration:::
bashunit test --output <format>
Select an alternative output format. Currently supported:
tap— TAP version 13 for CI/CD integrations.
The TAP version 13 header comes first, each test file is announced via a
# <path> diagnostic line, each test emits an ok <n> - <name> or
not ok <n> - <name> line (failures include a YAML --- ... ... block with
expected/actual), and the 1..N plan line closes the report.
::: code-group
bashunit test tests/ --output tapTAP version 13
# tests/example_test.sh
ok 1 - Should validate input
not ok 2 - Should handle errors
---
Expected 'foo'
but got 'bar'
...
1..2
:::
bashunit test -w|--watch
Watch the test path (plus src/ if present) and re-run tests when files change.
The -w/--watch flag uses a lightweight checksum polling loop that works
on any system — no external tools required.
::: code-group
bashunit test tests/ --watch:::
::: tip
For file-event-driven watching (no polling), use the dedicated
watch subcommand, which relies on inotifywait (Linux) or
fswatch (macOS).
:::
bashunit test -e|--env|--boot <file>bashunit test --env "file arg1 arg2"
Load a custom environment or bootstrap file before running tests.
::: code-group
bashunit test --env tests/bootstrap.sh tests/# Pass arguments to the bootstrap file
bashunit test --env "tests/bootstrap.sh staging verbose" tests/:::
Arguments are available as positional parameters ($1, $2, etc.) in your bootstrap script:
#!/usr/bin/env bash
# tests/bootstrap.sh
ENVIRONMENT="${1:-production}"
VERBOSE="${2:-false}"
export API_URL="https://${ENVIRONMENT}.api.example.com"You can also set arguments via environment variable:
BASHUNIT_BOOTSTRAP_ARGS="staging verbose" bashunit test tests/See Configuration: Bootstrap for more details.
You can also specify a filter directly in the file path using :: or :line syntax:
Run a specific test by function name:
bashunit test path::function_name
::: code-group
bashunit test tests/unit/example_test.sh::test_user_login# Runs all tests containing "user" in their name
bashunit test tests/unit/example_test.sh::user:::
Run the test at a specific line number:
bashunit test path:line_number
This is useful when jumping to a test from your editor or IDE.
::: code-group
bashunit test tests/unit/example_test.sh:42:::
::: tip The line number syntax finds the test function that contains the specified line. If the line is before any test function, an error is shown. :::
bashunit test -p|--parallelbashunit test --no-parallel
Run tests in parallel or sequentially. Sequential is the default.
In parallel mode, both test files and individual test functions run concurrently for maximum performance.
::: warning Parallel mode is supported on macOS, Ubuntu, and Windows. On other systems (like Alpine Linux) the option is automatically disabled due to inconsistent results. :::
::: tip Opt-out of test-level parallelism If a test file has shared state or race conditions, you can disable test-level parallelism by adding this directive as the second line:
#!/usr/bin/env bash
# bashunit: no-parallel-tests
function test_with_shared_state() {
# This test will not run in parallel with others in this file
}The file will still run in parallel with other files, but tests within it will run sequentially. :::
bashunit test -j|--jobs <N>
Run tests in parallel with a maximum of N concurrent jobs. This implicitly enables parallel mode.
Use this to limit CPU usage on CI or machines with constrained resources.
::: code-group
bashunit test tests/ --jobs 4:::
::: tip
--jobs 0 (the default) means unlimited concurrency, which is equivalent to
--parallel.
:::
bashunit test -s|--simplebashunit test --detailed
Choose between simple (dots) or detailed output.
::: code-group
bashunit test tests/ --simple........
:::
::: code-group
bashunit test tests/ --detailedRunning tests/unit/example_test.sh
✓ Passed: Should validate input
✓ Passed: Should handle errors
:::
Generate test reports in different formats:
::: code-group
bashunit test tests/ --log-junit results.xmlbashunit test tests/ --report-html report.html:::
bashunit test --show-outputbashunit test --no-output-on-failure
Control whether test output (stdout/stderr) is displayed when tests fail with runtime errors.
By default (--show-output), when a test fails due to a runtime error (command not found,
unbound variable, permission denied, etc.), bashunit displays the captured output in an
"Output:" section to help debug the failure.
Use --no-output-on-failure to suppress this output.
::: code-group
bashunit test tests/ --no-output-on-failure✗ Error: My test function
command not found
Output:
Debug: Setting up test
Running command: my_command
/path/to/test.sh: line 5: my_command: command not found
:::
bashunit test --no-progress
Suppress real-time progress display during test execution, showing only the final summary.
When enabled, bashunit hides:
- Per-test output (pass/fail messages or dots)
- File headers ("Running tests/...")
- Hook completion messages
- Spinner during parallel execution
The final summary with test counts and results is still displayed.
This is useful for:
- CI/CD pipelines where streaming output causes issues
- Log-restricted environments
- Reducing output noise when only the final result matters
::: code-group
bashunit test tests/ --no-progressbashunit - 0.34.1 | Tests: 10
Tests: 10 passed, 10 total
Assertions: 25 passed, 25 total
All tests passed
Time taken: 1.23s
:::
bashunit test --strict
Enable strict shell mode (set -euo pipefail) for test execution.
By default, tests run in permissive mode which allows:
- Unset variables without errors
- Non-zero return codes from commands
- Pipe failures to be ignored
With --strict, your tests run with bash strict mode enabled, catching
potential issues like uninitialized variables and unchecked command failures.
::: code-group
bashunit test tests/ --strict:::
bashunit test --skip-env-file
Skip loading the .env file and use the current shell environment only.
By default, bashunit loads variables from .env which can override environment
variables set in your shell. Use --skip-env-file when you want to:
- Run in CI/CD where environment is pre-configured
- Override
.envvalues with shell environment variables - Avoid
.envinterfering with your current settings
::: warning Important Only environment variables are inherited from the parent shell. Shell functions and aliases are NOT available in tests due to bashunit's subshell architecture. Use a bootstrap file to define functions needed by your tests. :::
::: code-group
BASHUNIT_SIMPLE_OUTPUT=true ./bashunit test tests/ --skip-env-file:::
bashunit test -l|--login
Run tests in a login shell context by sourcing profile files.
When enabled, bashunit sources the following files (if they exist) before each test:
/etc/profile~/.bash_profile~/.bash_login~/.profile
Use this when your tests depend on environment setup from login shell profiles, such as:
- PATH modifications
- Shell functions defined in
.bash_profile - Environment variables set during login
::: code-group
bashunit test tests/ --login:::
bashunit test --coverage
Enable code coverage tracking for your tests. See the Coverage documentation for comprehensive details.
::: code-group
bashunit test tests/ --coveragebashunit test tests/ --coverage --coverage-paths src/,lib/ --coverage-min 80:::
Coverage options:
| Option | Description |
|---|---|
--coverage |
Enable coverage tracking |
--coverage-paths <paths> |
Comma-separated paths to track (default: auto-discover from test files) |
--coverage-exclude <patterns> |
Comma-separated patterns to exclude (default: tests/*,vendor/*,*_test.sh) |
--coverage-report [file] |
LCOV output file path (default: coverage/lcov.info) |
--coverage-report-html [dir] |
Generate HTML report (default: coverage/html) |
--coverage-min <percent> |
Minimum coverage percentage; fails if below |
--no-coverage-report |
Show console report only, don't generate LCOV file |
::: tip
Coverage works with parallel execution (-p). Each worker tracks coverage independently, and results are aggregated before reporting.
:::
bashunit bench [path] [options]
Run benchmark functions prefixed with bench_. Use @revs and @its comments to control revolutions and iterations.
::: code-group
# Run all benchmarks
bashunit bench
# Run specific benchmark file
bashunit bench benchmarks/parser_bench.sh
# With filter
bashunit bench --filter "parse":::
| Option | Description |
|---|---|
-e, --env, --boot <file> |
Load custom env/bootstrap file (supports args) |
-f, --filter <name> |
Only run benchmarks matching name |
-s, --simple |
Simple output |
--detailed |
Detailed output (default) |
-vvv, --verbose |
Show execution details |
--skip-env-file |
Skip .env loading, use shell environment only |
-l, --login |
Run in login shell context |
bashunit watch [path] [test-options]
Dedicated watch subcommand that uses OS file-event notifications (no
polling) to re-run tests as soon as a .sh file changes. Any option accepted
by bashunit test is also accepted here.
::: code-group
# Watch current directory
bashunit watch
# Watch the tests/ directory
bashunit watch tests/
# Watch and filter by name
bashunit watch tests/ --filter user
# Watch with simple output
bashunit watch tests/ --simple:::
::: warning Requirements
- Linux:
inotifywait(sudo apt install inotify-tools) - macOS:
fswatch(brew install fswatch)
If the required tool is not installed, bashunit prints a clear installation hint and exits with a non-zero code. :::
::: tip
If you cannot install inotifywait or fswatch, use the portable
-w/--watch flag on bashunit test instead (uses polling).
:::
bashunit doc [filter]
Display documentation for assertion functions.
::: code-group
# Show all assertions
bashunit doc
# Filter by name
bashunit doc equals
# Show file-related assertions
bashunit doc file## assert_equals
--------------
> `assert_equals "expected" "actual"`
Reports an error if the two variables are not equal...
## assert_not_equals
--------------
...
:::
bashunit init [directory]
Initialize a new test directory with sample files.
::: code-group
# Create tests/ directory (default)
bashunit init
# Create custom directory
bashunit init spec> bashunit initialized in tests
:::
Creates:
bootstrap.sh- Setup file for test configurationexample_test.sh- Sample test file to get started
bashunit learn
Start the interactive learning tutorial with 10 progressive lessons.
::: code-group
bashunit learnbashunit - Interactive Learning
Choose a lesson:
1. Basics - Your First Test
2. Assertions - Testing Different Conditions
3. Setup & Teardown - Managing Test Lifecycle
4. Testing Functions - Unit Testing Patterns
5. Testing Scripts - Integration Testing
6. Mocking - Test Doubles and Mocks
7. Spies - Verifying Function Calls
8. Data Providers - Parameterized Tests
9. Exit Codes - Testing Success and Failure
10. Complete Challenge - Real World Scenario
p. Show Progress
r. Reset Progress
q. Quit
Enter your choice:
:::
::: tip Perfect for new users getting started with bashunit. :::
bashunit upgrade
Upgrade bashunit to the latest version.
::: code-group
bashunit upgrade> Upgrading bashunit to latest version
> bashunit upgraded successfully to latest version 0.34.1
:::
These options work without a subcommand:
bashunit --version
Display the current version.
::: code-group
bashunit --versionbashunit - {{ pkg.version }}
:::
bashunit --help
Display help message with available commands.
::: code-group
bashunit --helpUsage: bashunit <command> [arguments] [options]
Commands:
test [path] Run tests (default command)
bench [path] Run benchmarks
assert <fn> <args> Run standalone assertion
doc [filter] Display assertion documentation
init [dir] Initialize a new test directory
learn Start interactive tutorial
watch [path] Watch files and re-run tests on change
upgrade Upgrade bashunit to latest version
Global Options:
-h, --help Show this help message
-v, --version Display the current version
Run 'bashunit <command> --help' for command-specific options.
:::
Each subcommand also supports --help:
bashunit test --help
bashunit bench --help
bashunit watch --help
bashunit doc --help