From c8739db1938a95839728db5fa4c8ce1a3628c6db Mon Sep 17 00:00:00 2001 From: chemaclass Date: Mon, 20 Jul 2026 23:07:08 +0200 Subject: [PATCH 1/3] ref(console): reuse format_duration in print_execution_time The run-footer time formatter open-coded the same ms -> Xm Ys / X.XXs / Xms branching already provided by bashunit::console_results::format_duration. Since print_execution_time runs once per run (not on the per-test hot path), delegate to the shared helper instead of re-deriving the logic. Claude-Session: https://claude.ai/code/session_01JSeB8UzLCpqst55hAK6dED --- src/console_results.sh | 26 +++++--------------------- 1 file changed, 5 insertions(+), 21 deletions(-) diff --git a/src/console_results.sh b/src/console_results.sh index 3d9ecd62..5ef55a30 100644 --- a/src/console_results.sh +++ b/src/console_results.sh @@ -143,29 +143,13 @@ function bashunit::console_results::print_execution_time() { time="${time%%.*}" time="${time:-0}" - if [ "$time" -lt 1000 ]; then - printf "${_BASHUNIT_COLOR_BOLD}%s${_BASHUNIT_COLOR_DEFAULT}\n" \ - "Time taken: ${time}ms" - return - fi - - local time_in_seconds=$((time / 1000)) - - if [ "$time_in_seconds" -ge 60 ]; then - local minutes=$((time_in_seconds / 60)) - local seconds=$((time_in_seconds % 60)) - printf "${_BASHUNIT_COLOR_BOLD}%s${_BASHUNIT_COLOR_DEFAULT}\n" \ - "Time taken: ${minutes}m ${seconds}s" - return - fi - - local integer_part=$((time / 1000)) - local decimal_part=$(( (time % 1000) / 10 )) - local formatted_seconds - formatted_seconds=$(printf "%d.%02d" "$integer_part" "$decimal_part") + # Reuse the shared ms formatter (Xm Ys / X.XXs / Xms) instead of re-deriving it; + # this runs once per run, so the command-substitution fork is negligible. + local formatted + formatted=$(bashunit::console_results::format_duration "$time") printf "${_BASHUNIT_COLOR_BOLD}%s${_BASHUNIT_COLOR_DEFAULT}\n" \ - "Time taken: ${formatted_seconds}s" + "Time taken: ${formatted}" } function bashunit::console_results::format_duration() { From 57bec8a2c01894fa7c1567ff67170a06921c1e74 Mon Sep 17 00:00:00 2001 From: Chemaclass Date: Mon, 20 Jul 2026 23:05:14 +0200 Subject: [PATCH 2/3] ref(helpers): drop superseded get_tags_for_function wrapper The stdout-returning tag wrapper had zero production callers: runner.sh uses the fork-free build_tags_map + tags_for_function pair directly. Only its own unit tests exercised it. Remove the wrapper and its 4 tests, keeping the tags path singular. function_matches_tags tests remain. Claude-Session: https://claude.ai/code/session_01JSeB8UzLCpqst55hAK6dED --- src/helpers.sh | 17 ----------------- tests/unit/helpers_tag_test.sh | 33 --------------------------------- 2 files changed, 50 deletions(-) diff --git a/src/helpers.sh b/src/helpers.sh index c8db3917..deb9c310 100755 --- a/src/helpers.sh +++ b/src/helpers.sh @@ -856,23 +856,6 @@ function bashunit::helper::tags_for_function() { _BASHUNIT_TAGS_OUT="" } -# -# Extracts @tag annotations for a specific function from a test file. -# Thin wrapper over the cached tags map, kept for callers that want the tags -# on stdout. Hot-path call sites use build_tags_map + tags_for_function to -# avoid the subshell fork. -# -# @param $1 string Function name -# @param $2 string Script file path -# -# @return string Comma-separated list of tags, or empty if none -# -function bashunit::helper::get_tags_for_function() { - bashunit::helper::build_tags_map "$2" - bashunit::helper::tags_for_function "$1" - echo "$_BASHUNIT_TAGS_OUT" -} - # # Checks if a function's tags match the include/exclude filters. # Include uses OR logic (any match passes). diff --git a/tests/unit/helpers_tag_test.sh b/tests/unit/helpers_tag_test.sh index 71ee884f..55e39502 100644 --- a/tests/unit/helpers_tag_test.sh +++ b/tests/unit/helpers_tag_test.sh @@ -1,39 +1,6 @@ #!/usr/bin/env bash # shellcheck disable=SC2317 -function test_get_tags_for_function_returns_tags() { - local script="tests/acceptance/fixtures/test_bashunit_with_tags.sh" - local result - result=$(bashunit::helper::get_tags_for_function "test_slow_operation" "$script") - - assert_same "slow" "$result" -} - -function test_get_tags_for_function_returns_multiple_tags() { - local script="tests/acceptance/fixtures/test_bashunit_with_tags.sh" - local result - result=$(bashunit::helper::get_tags_for_function "test_slow_database_query" "$script") - - assert_contains "slow" "$result" - assert_contains "database" "$result" -} - -function test_get_tags_for_function_returns_empty_when_no_tags() { - local script="tests/acceptance/fixtures/test_bashunit_with_tags.sh" - local result - result=$(bashunit::helper::get_tags_for_function "test_no_tags" "$script") - - assert_empty "$result" -} - -function test_get_tags_for_function_returns_empty_for_nonexistent_function() { - local script="tests/acceptance/fixtures/test_bashunit_with_tags.sh" - local result - result=$(bashunit::helper::get_tags_for_function "test_nonexistent" "$script") - - assert_empty "$result" -} - function test_function_matches_tags_include_match() { local tags="slow,database" local include_tags="slow" From f818ca57fb36f693ec970b3d622ab410551adbe3 Mon Sep 17 00:00:00 2001 From: Chemaclass Date: Mon, 20 Jul 2026 23:12:34 +0200 Subject: [PATCH 3/3] chore(state): remove unreferenced internal accessor functions Drop 9 internal getters/resets that had zero call sites anywhere in the tracked repo (proven via git grep; no dynamic dispatch, not part of the public assertion/CLI API). The backing _BASHUNIT_* variables are read and written directly, so these accessors were dead: - bashunit::state::get_test_exit_code - bashunit::state::get_test_title - bashunit::state::get_current_test_interpolated_function_name - bashunit::state::get_test_hook_failure / reset_test_hook_failure - bashunit::state::get_test_hook_message / reset_test_hook_message - bashunit::state::is_assertion_failed_in_test - bashunit::clock::total_runtime_in_nanoseconds Claude-Session: https://claude.ai/code/session_01JSeB8UzLCpqst55hAK6dED --- src/clock.sh | 10 ---------- src/state.sh | 32 -------------------------------- 2 files changed, 42 deletions(-) diff --git a/src/clock.sh b/src/clock.sh index a81cf888..035cb66e 100644 --- a/src/clock.sh +++ b/src/clock.sh @@ -195,16 +195,6 @@ function bashunit::clock::total_runtime_in_milliseconds() { fi } -function bashunit::clock::total_runtime_in_nanoseconds() { - local end_time - end_time=$(bashunit::clock::now) - if [ -n "$end_time" ]; then - bashunit::math::calculate "$end_time - $_BASHUNIT_START_TIME" - else - echo "" - fi -} - function bashunit::clock::init() { _BASHUNIT_START_TIME=$(bashunit::clock::now) } diff --git a/src/state.sh b/src/state.sh index 99a2b25f..67b8a19a 100644 --- a/src/state.sh +++ b/src/state.sh @@ -148,18 +148,10 @@ function bashunit::state::add_test_output() { _BASHUNIT_TEST_OUTPUT="$_BASHUNIT_TEST_OUTPUT$1" } -function bashunit::state::get_test_exit_code() { - echo "$_BASHUNIT_TEST_EXIT_CODE" -} - function bashunit::state::set_test_exit_code() { _BASHUNIT_TEST_EXIT_CODE="$1" } -function bashunit::state::get_test_title() { - echo "$_BASHUNIT_TEST_TITLE" -} - function bashunit::state::set_test_title() { _BASHUNIT_TEST_TITLE="$1" } @@ -168,10 +160,6 @@ function bashunit::state::reset_test_title() { _BASHUNIT_TEST_TITLE="" } -function bashunit::state::get_current_test_interpolated_function_name() { - echo "$_BASHUNIT_CURRENT_TEST_INTERPOLATED_NAME" -} - function bashunit::state::set_current_test_interpolated_function_name() { _BASHUNIT_CURRENT_TEST_INTERPOLATED_NAME="$1" } @@ -180,34 +168,14 @@ function bashunit::state::reset_current_test_interpolated_function_name() { _BASHUNIT_CURRENT_TEST_INTERPOLATED_NAME="" } -function bashunit::state::get_test_hook_failure() { - echo "$_BASHUNIT_TEST_HOOK_FAILURE" -} - function bashunit::state::set_test_hook_failure() { _BASHUNIT_TEST_HOOK_FAILURE="$1" } -function bashunit::state::reset_test_hook_failure() { - _BASHUNIT_TEST_HOOK_FAILURE="" -} - -function bashunit::state::get_test_hook_message() { - echo "$_BASHUNIT_TEST_HOOK_MESSAGE" -} - function bashunit::state::set_test_hook_message() { _BASHUNIT_TEST_HOOK_MESSAGE="$1" } -function bashunit::state::reset_test_hook_message() { - _BASHUNIT_TEST_HOOK_MESSAGE="" -} - -function bashunit::state::is_assertion_failed_in_test() { - ((_BASHUNIT_ASSERTION_FAILED_IN_TEST)) -} - function bashunit::state::mark_assertion_failed_in_test() { _BASHUNIT_ASSERTION_FAILED_IN_TEST=1 }