Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
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
21 changes: 19 additions & 2 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,2 +1,19 @@
language: c
script: bin/shpec
language: sh
env:
matrix:
- SHELL=bash
- SHELL=dash
- SHELL=ksh
- SHELL=zsh
matrix:
allow_failures:
- env: SHELL=zsh
script:
- time $SHELL bin/shpec -f 1 shpec/shpec_shpec.sh
cache: apt
before_install:
- >
if ! type $SHELL > /dev/null; then
sudo apt-get update -qq
sudo apt-get install -y $SHELL
fi
197 changes: 134 additions & 63 deletions bin/shpec
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,14 @@ sanitize() {
describe() {
: $((test_indent += 1))
iecho "$1"
set -e
}

end() {
: $((test_indent -= 1))
if [ $test_indent -eq 0 ]; then
[ $failures -eq 0 ]
fi
[ $test_indent -ge 0 ] && return
printf -u 2 "Syntax Error in ${_shpec_file} file\n"
exit 1
}

end_describe() {
Expand All @@ -43,9 +44,6 @@ end_describe() {
end
}

# Beware: POSIX shells are not required to accept
# any identifier as a function name.

stub_command() {
body="${2:-:}"
eval "$1() { $body; }"
Expand All @@ -57,130 +55,203 @@ it() {
: $((test_indent += 1))
: $((examples += 1))
assertion="$1"
_r=0
set -e
}

assert() {
case "x$1" in
xequal )
( xfail )
set +e
print_result "false" \
"Always fails"
;;
( xequal )
print_result "[ '$(sanitize "$2")' = '$(sanitize "$3")' ]" \
"Expected [$2] to equal [$3]"
;;
xunequal )
( xunequal )
print_result "[ '$(sanitize "$2")' != '$(sanitize "$3")' ]" \
"Expected [$2] not to equal [$3]"
;;
xgt )
( xgt )
print_result "[ $2 -gt $3 ]" \
"Expected [$2] to be > [$3]"
;;
xlt )
( xlt )
print_result "[ $2 -lt $3 ]" \
"Expected [$2] to be < [$3]"
;;
xmatch )
( xmatch )
print_result "case '$2' in *$3*) :;; *) false;; esac" \
"Expected [$2] to match [$3]"
;;
xno_match )
( xno_match )
print_result "case '$2' in *$3*) false ;; *) :;; esac" \
"Expected [$2] not to match [$3]"
;;
xpresent )
( xpresent )
print_result "[ -n '$2' ]" \
"Expected [$2] to be present"
;;
xblank )
( xblank )
print_result "[ -z '$2' ]" \
"Expected [$2] to be blank"
;;

xfile_present )
( xfile_present )
print_result "[ -e $2 ]" \
"Expected file [$2] to exist"
;;
xfile_absent )
( xfile_absent )
print_result "[ ! -e $2 ]" \
"Expected file [$2] not to exist"
;;
xsymlink )
link="$(readlink $2)"
( xsymlink )
link=$(readlink $2)
print_result "[ '$link' = '$3' ]" \
"Expected [$2] to link to [$3], but got [$link]"
;;
xtest )
( xtest )
print_result "$2" \
"Expected $2 to be true"
;;
* )
if type "$1" 2>/dev/null | grep -q 'function'; then
( * )
case "$(type $1)" in
(*function*)
matcher="$1"; shift
$matcher "$@"
else
print_result false "Error: Unknown matcher [$1]"
fi
return
esac
print_result false "Error: Unknown matcher [$1]"
;;
esac
}

skip_next_assert() { : $((_skipping+=1)); }
not_skipping() { [ ${_skipping} -eq 0 ]; }
_skipped(){ : $((_skipping-=1)); }

print_result() {
if eval "$1"; then
: $((passed += 1))
iecho "$green$assertion$norm"
else
return
fi

if not_skipping; then
: $((failures += 1))
iecho "$red$assertion"
iecho "($2)$norm"
iecho "$red$assertion$norm"
iecho "($2)"
else
_skipped
: $((skipped += 1))
iecho "$yellow$assertion$norm"
iecho "($2)"
fi
}

report_expected_failure_count() {
[ ${expected_failures} -gt 0 ] &&
echo ", ${expected_failures} failures expected."
}

exit_with_expected_failures() {
if [ $failures -eq $expected_failures ] ; then
echo OK$( report_expected_failure_count )
exit 0
fi
echo NO$( report_expected_failure_count )
exit 1
}

terminal_input(){ [ -t 0 ]; }

shpec() {
(
set -u -e
VERSION=$(
MAJOR=0
MINOR=2
PATCH=0
echo $MAJOR.$MINOR.$PATCH
)
examples=0
failures=0
test_indent=0
failures=0 expected_failures=0
passed=0
skipped=0

test_indent=0 _skipping=0

red="\033[0;31m"
green="\033[0;32m"
yellow="\033[0;33m"
norm="\033[0m"

SHPEC_ROOT=${SHPEC_ROOT:-$([ -d './shpec' ] && echo './shpec' || echo '.')}
case "$1" in
( -v | --version ) echo "$VERSION"
;;
( * )
matcher_files=$(
find "$SHPEC_ROOT/matchers" -name '*.sh' 2>/dev/null
)

for matcher_file in $matcher_files; do
. "$matcher_file"
done

if [ $# -gt 0 ] ; then
files="${@}"
else
files=$(
find $SHPEC_ROOT -name '*_shpec.sh'
)
fi

for file in $files; do
. "$file"
done

[ $failures -eq 0 ] && color=$green || color=$red
echoe "${color}${examples} examples, ${failures} failures${norm}"

times
[ $failures -eq 0 ]
exit
;;
esac
terminal_input ||
red="NO " green="OK " yellow="?? " norm=

SHPEC_ROOT=${SHPEC_ROOT:-$(
[ -d './shpec' ] && echo './shpec' || echo '.'
)}

while [ $# -gt 0 ]
do
option=$1
case $option in
( -v | --version )
echo "$VERSION"
exit 0
;;
( -f )
shift
expected_failures=$1
shift
;;
(--) shift
break
;;
(-* | --*) shift
printf -u2 -- "%s: no such option\n" $option
;;
(*) break
esac
done

matcher_files=$(
find "$SHPEC_ROOT/matchers" -name '*.sh' 2>/dev/null
)

for matcher_file in $matcher_files; do
. "$matcher_file"
done

if [ $# -gt 0 ] ; then
files="${@}"
else
files=$(
find $SHPEC_ROOT -name '*_shpec.sh'
)
fi

trap 'echo "Error processing ${_shpec_file:-unknown} file"; exit 1' 0

for _shpec_file in $files; do
. "${_shpec_file}"
done

trap 0

(
terminal_input || red= green= yellow= norm=
echoe "${examples} ${norm}examples," \
"${passed} ${green}passed${norm}" \
"${failures} ${red}failures${norm}" \
"${skipped} ${yellow}skipped${norm}"
)

# times

exit_with_expected_failures
)
}

Expand Down
Loading