Skip to content

Commit 3865983

Browse files
committed
feat(cli): add TAP output format via --output tap
Adds TAP version 13 compliant output with --output tap flag. Includes test plan, ok/not ok lines, YAML diagnostics for failures, and proper SKIP/TODO directives.
1 parent 1d7a4ce commit 3865983

6 files changed

Lines changed: 99 additions & 5 deletions

File tree

src/console_header.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,7 @@ Options:
114114
-r, --report-html <file> Write HTML report
115115
-s, --simple Simple output (dots)
116116
--detailed Detailed output (default)
117+
--output <format> Output format: tap (TAP version 13)
117118
-R, --run-all Run all assertions (don't stop on first failure)
118119
-S, --stop-on-failure Stop on first failure
119120
-vvv, --verbose Show execution details

src/console_results.sh

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,14 @@ function bashunit::console_results::render_result() {
1212
return 1
1313
fi
1414

15+
if bashunit::env::is_tap_output_enabled; then
16+
printf "1..%d\n" "$_BASHUNIT_TOTAL_TESTS_COUNT"
17+
if [[ $_BASHUNIT_TESTS_FAILED -gt 0 ]]; then
18+
return 1
19+
fi
20+
return 0
21+
fi
22+
1523
if bashunit::env::is_simple_output_enabled; then
1624
printf "\n\n"
1725
fi
@@ -176,6 +184,10 @@ function bashunit::console_results::print_hook_completed() {
176184
return
177185
fi
178186

187+
if bashunit::env::is_tap_output_enabled; then
188+
return
189+
fi
190+
179191
if bashunit::parallel::is_enabled; then
180192
return
181193
fi

src/env.sh

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ _BASHUNIT_DEFAULT_FAILURES_ONLY="false"
6464
_BASHUNIT_DEFAULT_NO_COLOR="false"
6565
_BASHUNIT_DEFAULT_SHOW_OUTPUT_ON_FAILURE="true"
6666
_BASHUNIT_DEFAULT_NO_PROGRESS="false"
67+
_BASHUNIT_DEFAULT_OUTPUT_FORMAT=""
6768

6869
: "${BASHUNIT_PARALLEL_RUN:=${PARALLEL_RUN:=$_BASHUNIT_DEFAULT_PARALLEL_RUN}}"
6970
: "${BASHUNIT_PARALLEL_JOBS:=0}"
@@ -85,6 +86,7 @@ _BASHUNIT_DEFAULT_NO_PROGRESS="false"
8586
: "${BASHUNIT_FAILURES_ONLY:=${FAILURES_ONLY:=$_BASHUNIT_DEFAULT_FAILURES_ONLY}}"
8687
: "${BASHUNIT_SHOW_OUTPUT_ON_FAILURE:=${SHOW_OUTPUT_ON_FAILURE:=$_BASHUNIT_DEFAULT_SHOW_OUTPUT_ON_FAILURE}}"
8788
: "${BASHUNIT_NO_PROGRESS:=${NO_PROGRESS:=$_BASHUNIT_DEFAULT_NO_PROGRESS}}"
89+
: "${BASHUNIT_OUTPUT_FORMAT:=${OUTPUT_FORMAT:=$_BASHUNIT_DEFAULT_OUTPUT_FORMAT}}"
8890
# Support NO_COLOR standard (https://no-color.org)
8991
if [[ -n "${NO_COLOR:-}" ]]; then
9092
BASHUNIT_NO_COLOR="true"
@@ -180,6 +182,10 @@ function bashunit::env::is_coverage_enabled() {
180182
[[ "$BASHUNIT_COVERAGE" == "true" ]]
181183
}
182184

185+
function bashunit::env::is_tap_output_enabled() {
186+
[[ "$BASHUNIT_OUTPUT_FORMAT" == "tap" ]]
187+
}
188+
183189
function bashunit::env::active_internet_connection() {
184190
if [[ "${BASHUNIT_NO_NETWORK:-}" == "true" ]]; then
185191
return 1

src/main.sh

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,10 @@ function bashunit::main::cmd_test() {
4848
--detailed)
4949
export BASHUNIT_SIMPLE_OUTPUT=false
5050
;;
51+
--output)
52+
export BASHUNIT_OUTPUT_FORMAT="$2"
53+
shift
54+
;;
5155
--debug)
5256
local output_file="${2:-}"
5357
if [[ -n "$output_file" && "${output_file:0:1}" != "-" ]]; then
@@ -605,7 +609,11 @@ function bashunit::main::exec_tests() {
605609
bashunit::parallel::init
606610
fi
607611

608-
bashunit::console_header::print_version_with_env "$filter" "${test_files[@]}"
612+
if bashunit::env::is_tap_output_enabled; then
613+
printf "TAP version 13\n"
614+
else
615+
bashunit::console_header::print_version_with_env "$filter" "${test_files[@]}"
616+
fi
609617

610618
if bashunit::env::is_verbose_enabled; then
611619
if bashunit::env::is_simple_output_enabled; then
@@ -631,9 +639,11 @@ function bashunit::main::exec_tests() {
631639
printf "\r%sStop on failure enabled...%s\n" "${_BASHUNIT_COLOR_SKIPPED}" "${_BASHUNIT_COLOR_DEFAULT}"
632640
fi
633641

634-
bashunit::console_results::print_failing_tests_and_reset
635-
bashunit::console_results::print_incomplete_tests_and_reset
636-
bashunit::console_results::print_skipped_tests_and_reset
642+
if ! bashunit::env::is_tap_output_enabled; then
643+
bashunit::console_results::print_failing_tests_and_reset
644+
bashunit::console_results::print_incomplete_tests_and_reset
645+
bashunit::console_results::print_skipped_tests_and_reset
646+
fi
637647
bashunit::console_results::render_result
638648
exit_code=$?
639649

src/runner.sh

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -525,7 +525,9 @@ function bashunit::runner::render_running_file_header() {
525525
return
526526
fi
527527

528-
if ! bashunit::env::is_simple_output_enabled; then
528+
if bashunit::env::is_tap_output_enabled; then
529+
printf "# %s\n" "$script"
530+
elif ! bashunit::env::is_simple_output_enabled; then
529531
if bashunit::env::is_verbose_enabled; then
530532
printf "\n${_BASHUNIT_COLOR_BOLD}%s${_BASHUNIT_COLOR_DEFAULT}\n" "Running $script"
531533
else

src/state.sh

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -272,6 +272,11 @@ function bashunit::state::print_line() {
272272
return
273273
fi
274274

275+
if bashunit::env::is_tap_output_enabled; then
276+
bashunit::state::print_tap_line "$type" "$line"
277+
return
278+
fi
279+
275280
if ! bashunit::env::is_simple_output_enabled; then
276281
printf "%s\n" "$line"
277282
return
@@ -300,3 +305,61 @@ function bashunit::state::print_line() {
300305
fi
301306
fi
302307
}
308+
309+
function bashunit::state::print_tap_line() {
310+
local type=$1
311+
local line=$2
312+
313+
local clean_line
314+
clean_line=$(printf "%s" "$line" | sed 's/\x1B\[[0-9;]*[mK]//g')
315+
local test_name="${clean_line#*: }"
316+
test_name="${test_name%%$'\n'*}"
317+
# Strip trailing whitespace and duration
318+
test_name=$(printf "%s" "$test_name" | \
319+
sed 's/[[:space:]]*[0-9][0-9]*m\{0,1\}[[:space:]]*[0-9.]*[ms]*[[:space:]]*$//')
320+
321+
case "$type" in
322+
successful)
323+
printf "ok %d - %s\n" "$_BASHUNIT_TOTAL_TESTS_COUNT" "$test_name"
324+
;;
325+
failure | failed | failed_snapshot | error)
326+
printf "not ok %d - %s\n" "$_BASHUNIT_TOTAL_TESTS_COUNT" "$test_name"
327+
local detail_line
328+
printf " ---\n"
329+
while IFS= read -r detail_line; do
330+
detail_line=$(printf "%s" "$detail_line" | sed 's/\x1B\[[0-9;]*[mK]//g')
331+
if [[ -n "$detail_line" \
332+
&& "$detail_line" != *"Failed:"* \
333+
&& "$detail_line" != *"Error:"* ]]; then
334+
local trimmed="${detail_line#"${detail_line%%[![:space:]]*}"}"
335+
printf " %s\n" "$trimmed"
336+
fi
337+
done <<< "$clean_line"
338+
printf " ...\n"
339+
;;
340+
skipped)
341+
local skip_name="${test_name%% *}"
342+
local skip_reason="${test_name#"$skip_name"}"
343+
skip_reason="${skip_reason#"${skip_reason%%[![:space:]]*}"}"
344+
if [[ -n "$skip_reason" ]]; then
345+
printf "ok %d - %s # SKIP %s\n" \
346+
"$_BASHUNIT_TOTAL_TESTS_COUNT" "$skip_name" "$skip_reason"
347+
else
348+
printf "ok %d - %s # SKIP\n" \
349+
"$_BASHUNIT_TOTAL_TESTS_COUNT" "$test_name"
350+
fi
351+
;;
352+
incomplete)
353+
printf "ok %d - %s # TODO incomplete\n" \
354+
"$_BASHUNIT_TOTAL_TESTS_COUNT" "$test_name"
355+
;;
356+
snapshot)
357+
printf "ok %d - %s # snapshot\n" \
358+
"$_BASHUNIT_TOTAL_TESTS_COUNT" "$test_name"
359+
;;
360+
*)
361+
printf "not ok %d - %s\n" \
362+
"$_BASHUNIT_TOTAL_TESTS_COUNT" "$test_name"
363+
;;
364+
esac
365+
}

0 commit comments

Comments
 (0)