diff --git a/CHANGELOG.md b/CHANGELOG.md index 3f949b64..2f388806 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,11 +3,14 @@ ## Unreleased ### Added +- Add `--jobs N` flag to limit parallel test concurrency (e.g., `--jobs 4`) +- Add `--watch` mode to automatically re-run tests when files change - Add `watch [path]` subcommand to re-run tests automatically on file changes - Uses `inotifywait` on Linux (via `inotify-tools`) or `fswatch` on macOS - Falls back with a clear install hint if neither tool is available - Accepts optional path argument (defaults to current directory) - +- Add source context display in failure summaries showing relevant assertion lines +- Add TAP version 13 output format via `--output tap` for CI/CD integration - 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 - Mixed formats supported in the same assertion call diff --git a/docs/command-line.md b/docs/command-line.md index 1913525e..d2c3d73c 100644 --- a/docs/command-line.md +++ b/docs/command-line.md @@ -56,6 +56,7 @@ bashunit test tests/ --parallel --simple | `-e, --env, --boot ` | Load custom env/bootstrap file (supports args) | | `-f, --filter ` | Only run tests matching name | | `--log-junit ` | Write JUnit XML report | +| `-j, --jobs ` | Run tests in parallel with max N concurrent jobs | | `-p, --parallel` | Run tests in parallel | | `--no-parallel` | Run tests sequentially | | `-r, --report-html ` | Write HTML report | @@ -214,6 +215,26 @@ The file will still run in parallel with other files, but tests within it will run sequentially. ::: +### Jobs + +> `bashunit test -j|--jobs ` + +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 +```bash [Example] +bashunit test tests/ --jobs 4 +``` +::: + +::: tip +`--jobs 0` (the default) means unlimited concurrency, which is equivalent to +`--parallel`. +::: + ### Output Style > `bashunit test -s|--simple` diff --git a/docs/configuration.md b/docs/configuration.md index 7cebab4f..36b01ef7 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -76,6 +76,13 @@ systems bashunit forces sequential execution to avoid inconsistent results. Similar as using `-p|--parallel` option on the [command line](/command-line#parallel). +## Parallel Jobs + +> `BASHUNIT_PARALLEL_JOBS=` + +Limits the number of concurrent jobs when running in parallel mode. Set to `0` (default) for unlimited concurrency. + +Similar as using `-j|--jobs` option on the [command line](/command-line#jobs). ## Stop on failure diff --git a/src/console_header.sh b/src/console_header.sh index 03502abb..1e008d5f 100644 --- a/src/console_header.sh +++ b/src/console_header.sh @@ -109,11 +109,13 @@ Options: --tag Only run tests with matching @tag (repeatable, OR logic) --exclude-tag Skip tests with matching @tag (repeatable, exclude wins) --log-junit Write JUnit XML report - -p, --parallel Run tests in parallel + -j, --jobs Run tests in parallel with max N concurrent jobs + -p, --parallel Run tests in parallel (unlimited concurrency) --no-parallel Run tests sequentially -r, --report-html Write HTML report -s, --simple Simple output (dots) --detailed Detailed output (default) + --output Output format: tap (TAP version 13) -R, --run-all Run all assertions (don't stop on first failure) -S, --stop-on-failure Stop on first failure -vvv, --verbose Show execution details @@ -126,6 +128,7 @@ Options: --strict Enable strict shell mode (set -euo pipefail) --skip-env-file Skip .env loading, use shell environment only -l, --login Run tests in login shell context + -w, --watch Watch for changes and re-run tests --no-color Disable colored output (honors NO_COLOR env var) -h, --help Show this help message diff --git a/src/console_results.sh b/src/console_results.sh index ab96cd26..ff8b08ec 100644 --- a/src/console_results.sh +++ b/src/console_results.sh @@ -12,6 +12,14 @@ function bashunit::console_results::render_result() { return 1 fi + if bashunit::env::is_tap_output_enabled; then + printf "1..%d\n" "$_BASHUNIT_TOTAL_TESTS_COUNT" + if [[ $_BASHUNIT_TESTS_FAILED -gt 0 ]]; then + return 1 + fi + return 0 + fi + if bashunit::env::is_simple_output_enabled; then printf "\n\n" fi @@ -176,6 +184,10 @@ function bashunit::console_results::print_hook_completed() { return fi + if bashunit::env::is_tap_output_enabled; then + return + fi + if bashunit::parallel::is_enabled; then return fi diff --git a/src/env.sh b/src/env.sh index 4b9f9f61..9948fa0d 100644 --- a/src/env.sh +++ b/src/env.sh @@ -64,8 +64,10 @@ _BASHUNIT_DEFAULT_FAILURES_ONLY="false" _BASHUNIT_DEFAULT_NO_COLOR="false" _BASHUNIT_DEFAULT_SHOW_OUTPUT_ON_FAILURE="true" _BASHUNIT_DEFAULT_NO_PROGRESS="false" +_BASHUNIT_DEFAULT_OUTPUT_FORMAT="" : "${BASHUNIT_PARALLEL_RUN:=${PARALLEL_RUN:=$_BASHUNIT_DEFAULT_PARALLEL_RUN}}" +: "${BASHUNIT_PARALLEL_JOBS:=0}" : "${BASHUNIT_SHOW_HEADER:=${SHOW_HEADER:=$_BASHUNIT_DEFAULT_SHOW_HEADER}}" : "${BASHUNIT_HEADER_ASCII_ART:=${HEADER_ASCII_ART:=$_BASHUNIT_DEFAULT_HEADER_ASCII_ART}}" : "${BASHUNIT_SIMPLE_OUTPUT:=${SIMPLE_OUTPUT:=$_BASHUNIT_DEFAULT_SIMPLE_OUTPUT}}" @@ -84,6 +86,7 @@ _BASHUNIT_DEFAULT_NO_PROGRESS="false" : "${BASHUNIT_FAILURES_ONLY:=${FAILURES_ONLY:=$_BASHUNIT_DEFAULT_FAILURES_ONLY}}" : "${BASHUNIT_SHOW_OUTPUT_ON_FAILURE:=${SHOW_OUTPUT_ON_FAILURE:=$_BASHUNIT_DEFAULT_SHOW_OUTPUT_ON_FAILURE}}" : "${BASHUNIT_NO_PROGRESS:=${NO_PROGRESS:=$_BASHUNIT_DEFAULT_NO_PROGRESS}}" +: "${BASHUNIT_OUTPUT_FORMAT:=${OUTPUT_FORMAT:=$_BASHUNIT_DEFAULT_OUTPUT_FORMAT}}" # Support NO_COLOR standard (https://no-color.org) if [[ -n "${NO_COLOR:-}" ]]; then BASHUNIT_NO_COLOR="true" @@ -179,6 +182,10 @@ function bashunit::env::is_coverage_enabled() { [[ "$BASHUNIT_COVERAGE" == "true" ]] } +function bashunit::env::is_tap_output_enabled() { + [[ "$BASHUNIT_OUTPUT_FORMAT" == "tap" ]] +} + function bashunit::env::active_internet_connection() { if [[ "${BASHUNIT_NO_NETWORK:-}" == "true" ]]; then return 1 diff --git a/src/main.sh b/src/main.sh index 99b5e47a..e5cc579b 100644 --- a/src/main.sh +++ b/src/main.sh @@ -48,6 +48,10 @@ function bashunit::main::cmd_test() { --detailed) export BASHUNIT_SIMPLE_OUTPUT=false ;; + --output) + export BASHUNIT_OUTPUT_FORMAT="$2" + shift + ;; --debug) local output_file="${2:-}" if [[ -n "$output_file" && "${output_file:0:1}" != "-" ]]; then @@ -62,9 +66,17 @@ function bashunit::main::cmd_test() { -p | --parallel) export BASHUNIT_PARALLEL_RUN=true ;; + -j | --jobs) + export BASHUNIT_PARALLEL_RUN=true + export BASHUNIT_PARALLEL_JOBS="$2" + shift + ;; --no-parallel) export BASHUNIT_PARALLEL_RUN=false ;; + -w | --watch) + export BASHUNIT_WATCH_MODE=true + ;; -e | --env | --boot) # Support: --env "bootstrap.sh arg1 arg2" local boot_file="${2%% *}" @@ -265,12 +277,19 @@ function bashunit::main::cmd_test() { export BASHUNIT_COVERAGE=false bashunit::main::exec_assert "$assert_fn" ${args+"${args[@]}"} else - # Bash 3.0 compatible: only pass args if we have files - # (local args without =() creates a scalar, not an empty array) - if [[ "$args_count" -gt 0 ]]; then - bashunit::main::exec_tests "$filter" "$tag_filter" "$exclude_tag_filter" "${args[@]}" + if [[ "${BASHUNIT_WATCH_MODE:-false}" == true ]]; then + bashunit::main::watch_loop \ + "$filter" "$tag_filter" "$exclude_tag_filter" \ + ${args+"${args[@]}"} else - bashunit::main::exec_tests "$filter" "$tag_filter" "$exclude_tag_filter" + if [[ "$args_count" -gt 0 ]]; then + bashunit::main::exec_tests \ + "$filter" "$tag_filter" "$exclude_tag_filter" \ + "${args[@]}" + else + bashunit::main::exec_tests \ + "$filter" "$tag_filter" "$exclude_tag_filter" + fi fi fi } @@ -491,6 +510,79 @@ function bashunit::main::cmd_assert() { exit $? } +############################# +# Watch mode +############################# +function bashunit::main::watch_get_checksum() { + local IFS=$' \t\n' + local -a paths=("$@") + + local file checksum="" + for file in "${paths[@]+"${paths[@]}"}"; do + if [[ -d "$file" ]]; then + local found + found=$(find "$file" -name '*.sh' -type f \ + -exec stat -f '%m %N' {} + 2>/dev/null || + find "$file" -name '*.sh' -type f \ + -exec stat -c '%Y %n' {} + 2>/dev/null) || true + checksum="${checksum}${found}" + elif [[ -f "$file" ]]; then + local mtime + mtime=$(stat -f '%m' "$file" 2>/dev/null || + stat -c '%Y' "$file" 2>/dev/null) || true + checksum="${checksum}${mtime} ${file}" + fi + done + echo "$checksum" +} + +function bashunit::main::watch_loop() { + local filter="$1" + local tag_filter="${2:-}" + local exclude_tag_filter="${3:-}" + shift 3 + + local IFS=$' \t\n' + local -a watch_paths=("$@") + [[ -d "src" ]] && watch_paths[${#watch_paths[@]}]="src" + + trap 'printf "\n%sWatch mode stopped.%s\n" \ + "${_BASHUNIT_COLOR_SKIPPED}" "${_BASHUNIT_COLOR_DEFAULT}"; \ + exit 0' INT + + local last_checksum="" + while true; do + local current_checksum + current_checksum=$(bashunit::main::watch_get_checksum \ + "${watch_paths[@]}") + + if [[ "$current_checksum" != "$last_checksum" ]]; then + last_checksum="$current_checksum" + printf '\033[2J\033[H' + printf "%s[watch] Running tests...%s\n\n" \ + "${_BASHUNIT_COLOR_SKIPPED}" \ + "${_BASHUNIT_COLOR_DEFAULT}" + + ( + if [[ $# -gt 0 ]]; then + bashunit::main::exec_tests \ + "$filter" "$tag_filter" \ + "$exclude_tag_filter" "$@" + else + bashunit::main::exec_tests \ + "$filter" "$tag_filter" \ + "$exclude_tag_filter" + fi + ) || true + + printf "\n%s[watch] Waiting for changes...%s\n" \ + "${_BASHUNIT_COLOR_SKIPPED}" \ + "${_BASHUNIT_COLOR_DEFAULT}" + fi + sleep 1 + done +} + ############################# # Test execution ############################# @@ -533,7 +625,11 @@ function bashunit::main::exec_tests() { bashunit::parallel::init fi - bashunit::console_header::print_version_with_env "$filter" "${test_files[@]}" + if bashunit::env::is_tap_output_enabled; then + printf "TAP version 13\n" + else + bashunit::console_header::print_version_with_env "$filter" "${test_files[@]}" + fi if bashunit::env::is_verbose_enabled; then if bashunit::env::is_simple_output_enabled; then @@ -559,9 +655,11 @@ function bashunit::main::exec_tests() { printf "\r%sStop on failure enabled...%s\n" "${_BASHUNIT_COLOR_SKIPPED}" "${_BASHUNIT_COLOR_DEFAULT}" fi - bashunit::console_results::print_failing_tests_and_reset - bashunit::console_results::print_incomplete_tests_and_reset - bashunit::console_results::print_skipped_tests_and_reset + if ! bashunit::env::is_tap_output_enabled; then + bashunit::console_results::print_failing_tests_and_reset + bashunit::console_results::print_incomplete_tests_and_reset + bashunit::console_results::print_skipped_tests_and_reset + fi bashunit::console_results::render_result exit_code=$? diff --git a/src/runner.sh b/src/runner.sh index e3ddaea4..c98b49d0 100755 --- a/src/runner.sh +++ b/src/runner.sh @@ -12,6 +12,22 @@ function bashunit::runner::restore_workdir() { cd "$BASHUNIT_WORKING_DIR" 2>/dev/null || true } +function bashunit::runner::wait_for_job_slot() { + local max_jobs="${BASHUNIT_PARALLEL_JOBS:-0}" + if [[ "$max_jobs" -le 0 ]]; then + return 0 + fi + + while true; do + local running_jobs + running_jobs=$(jobs -r | wc -l) + if [[ "$running_jobs" -lt "$max_jobs" ]]; then + break + fi + sleep 0.05 + done +} + function bashunit::runner::load_test_files() { local filter=$1 local tag_filter="${2:-}" @@ -103,6 +119,7 @@ function bashunit::runner::load_test_files() { fi local _cached_fns="$functions_for_script" if bashunit::parallel::is_enabled; then + bashunit::runner::wait_for_job_slot bashunit::runner::call_test_functions \ "$test_file" "$filter" "$tag_filter" \ "$exclude_tag_filter" "$_cached_fns" 2>/dev/null & @@ -426,6 +443,7 @@ function bashunit::runner::call_test_functions() { # No data provider found if [ "$provider_data_count" -eq 0 ]; then if bashunit::parallel::is_enabled && [ "$allow_test_parallel" = true ]; then + bashunit::runner::wait_for_job_slot bashunit::runner::run_test "$script" "$fn_name" & else bashunit::runner::run_test "$script" "$fn_name" @@ -446,6 +464,7 @@ function bashunit::runner::call_test_functions() { parsed_data_count=$((parsed_data_count + 1)) done <<<"$(bashunit::runner::parse_data_provider_args "$data")" if bashunit::parallel::is_enabled && [ "$allow_test_parallel" = true ]; then + bashunit::runner::wait_for_job_slot bashunit::runner::run_test "$script" "$fn_name" ${parsed_data+"${parsed_data[@]}"} & else bashunit::runner::run_test "$script" "$fn_name" ${parsed_data+"${parsed_data[@]}"} @@ -519,7 +538,9 @@ function bashunit::runner::render_running_file_header() { return fi - if ! bashunit::env::is_simple_output_enabled; then + if bashunit::env::is_tap_output_enabled; then + printf "# %s\n" "$script" + elif ! bashunit::env::is_simple_output_enabled; then if bashunit::env::is_verbose_enabled; then printf "\n${_BASHUNIT_COLOR_BOLD}%s${_BASHUNIT_COLOR_DEFAULT}\n" "Running $script" else @@ -946,7 +967,43 @@ function bashunit::runner::write_failure_result_output() { output_section="\n Output:\n$raw_output" fi - echo -e "$test_nr) $test_file:$line_number\n$error_msg$output_section" >>"$FAILURES_OUTPUT_PATH" + local source_context="" + if [[ -n "$line_number" && -f "$test_file" ]]; then + source_context=$(bashunit::runner::get_failure_source_context \ + "$test_file" "$line_number") + fi + + echo -e "$test_nr) $test_file:$line_number\n$error_msg$output_section$source_context" \ + >>"$FAILURES_OUTPUT_PATH" +} + +function bashunit::runner::get_failure_source_context() { + local file=$1 + local fn_line=$2 + + local end_line start_line + end_line=$(wc -l <"$file") + start_line=$((fn_line + 1)) + + local line_text line_num assert_lines="" + line_num=$start_line + while [[ $line_num -le $end_line ]]; do + line_text=$(sed -n "${line_num}p" "$file") + # Stop at the closing brace of the function + if [[ "$line_text" =~ ^[[:space:]]*\}[[:space:]]*$ ]]; then + break + fi + # Collect lines containing assert calls + if [[ "$line_text" == *assert_* ]] || [[ "$line_text" == *assert\ * ]]; then + local trimmed="${line_text#"${line_text%%[![:space:]]*}"}" + assert_lines="${assert_lines}\n ${_BASHUNIT_COLOR_FAINT}${line_num}:${_BASHUNIT_COLOR_DEFAULT} ${trimmed}" + fi + line_num=$((line_num + 1)) + done + + if [[ -n "$assert_lines" ]]; then + echo -e "\n ${_BASHUNIT_COLOR_FAINT}Source:${_BASHUNIT_COLOR_DEFAULT}${assert_lines}" + fi } function bashunit::runner::write_skipped_result_output() { diff --git a/src/state.sh b/src/state.sh index c78cae17..37c88b13 100644 --- a/src/state.sh +++ b/src/state.sh @@ -272,6 +272,11 @@ function bashunit::state::print_line() { return fi + if bashunit::env::is_tap_output_enabled; then + bashunit::state::print_tap_line "$type" "$line" + return + fi + if ! bashunit::env::is_simple_output_enabled; then printf "%s\n" "$line" return @@ -300,3 +305,61 @@ function bashunit::state::print_line() { fi fi } + +function bashunit::state::print_tap_line() { + local type=$1 + local line=$2 + + local clean_line + clean_line=$(printf "%s" "$line" | sed 's/\x1B\[[0-9;]*[mK]//g') + local test_name="${clean_line#*: }" + test_name="${test_name%%$'\n'*}" + # Strip trailing whitespace and duration + test_name=$(printf "%s" "$test_name" | \ + sed 's/[[:space:]]*[0-9][0-9]*m\{0,1\}[[:space:]]*[0-9.]*[ms]*[[:space:]]*$//') + + case "$type" in + successful) + printf "ok %d - %s\n" "$_BASHUNIT_TOTAL_TESTS_COUNT" "$test_name" + ;; + failure | failed | failed_snapshot | error) + printf "not ok %d - %s\n" "$_BASHUNIT_TOTAL_TESTS_COUNT" "$test_name" + local detail_line + printf " ---\n" + while IFS= read -r detail_line; do + detail_line=$(printf "%s" "$detail_line" | sed 's/\x1B\[[0-9;]*[mK]//g') + if [[ -n "$detail_line" \ + && "$detail_line" != *"Failed:"* \ + && "$detail_line" != *"Error:"* ]]; then + local trimmed="${detail_line#"${detail_line%%[![:space:]]*}"}" + printf " %s\n" "$trimmed" + fi + done <<< "$clean_line" + printf " ...\n" + ;; + skipped) + local skip_name="${test_name%% *}" + local skip_reason="${test_name#"$skip_name"}" + skip_reason="${skip_reason#"${skip_reason%%[![:space:]]*}"}" + if [[ -n "$skip_reason" ]]; then + printf "ok %d - %s # SKIP %s\n" \ + "$_BASHUNIT_TOTAL_TESTS_COUNT" "$skip_name" "$skip_reason" + else + printf "ok %d - %s # SKIP\n" \ + "$_BASHUNIT_TOTAL_TESTS_COUNT" "$test_name" + fi + ;; + incomplete) + printf "ok %d - %s # TODO incomplete\n" \ + "$_BASHUNIT_TOTAL_TESTS_COUNT" "$test_name" + ;; + snapshot) + printf "ok %d - %s # snapshot\n" \ + "$_BASHUNIT_TOTAL_TESTS_COUNT" "$test_name" + ;; + *) + printf "not ok %d - %s\n" \ + "$_BASHUNIT_TOTAL_TESTS_COUNT" "$test_name" + ;; + esac +} diff --git a/tests/acceptance/snapshots/bashunit_fail_test_sh.test_bashunit_when_a_test_fail_simple_output_env.snapshot b/tests/acceptance/snapshots/bashunit_fail_test_sh.test_bashunit_when_a_test_fail_simple_output_env.snapshot index dde48b71..9eadffb5 100644 --- a/tests/acceptance/snapshots/bashunit_fail_test_sh.test_bashunit_when_a_test_fail_simple_output_env.snapshot +++ b/tests/acceptance/snapshots/bashunit_fail_test_sh.test_bashunit_when_a_test_fail_simple_output_env.snapshot @@ -6,6 +6,8 @@ |✗ Failed: Assert failing | Expected '1' | but got  '0' +| Source: +| 13: assert_same 1 0 diff --git a/tests/acceptance/snapshots/bashunit_fail_test_sh.test_bashunit_when_a_test_fail_simple_output_option.snapshot b/tests/acceptance/snapshots/bashunit_fail_test_sh.test_bashunit_when_a_test_fail_simple_output_option.snapshot index dde48b71..9eadffb5 100644 --- a/tests/acceptance/snapshots/bashunit_fail_test_sh.test_bashunit_when_a_test_fail_simple_output_option.snapshot +++ b/tests/acceptance/snapshots/bashunit_fail_test_sh.test_bashunit_when_a_test_fail_simple_output_option.snapshot @@ -6,6 +6,8 @@ |✗ Failed: Assert failing | Expected '1' | but got  '0' +| Source: +| 13: assert_same 1 0 diff --git a/tests/acceptance/snapshots/bashunit_fail_test_sh.test_bashunit_when_a_test_fail_verbose_output_env.snapshot b/tests/acceptance/snapshots/bashunit_fail_test_sh.test_bashunit_when_a_test_fail_verbose_output_env.snapshot index 7e879aff..eb2aaa35 100644 --- a/tests/acceptance/snapshots/bashunit_fail_test_sh.test_bashunit_when_a_test_fail_verbose_output_env.snapshot +++ b/tests/acceptance/snapshots/bashunit_fail_test_sh.test_bashunit_when_a_test_fail_verbose_output_env.snapshot @@ -13,6 +13,8 @@ |✗ Failed: Assert failing | Expected '1' | but got  '0' +| Source: +| 13: assert_same 1 0 Tests:  4 passed, 1 failed, 5 total Assertions: 6 passed, 1 failed, 7 total diff --git a/tests/acceptance/snapshots/bashunit_fail_test_sh.test_bashunit_when_a_test_fail_verbose_output_option.snapshot b/tests/acceptance/snapshots/bashunit_fail_test_sh.test_bashunit_when_a_test_fail_verbose_output_option.snapshot index 7e879aff..eb2aaa35 100644 --- a/tests/acceptance/snapshots/bashunit_fail_test_sh.test_bashunit_when_a_test_fail_verbose_output_option.snapshot +++ b/tests/acceptance/snapshots/bashunit_fail_test_sh.test_bashunit_when_a_test_fail_verbose_output_option.snapshot @@ -13,6 +13,8 @@ |✗ Failed: Assert failing | Expected '1' | but got  '0' +| Source: +| 13: assert_same 1 0 Tests:  4 passed, 1 failed, 5 total Assertions: 6 passed, 1 failed, 7 total diff --git a/tests/acceptance/snapshots/bashunit_fail_test_sh.test_bashunit_with_multiple_failing_tests.snapshot b/tests/acceptance/snapshots/bashunit_fail_test_sh.test_bashunit_with_multiple_failing_tests.snapshot index b6eba770..3617af36 100644 --- a/tests/acceptance/snapshots/bashunit_fail_test_sh.test_bashunit_with_multiple_failing_tests.snapshot +++ b/tests/acceptance/snapshots/bashunit_fail_test_sh.test_bashunit_with_multiple_failing_tests.snapshot @@ -14,6 +14,9 @@ |✗ Failed: Assert failing | Expected '1' | but got  '2' +| Source: +| 8: assert_same 1 2 +| 9: assert_same 3 4 Tests:  1 passed, 0 skipped, 2 incomplete, 1 failed, 4 total Assertions: 1 passed, 2 skipped, 2 incomplete, 1 failed, 6 total diff --git a/tests/acceptance/snapshots/bashunit_log_junit_test_sh.test_bashunit_when_log_junit_env.snapshot b/tests/acceptance/snapshots/bashunit_log_junit_test_sh.test_bashunit_when_log_junit_env.snapshot index 7fb7ee24..73a373c0 100644 --- a/tests/acceptance/snapshots/bashunit_log_junit_test_sh.test_bashunit_when_log_junit_env.snapshot +++ b/tests/acceptance/snapshots/bashunit_log_junit_test_sh.test_bashunit_when_log_junit_env.snapshot @@ -10,6 +10,8 @@ |✗ Failed: Failure | Expected '2' | but got  '3' +| Source: +| 8: assert_same 2 3 Tests:  1 passed, 1 failed, 2 total Assertions: 1 passed, 1 failed, 2 total diff --git a/tests/acceptance/snapshots/bashunit_log_junit_test_sh.test_bashunit_when_log_junit_option.snapshot b/tests/acceptance/snapshots/bashunit_log_junit_test_sh.test_bashunit_when_log_junit_option.snapshot index 7fb7ee24..73a373c0 100644 --- a/tests/acceptance/snapshots/bashunit_log_junit_test_sh.test_bashunit_when_log_junit_option.snapshot +++ b/tests/acceptance/snapshots/bashunit_log_junit_test_sh.test_bashunit_when_log_junit_option.snapshot @@ -10,6 +10,8 @@ |✗ Failed: Failure | Expected '2' | but got  '3' +| Source: +| 8: assert_same 2 3 Tests:  1 passed, 1 failed, 2 total Assertions: 1 passed, 1 failed, 2 total diff --git a/tests/acceptance/snapshots/bashunit_report_html_test_sh.test_bashunit_when_report_html_env.snapshot b/tests/acceptance/snapshots/bashunit_report_html_test_sh.test_bashunit_when_report_html_env.snapshot index 6556aaa7..4a69a918 100644 --- a/tests/acceptance/snapshots/bashunit_report_html_test_sh.test_bashunit_when_report_html_env.snapshot +++ b/tests/acceptance/snapshots/bashunit_report_html_test_sh.test_bashunit_when_report_html_env.snapshot @@ -12,6 +12,8 @@ |✗ Failed: Fail | Expected 'to be empty' | but got  'non empty' +| Source: +| 8: assert_empty "non empty" Tests:  1 passed, 1 skipped, 1 incomplete, 1 failed, 4 total Assertions: 1 passed, 1 skipped, 1 incomplete, 1 failed, 4 total diff --git a/tests/acceptance/snapshots/bashunit_report_html_test_sh.test_bashunit_when_report_html_option.snapshot b/tests/acceptance/snapshots/bashunit_report_html_test_sh.test_bashunit_when_report_html_option.snapshot index 6556aaa7..4a69a918 100644 --- a/tests/acceptance/snapshots/bashunit_report_html_test_sh.test_bashunit_when_report_html_option.snapshot +++ b/tests/acceptance/snapshots/bashunit_report_html_test_sh.test_bashunit_when_report_html_option.snapshot @@ -12,6 +12,8 @@ |✗ Failed: Fail | Expected 'to be empty' | but got  'non empty' +| Source: +| 8: assert_empty "non empty" Tests:  1 passed, 1 skipped, 1 incomplete, 1 failed, 4 total Assertions: 1 passed, 1 skipped, 1 incomplete, 1 failed, 4 total diff --git a/tests/acceptance/snapshots/bashunit_stop_on_failure_test_sh.test_bashunit_when_stop_on_failure_env.snapshot b/tests/acceptance/snapshots/bashunit_stop_on_failure_test_sh.test_bashunit_when_stop_on_failure_env.snapshot index 7f053a1d..ee255690 100644 --- a/tests/acceptance/snapshots/bashunit_stop_on_failure_test_sh.test_bashunit_when_stop_on_failure_env.snapshot +++ b/tests/acceptance/snapshots/bashunit_stop_on_failure_test_sh.test_bashunit_when_stop_on_failure_env.snapshot @@ -11,6 +11,10 @@ |✗ Failed: B error | Expected '1' | but got  '2' +| Source: +| 7: assert_same 1 1 +| 8: assert_same 1 2 # error +| 9: assert_same 2 2 Tests:  1 passed, 1 failed, 2 total Assertions: 2 passed, 1 failed, 3 total diff --git a/tests/acceptance/snapshots/bashunit_stop_on_failure_test_sh.test_bashunit_when_stop_on_failure_env_simple_output.snapshot b/tests/acceptance/snapshots/bashunit_stop_on_failure_test_sh.test_bashunit_when_stop_on_failure_env_simple_output.snapshot index 7bb10683..139f1b4e 100644 --- a/tests/acceptance/snapshots/bashunit_stop_on_failure_test_sh.test_bashunit_when_stop_on_failure_env_simple_output.snapshot +++ b/tests/acceptance/snapshots/bashunit_stop_on_failure_test_sh.test_bashunit_when_stop_on_failure_env_simple_output.snapshot @@ -8,6 +8,10 @@ |✗ Failed: B error | Expected '1' | but got  '2' +| Source: +| 7: assert_same 1 1 +| 8: assert_same 1 2 # error +| 9: assert_same 2 2 diff --git a/tests/acceptance/snapshots/bashunit_stop_on_failure_test_sh.test_bashunit_when_stop_on_failure_option.snapshot b/tests/acceptance/snapshots/bashunit_stop_on_failure_test_sh.test_bashunit_when_stop_on_failure_option.snapshot index 7f053a1d..ee255690 100644 --- a/tests/acceptance/snapshots/bashunit_stop_on_failure_test_sh.test_bashunit_when_stop_on_failure_option.snapshot +++ b/tests/acceptance/snapshots/bashunit_stop_on_failure_test_sh.test_bashunit_when_stop_on_failure_option.snapshot @@ -11,6 +11,10 @@ |✗ Failed: B error | Expected '1' | but got  '2' +| Source: +| 7: assert_same 1 1 +| 8: assert_same 1 2 # error +| 9: assert_same 2 2 Tests:  1 passed, 1 failed, 2 total Assertions: 2 passed, 1 failed, 3 total diff --git a/tests/unit/parallel_test.sh b/tests/unit/parallel_test.sh index 9bf9610e..7265c950 100644 --- a/tests/unit/parallel_test.sh +++ b/tests/unit/parallel_test.sh @@ -37,6 +37,24 @@ function tear_down() { export TEMP_FILE_PARALLEL_STOP_ON_FAILURE="$_ORIGINAL_TEMP_FILE_STOP" } +# === wait_for_job_slot tests === + +function test_wait_for_job_slot_returns_immediately_when_no_limit() { + export BASHUNIT_PARALLEL_JOBS=0 + + bashunit::runner::wait_for_job_slot + + assert_successful_code "$?" +} + +function test_wait_for_job_slot_returns_immediately_when_under_limit() { + export BASHUNIT_PARALLEL_JOBS=10 + + bashunit::runner::wait_for_job_slot + + assert_successful_code "$?" +} + # === is_enabled tests === function test_parallel_enabled_on_windows() {