Skip to content

Latest commit

 

History

History
756 lines (575 loc) · 19.9 KB

File metadata and controls

756 lines (575 loc) · 19.9 KB

Command line

bashunit uses a subcommand-based CLI. Each command has its own options and behavior.

Quick Reference

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

Argument Notation

Syntax Meaning
<arg> Required - must be provided
[arg] Optional - can be omitted (uses default)

test

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

:::

Test Options

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

Standalone Assert

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'

:::

Filter

bashunit test -f|--filter "test name"

Run only tests matching the given name.

::: code-group

bashunit test tests/ --filter "user_login"

:::

Tags

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

:::

Output format

bashunit test --output <format>

Select an alternative output format. Currently supported:

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 tap
TAP version 13
# tests/example_test.sh
ok 1 - Should validate input
not ok 2 - Should handle errors
  ---
  Expected 'foo'
  but got  'bar'
  ...

1..2

:::

Watch mode

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). :::

Environment / Bootstrap

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.

Inline Filter Syntax

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. :::

Parallel

bashunit test -p|--parallel bashunit 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. :::

Jobs

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. :::

Output Style

bashunit test -s|--simple bashunit test --detailed

Choose between simple (dots) or detailed output.

::: code-group

bashunit test tests/ --simple
........

:::

::: code-group

bashunit test tests/ --detailed
Running tests/unit/example_test.sh
✓ Passed: Should validate input
✓ Passed: Should handle errors

:::

Reports

Generate test reports in different formats:

::: code-group

bashunit test tests/ --log-junit results.xml
bashunit test tests/ --report-html report.html

:::

Show Output on Failure

bashunit test --show-output bashunit 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

:::

No Progress

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-progress
bashunit - 0.34.1 | Tests: 10
Tests:      10 passed, 10 total
Assertions: 25 passed, 25 total

 All tests passed
Time taken: 1.23s

:::

Strict Mode

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

:::

Skip Env File

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 .env values with shell environment variables
  • Avoid .env interfering 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

:::

Login Shell

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

:::

Coverage

bashunit test --coverage

Enable code coverage tracking for your tests. See the Coverage documentation for comprehensive details.

::: code-group

bashunit test tests/ --coverage
bashunit 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. :::

bench

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"

:::

Bench Options

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

watch

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). :::

doc

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
--------------
...

:::

init

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 configuration
  • example_test.sh - Sample test file to get started

learn

bashunit learn

Start the interactive learning tutorial with 10 progressive lessons.

::: code-group

bashunit learn
bashunit - 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. :::

upgrade

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

:::

Global Options

These options work without a subcommand:

Version

bashunit --version

Display the current version.

::: code-group

bashunit --version
bashunit - {{ pkg.version }}

:::

Help

bashunit --help

Display help message with available commands.

::: code-group

bashunit --help
Usage: 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
<script setup> import pkg from '../package.json' </script>