Skip to content
This repository has been archived by the owner on Apr 29, 2021. It is now read-only.

adds ability to output TAP to file and release STDOUT from tests #149

Open
wants to merge 10 commits into
base: master
Choose a base branch
from
33 changes: 33 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,39 @@ You can force TAP output from a terminal by invoking Bats with the
ok 1 addition using bc
ok 2 addition using dc

As stated previously you can redirect the output to a file and it
will be in TAP format, but you can specify to write the output to
a file using the '-o' option which will be in pretty format.

$ bats -o addition.tap addition.bats
$ cat addition.tap

✓ addition using bc
✓ addition using dc

2 tests, 0 failures

You may also tell it to do the same in TAP format using --tap parameter.
Finally, if output has been redirected using -o then you may also tell
bats to release output from tests and commands run in tests on STDOUT.
For instance, if you have a test file like:

```bats
@test "echo something" {
echo something
[ 0 -eq 0 ]
}
```

Then you would get this:

$ bats --tap -r -o echo.tap echo.bats
something
$ cat echo.tap
1..1
ok 1 echo something


### Test suites

You can invoke the `bats` interpreter with multiple test file
Expand Down
137 changes: 92 additions & 45 deletions libexec/bats
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
#!/usr/bin/env bash
set -e


version() {
echo "Bats 0.4.0"
}

usage() {
version
echo "Usage: bats [-c] [-p | -t] <test> [<test> ...]"
echo "Usage: bats [-c] [-p | -t] [-r] [-o <filename>] <test> [<test> ...]"
}

help() {
Expand All @@ -20,6 +21,8 @@ help() {
echo " -h, --help Display this help message"
echo " -p, --pretty Show results in pretty format (default for terminals)"
echo " -t, --tap Show results in TAP format"
echo " -o <filename> Write test results to <filename>"
echo " -r Release output from tests to STDOUT"
echo " -v, --version Display the version number"
echo
echo " For more information, see https://github.com/sstephenson/bats"
Expand Down Expand Up @@ -52,65 +55,91 @@ expand_path() {
} || echo "$1"
}

BATS_LIBEXEC="$(abs_dirname "$0")"
export BATS_LIBEXEC="$(abs_dirname "$0")"
export BATS_PREFIX="$(abs_dirname "$BATS_LIBEXEC")"
export BATS_CWD="$(abs_dirname .)"
export PATH="$BATS_LIBEXEC:$PATH"

options=()
arguments=()
for arg in "$@"; do
if [ "${arg:0:1}" = "-" ]; then
if [ "${arg:1:1}" = "-" ]; then
options[${#options[*]}]="${arg:2}"
else
index=1
while option="${arg:$index:1}"; do
[ -n "$option" ] || break
options[${#options[*]}]="$option"
let index+=1
done
fi
else
arguments[${#arguments[*]}]="$arg"
fi
done
source $BATS_LIBEXEC/common_functions.shrc

unset count_flag pretty
unset pass_the_opts pretty
[ -t 0 ] && [ -t 1 ] && pretty="1"
[ -n "$CI" ] && pretty=""

for option in "${options[@]}"; do
case "$option" in
"h" | "help" )
help
exit 0
;;
"v" | "version" )
version
exit 0
;;
"c" | "count" )
count_flag="-c"
;;
"t" | "tap" )
pretty=""
;;
"p" | "pretty" )
pretty="1"
;;
* )
usage >&2
exit 1
;;
while getopts ":hvctpro:-:" opt; do
if [[ $opt == '-' ]]; then
case $OPTARG in
'pretty')
opt=p;;
'tap')
opt=t;;
'help')
opt=h;;
'version')
opt=v;;
*)
if [ "$OPTERR" = 1 ] && [ "${optspec:0:1}" != ":" ]; then
echo "Unknown option --${OPTARG}" >&2
fi
exit 1
;;
esac
fi
case $opt in
h)
help
exit 0
;;
v)
version
exit 0
;;
c)
pass_the_opts="$pass_the_opts -c"
;;
r)
pass_the_opts="$pass_the_opts -r"
BATS_RELEASE_OUTPUT=1
;;
t)
pretty=""
;;
p)
pretty="1"
;;
o)
TMPFILE1=$(createTempFile)
pass_the_opts="$pass_the_opts -o $TMPFILE1"
BATS_TAPOUT_FILE=$OPTARG
;;
\?)
echo "Invalid option: -$OPTARG" >&2
exit 1
;;
:)
echo "Option -$OPTARG requires an argument." >&2
exit 1
;;
esac
done
shift $((OPTIND-1))

arguments=("${@}")

if [ "${#arguments[@]}" -eq 0 ]; then
usage >&2
exit 1
fi

bats_exit_trap() {
# remove rubbish
if [[ -e $TMPFILE1 ]]; then
rm -f $TMPFILE1
fi
}
trap "bats_exit_trap" exit


filenames=()
for filename in "${arguments[@]}"; do
if [ -d "$filename" ]; then
Expand Down Expand Up @@ -139,4 +168,22 @@ else
fi

set -o pipefail execfail
exec "$command" $count_flag $extended_syntax_flag "${filenames[@]}" | "$formatter"

if [[ -n $BATS_RELEASE_OUTPUT && -z $BATS_TAPOUT_FILE ]]; then
# covers: -r
echo "ERROR: Cannot release output of tests to STDOUT and produce TAP output to STDOUT" 2>&1
exit 1
else
if [[ -n $BATS_TAPOUT_FILE ]]; then
# covers: -r -o t.tap || -o t.tap
set +e
"$command" $pass_the_opts $extended_syntax_flag "${filenames[@]}"
status=$?
set -e
cat $TMPFILE1 | "$formatter" > $BATS_TAPOUT_FILE
exit $status
else
# (near) original command: no tapout file, no release to STDOUT - will spew test results on STDOUT
exec "$command" $pass_the_opts $extended_syntax_flag "${filenames[@]}" | "$formatter"
fi
fi
78 changes: 62 additions & 16 deletions libexec/bats-exec-suite
Original file line number Diff line number Diff line change
@@ -1,17 +1,38 @@
#!/usr/bin/env bash
set -e

count_only_flag=""
if [ "$1" = "-c" ]; then
count_only_flag=1
shift
fi
source $BATS_LIBEXEC/common_functions.shrc

unset pass_the_opts
count_only_flag=""
extended_syntax_flag=""
if [ "$1" = "-x" ]; then
extended_syntax_flag="-x"
shift
fi
while getopts ":o:cxr" opt; do
case $opt in
c)
count_only_flag=1
;;
x)
extended_syntax_flag="-x"
pass_the_opts="$pass_the_opts -x"
;;
o)
export BATS_OUTPUT_FILE=$OPTARG
pass_the_opts="$pass_the_opts -o $BATS_OUTPUT_FILE"
;;
r)
pass_the_opts="$pass_the_opts -r"
;;
\?)
echo "Invalid option: -$OPTARG" >&2
exit 1
;;
:)
echo "Option -$OPTARG requires an argument." >&2
exit 1
;;
esac
done
shift $((OPTIND-1))

trap "kill 0; exit 1" int

Expand All @@ -20,36 +41,61 @@ for filename in "$@"; do
let count+="$(bats-exec-test -c "$filename")"
done

# Set up the location of TAP output and location of run outputs
if [[ -n $BATS_OUTPUT_FILE ]]; then
# Store output in temp file and overwrite BATS_OUTPUT_FILE with it later
TMP_TAP_FILE=$(createTempFile)
exec 4>$TMP_TAP_FILE
else
exec 4<&1 # copy STDOUT file descriptor and use that instead of assuming STDOUT as the file descriptor of outputs
fi

if [ -n "$count_only_flag" ]; then
echo "$count"
>&4 echo "$count"
exit
fi

echo "1..$count"
>&4 echo "1..$count"
status=0
offset=0
for filename in "$@"; do
index=0
if [[ -n $BATS_OUTPUT_FILE ]]; then
echo -n "" > $BATS_OUTPUT_FILE # zero out the file
set +e
bats-exec-test $pass_the_opts "$filename"
set -e
exec 5<$BATS_OUTPUT_FILE
else
exec 5< <( bats-exec-test $pass_the_opts "$filename" )
fi

{
IFS= read -r # 1..n
IFS= read -r myline # 1..n
while IFS= read -r line; do
case "$line" in
"begin "* )
let index+=1
echo "${line/ $index / $(($offset + $index)) }"
>&4 echo "${line/ $index / $(($offset + $index)) }"
;;
"ok "* | "not ok "* )
[ -n "$extended_syntax_flag" ] || let index+=1
echo "${line/ $index / $(($offset + $index)) }"
>&4 echo "${line/ $index / $(($offset + $index)) }"
[ "${line:0:6}" != "not ok" ] || status=1
;;
* )
echo "$line"
>&4 echo "$line"
;;
esac
done
} < <( bats-exec-test $extended_syntax_flag "$filename" )
} <&5

offset=$(($offset + $index))
done

if [[ -n $BATS_OUTPUT_FILE ]]; then
# move temp file over BATS_OUTPUT_FILE
mv -f $TMP_TAP_FILE $BATS_OUTPUT_FILE
fi

exit "$status"
Loading