Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

assert_output and assert_lines: add --use-stderr option #69

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 28 additions & 14 deletions src/assert_line.bash
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,13 @@
#
# Summary: Fail if the expected line is not found in the output (default) or at a specific line number.
#
# Usage: assert_line [-n index] [-p | -e] [--] <expected>
# Usage: assert_line [-n index] [-p | -e] [-s | --use-stderr] [--] <expected>
#
# Options:
# -n, --index <idx> Match the <idx>th line
# -p, --partial Match if `expected` is a substring of `$output` or line <idx>
# -e, --regexp Treat `expected` as an extended regular expression
# -s, --use-stderr Match against `$stderr_lines` instead of `$lines`
# <expected> The expected line string, substring, or regular expression
#
# IO:
Expand All @@ -17,6 +18,8 @@
# Globals:
# output
# lines
# stderr
# stderr_lines
# Returns:
# 0 - if matching line found
# 1 - otherwise
Expand Down Expand Up @@ -131,7 +134,7 @@ assert_line() {
local -i is_match_line=0
local -i is_mode_partial=0
local -i is_mode_regexp=0
: "${lines?}"
local -i use_stderr=0

# Handle options.
while (( $# > 0 )); do
Expand All @@ -149,6 +152,7 @@ assert_line() {
;;
-p|--partial) is_mode_partial=1; shift ;;
-e|--regexp) is_mode_regexp=1; shift ;;
-s|--use-stderr) use_stderr=1; shift ;;
--) shift; break ;;
*) break ;;
esac
Expand All @@ -171,33 +175,43 @@ assert_line() {
return $?
fi

# Select lines array based on use_stderr.
local -n selected_lines
if (( use_stderr )); then
: "${stderr_lines?}"
selected_lines="stderr_lines"
else
: "${lines?}"
selected_lines="lines"
fi

# Matching.
if (( is_match_line )); then
# Specific line.
if (( is_mode_regexp )); then
if ! [[ ${lines[$idx]} =~ $expected ]]; then
if ! [[ ${selected_lines[$idx]} =~ $expected ]]; then
batslib_print_kv_single 6 \
'index' "$idx" \
'regexp' "$expected" \
'line' "${lines[$idx]}" \
'line' "${selected_lines[$idx]}" \
| batslib_decorate 'regular expression does not match line' \
| fail
fi
elif (( is_mode_partial )); then
if [[ ${lines[$idx]} != *"$expected"* ]]; then
if [[ ${selected_lines[$idx]} != *"$expected"* ]]; then
batslib_print_kv_single 9 \
'index' "$idx" \
'substring' "$expected" \
'line' "${lines[$idx]}" \
'line' "${selected_lines[$idx]}" \
| batslib_decorate 'line does not contain substring' \
| fail
fi
else
if [[ ${lines[$idx]} != "$expected" ]]; then
if [[ ${selected_lines[$idx]} != "$expected" ]]; then
batslib_print_kv_single 8 \
'index' "$idx" \
'expected' "$expected" \
'actual' "${lines[$idx]}" \
'actual' "${selected_lines[$idx]}" \
| batslib_decorate 'line differs' \
| fail
fi
Expand All @@ -206,8 +220,8 @@ assert_line() {
# Contained in output.
if (( is_mode_regexp )); then
local -i idx
for (( idx = 0; idx < ${#lines[@]}; ++idx )); do
[[ ${lines[$idx]} =~ $expected ]] && return 0
for (( idx = 0; idx < ${#selected_lines[@]}; ++idx )); do
[[ ${selected_lines[$idx]} =~ $expected ]] && return 0
done
{ local -ar single=( 'regexp' "$expected" )
local -ar may_be_multi=( 'output' "$output" )
Expand All @@ -219,8 +233,8 @@ assert_line() {
| fail
elif (( is_mode_partial )); then
local -i idx
for (( idx = 0; idx < ${#lines[@]}; ++idx )); do
[[ ${lines[$idx]} == *"$expected"* ]] && return 0
for (( idx = 0; idx < ${#selected_lines[@]}; ++idx )); do
[[ ${selected_lines[$idx]} == *"$expected"* ]] && return 0
done
{ local -ar single=( 'substring' "$expected" )
local -ar may_be_multi=( 'output' "$output" )
Expand All @@ -232,8 +246,8 @@ assert_line() {
| fail
else
local -i idx
for (( idx = 0; idx < ${#lines[@]}; ++idx )); do
[[ ${lines[$idx]} == "$expected" ]] && return 0
for (( idx = 0; idx < ${#selected_lines[@]}; ++idx )); do
[[ ${selected_lines[$idx]} == "$expected" ]] && return 0
done
{ local -ar single=( 'line' "$expected" )
local -ar may_be_multi=( 'output' "$output" )
Expand Down
53 changes: 42 additions & 11 deletions src/assert_output.bash
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
# assert_output
# =============
#
# Summary: Fail if `$output' does not match the expected output.
# Summary: Fail if `$output` or `$stderr` (with --use-stderr) does not match the expected output.
#
# Usage: assert_output [-p | -e] [- | [--] <expected>]
# Usage: assert_output [-p | -e] [--use-stderr] [- | [--] <expected>]
#
# Options:
# -p, --partial Match if `expected` is a substring of `$output`
# -p, --partial Match if `expected` is a substring of `$output` or `$stderr`
# -e, --regexp Treat `expected` as an extended regular expression
# -, --stdin Read `expected` value from STDIN
# --use-stderr Compare against `$stderr` instead of `$output`
# <expected> The expected value, substring or regular expression
#
# IO:
Expand All @@ -17,6 +18,7 @@
# error message, on error
# Globals:
# output
# stderr
# Returns:
# 0 - if output matches the expected value/partial/regexp
# 1 - otherwise
Expand Down Expand Up @@ -121,12 +123,26 @@
# output : Foobar 0.1.0
# --
# ```
#
# ## Using --use-stderr
#
# The `--use-stderr` option directs `assert_output` to match against `$stderr` instead of `$output`.
# This is useful for verifying error messages or other content written to standard error.
#
# ```bash
# @test 'assert_output() with --use-stderr' {
# run --separate-stderr bash -c 'echo "error message" >&2'
# assert_output --use-stderr 'error message'
# }
# ```
#
# On failure, the expected and actual stderr values are displayed.
assert_output() {
local -i is_mode_partial=0
local -i is_mode_regexp=0
local -i is_mode_nonempty=0
local -i use_stdin=0
: "${output?}"
local -i use_stderr=0

# Handle options.
if (( $# == 0 )); then
Expand All @@ -137,12 +153,19 @@ assert_output() {
case "$1" in
-p|--partial) is_mode_partial=1; shift ;;
-e|--regexp) is_mode_regexp=1; shift ;;
--use-stderr) use_stderr=1; shift ;;
-|--stdin) use_stdin=1; shift ;;
--) shift; break ;;
*) break ;;
esac
done

if (( use_stderr )); then
: "${stderr?}"
else
: "${output?}"
fi

if (( is_mode_partial )) && (( is_mode_regexp )); then
echo "\`--partial' and \`--regexp' are mutually exclusive" \
| batslib_decorate 'ERROR: assert_output' \
Expand All @@ -158,9 +181,17 @@ assert_output() {
expected="${1-}"
fi

# Determine the source of output (stdout or stderr).
local actual_output
if (( use_stderr )); then
actual_output="$stderr"
else
actual_output="$output"
fi

# Matching.
if (( is_mode_nonempty )); then
if [ -z "$output" ]; then
if [ -z "$actual_output" ]; then
echo 'expected non-empty output, but output was empty' \
| batslib_decorate 'no output' \
| fail
Expand All @@ -170,26 +201,26 @@ assert_output() {
echo "Invalid extended regular expression: \`$expected'" \
| batslib_decorate 'ERROR: assert_output' \
| fail
elif ! [[ $output =~ $expected ]]; then
elif ! [[ $actual_output =~ $expected ]]; then
batslib_print_kv_single_or_multi 6 \
'regexp' "$expected" \
'output' "$output" \
'output' "$actual_output" \
| batslib_decorate 'regular expression does not match output' \
| fail
fi
elif (( is_mode_partial )); then
if [[ $output != *"$expected"* ]]; then
if [[ $actual_output != *"$expected"* ]]; then
batslib_print_kv_single_or_multi 9 \
'substring' "$expected" \
'output' "$output" \
'output' "$actual_output" \
| batslib_decorate 'output does not contain substring' \
| fail
fi
else
if [[ $output != "$expected" ]]; then
if [[ $actual_output != "$expected" ]]; then
batslib_print_kv_single_or_multi 8 \
'expected' "$expected" \
'actual' "$output" \
'actual' "$actual_output" \
| batslib_decorate 'output differs' \
| fail
fi
Expand Down