@@ -101,10 +101,15 @@ function bashunit::runner::load_test_files() {
101101 bashunit::runner::restore_workdir
102102 continue
103103 fi
104+ local _cached_fns=" $functions_for_script "
104105 if bashunit::parallel::is_enabled; then
105- bashunit::runner::call_test_functions " $test_file " " $filter " " $tag_filter " " $exclude_tag_filter " 2> /dev/null &
106+ bashunit::runner::call_test_functions \
107+ " $test_file " " $filter " " $tag_filter " \
108+ " $exclude_tag_filter " " $_cached_fns " 2> /dev/null &
106109 else
107- bashunit::runner::call_test_functions " $test_file " " $filter " " $tag_filter " " $exclude_tag_filter "
110+ bashunit::runner::call_test_functions \
111+ " $test_file " " $filter " " $tag_filter " \
112+ " $exclude_tag_filter " " $_cached_fns "
108113 fi
109114 bashunit::runner::run_tear_down_after_script " $test_file "
110115 bashunit::runner::clean_set_up_and_tear_down_after_script
@@ -343,36 +348,48 @@ function bashunit::runner::call_test_functions() {
343348 local filter=" $2 "
344349 local tag_filter=" ${3:- } "
345350 local exclude_tag_filter=" ${4:- } "
351+ local cached_functions=" ${5:- } "
346352 local IFS=$' \t\n '
347- local prefix=" test"
348- # Use cached function names for better performance
349- local filtered_functions
350- filtered_functions=$( bashunit::helper::get_functions_to_run \
351- " $prefix " " $filter " " $_BASHUNIT_CACHED_ALL_FUNCTIONS " )
352353 local -a functions_to_run=()
353354 local functions_to_run_count=0
354- local _fn
355- while IFS= read -r _fn; do
356- [[ -z " $_fn " ]] && continue
357- functions_to_run[functions_to_run_count]=" $_fn "
358- functions_to_run_count=$(( functions_to_run_count + 1 ))
359- done < <( bashunit::runner::functions_for_script " $script " " $filtered_functions " )
360355
361- # Apply tag filtering if --tag or --exclude-tag was specified
362- if [ -n " $tag_filter " ] || [ -n " $exclude_tag_filter " ]; then
363- local -a tag_filtered=()
364- local tag_filtered_count=0
365- local _tf_fn
366- for _tf_fn in " ${functions_to_run[@]+" ${functions_to_run[@]} " } " ; do
367- local fn_tags
368- fn_tags=$( bashunit::helper::get_tags_for_function " $_tf_fn " " $script " )
369- if bashunit::helper::function_matches_tags " $fn_tags " " $tag_filter " " $exclude_tag_filter " ; then
370- tag_filtered[tag_filtered_count]=" $_tf_fn "
371- tag_filtered_count=$(( tag_filtered_count + 1 ))
372- fi
356+ if [[ -n " $cached_functions " ]]; then
357+ # Use pre-computed function list from load_test_files (already tag-filtered)
358+ local _fn
359+ for _fn in $cached_functions ; do
360+ [[ -z " $_fn " ]] && continue
361+ functions_to_run[functions_to_run_count]=" $_fn "
362+ functions_to_run_count=$(( functions_to_run_count + 1 ))
373363 done
374- functions_to_run=(" ${tag_filtered[@]+" ${tag_filtered[@]} " } " )
375- functions_to_run_count=$tag_filtered_count
364+ else
365+ # Fallback: compute function list (for direct calls without cache)
366+ local prefix=" test"
367+ local filtered_functions
368+ filtered_functions=$( bashunit::helper::get_functions_to_run \
369+ " $prefix " " $filter " " $_BASHUNIT_CACHED_ALL_FUNCTIONS " )
370+ local _fn
371+ while IFS= read -r _fn; do
372+ [[ -z " $_fn " ]] && continue
373+ functions_to_run[functions_to_run_count]=" $_fn "
374+ functions_to_run_count=$(( functions_to_run_count + 1 ))
375+ done < <( bashunit::runner::functions_for_script " $script " " $filtered_functions " )
376+
377+ # Apply tag filtering if --tag or --exclude-tag was specified
378+ if [ -n " $tag_filter " ] || [ -n " $exclude_tag_filter " ]; then
379+ local -a tag_filtered=()
380+ local tag_filtered_count=0
381+ local _tf_fn
382+ for _tf_fn in " ${functions_to_run[@]+" ${functions_to_run[@]} " } " ; do
383+ local fn_tags
384+ fn_tags=$( bashunit::helper::get_tags_for_function " $_tf_fn " " $script " )
385+ if bashunit::helper::function_matches_tags " $fn_tags " " $tag_filter " " $exclude_tag_filter " ; then
386+ tag_filtered[tag_filtered_count]=" $_tf_fn "
387+ tag_filtered_count=$(( tag_filtered_count + 1 ))
388+ fi
389+ done
390+ functions_to_run=(" ${tag_filtered[@]+" ${tag_filtered[@]} " } " )
391+ functions_to_run_count=$tag_filtered_count
392+ fi
376393 fi
377394
378395 if [[ " $functions_to_run_count " -le 0 ]]; then
@@ -541,10 +558,10 @@ function bashunit::runner::run_test() {
541558 else
542559 bashunit::state::reset_current_test_interpolated_function_name
543560 fi
544- local current_assertions_failed=" $( bashunit::state::get_assertions_failed ) "
545- local current_assertions_snapshot=" $( bashunit::state::get_assertions_snapshot ) "
546- local current_assertions_incomplete=" $( bashunit::state::get_assertions_incomplete ) "
547- local current_assertions_skipped=" $( bashunit::state::get_assertions_skipped ) "
561+ local current_assertions_failed=" $_BASHUNIT_ASSERTIONS_FAILED "
562+ local current_assertions_snapshot=" $_BASHUNIT_ASSERTIONS_SNAPSHOT "
563+ local current_assertions_incomplete=" $_BASHUNIT_ASSERTIONS_INCOMPLETE "
564+ local current_assertions_skipped=" $_BASHUNIT_ASSERTIONS_SKIPPED "
548565
549566 # (FD = File Descriptor)
550567 # Duplicate the current std-output (FD 1) and assigns it to FD 3.
@@ -655,8 +672,24 @@ function bashunit::runner::run_test() {
655672
656673 bashunit::runner::parse_result " $fn_name " " $test_execution_result " " $@ "
657674
658- local total_assertions=" $( bashunit::state::calculate_total_assertions " $test_execution_result " ) "
659- local test_exit_code=" $( bashunit::state::get_test_exit_code) "
675+ local test_exit_code=" $_BASHUNIT_TEST_EXIT_CODE "
676+
677+ # Extract assertion counts directly via parameter expansion
678+ # instead of spawning grep subprocesses
679+ local _te_failed=" ${test_execution_result##*## ASSERTIONS_FAILED=} "
680+ _te_failed=" ${_te_failed%%##* } "
681+ local _te_passed=" ${test_execution_result##*## ASSERTIONS_PASSED=} "
682+ _te_passed=" ${_te_passed%%##* } "
683+ local _te_skipped=" ${test_execution_result##*## ASSERTIONS_SKIPPED=} "
684+ _te_skipped=" ${_te_skipped%%##* } "
685+ local _te_incomplete=" ${test_execution_result##*## ASSERTIONS_INCOMPLETE=} "
686+ _te_incomplete=" ${_te_incomplete%%##* } "
687+ local _te_snapshot=" ${test_execution_result##*## ASSERTIONS_SNAPSHOT=} "
688+ _te_snapshot=" ${_te_snapshot%%##* } "
689+ local total_assertions=$(( \
690+ ${_te_failed:- 0} + ${_te_passed:- 0} + ${_te_skipped:- 0} + \
691+ ${_te_incomplete:- 0} + ${_te_snapshot:- 0} \
692+ ))
660693
661694 local encoded_test_title
662695 encoded_test_title=" ${test_execution_result##*## TEST_TITLE=} "
0 commit comments