-
Notifications
You must be signed in to change notification settings - Fork 3
/
runtests
executable file
·138 lines (110 loc) · 2.97 KB
/
runtests
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
#!/bin/bash
#
# yesod test runner, simplistically based on rails' test/unit
#
# searches for "test files" located at ./test/*_test.sh
#
# a test file can contain the following special function definitions:
#
# setup: run before _every_ test
# teardown: run after _every_ test
# test_*: any functions prefixed with this are taken to be your
# actual tests
#
# setup/teardown are optional and if no test_ functions are found, no
# tests are run.
#
# compiles the application into a source distribution, unpacks and
# enters the source distribution, then runs any test_* functions "as
# tests", meaning:
#
# stdout is silenced (unless --verbose) and stderr is collected in /tmp
# (use --tmp <dir> to override). after all tests finish, the failures
# and the collected stderr is reported.
#
###
usage() { echo 'runtests [ --verbose ] [ --tmp <dir> ]'; exit 1; }
# runs the function named by $1 as a test. failures are tracked to be
# reported on after all tests have been run
run_test() { # {{{
local test_function="$*" stdout
$verbose && stdout='/dev/stdout' || stdout='/dev/null'
type -p setup && setup
if $test_function >"$stdout" 2>"$tmp/$test_function.errors"; then
echo -n '.'
rm -f "$tmp/$test_function.errors"
else
echo -n 'F'
FAILURES+=( "$test_function" )
fi
type -p teardown && teardown
}
# }}}
# unset any existing definitions and source new ones from the file named
# by $1
source_test_file() { # {{{
local test_file="$1" test_
[[ -f "$test_file" ]] || return 1
unset -f setup teardown
while read -r test_; do
unset -f test_ # unset any already-defined test_ functions
done < <(set | sed '/^\(test_[^ ]*\) ()/!d; s//\1/g')
source "$test_file" || return 1
# read any newly defined test_ functions into a TESTS array
read -r -d '\n' -a TESTS < <(set | sed '/^\(test_[^ ]*\) ()/!d; s//\1/g')
}
# }}}
# outputs a report of tests and failures
report() { # {{{
local test_
echo
echo
echo "Tests: ${#TESTS[@]}, Failures: ${#FAILURES[@]}."
echo
[[ ${#FAILURES[@]} -eq 0 ]] && return 0
for test_ in ${FAILURES[@]}; do
echo "Failure: $test_"
echo 'details:'
echo
if [[ -f "$tmp/$test_.errors" ]]; then
cat "$tmp/$test_.errors"
rm "$tmp/$test_.errors"
else
echo '<no stderr captured>'
fi
echo
done
return ${#FAILURES[@]}
}
# }}}
tmp='/tmp'
verbose=false
while [[ -n "$1" ]]; do
case "$1" in
-t|--tmp) shift; tmp="$1" ;;
-v|--verbose) verbose=true ;;
*) usage ;;
esac
done
CABAL=${CABAL:-cabal}
echo 'Compiling application...'
(
set -e
$CABAL clean
$CABAL install
$CABAL sdist
) &>/dev/null || { echo 'Failed.' >&2; exit 1; }
read -r pkg < <(find dist/ -type f -name '*.tar.gz' | sort -rV)
dir="$(basename "$pkg" .tar.gz)"
tar -xzf "$pkg"
echo 'Started'
for file in test/*_test.sh; do
source_test_file "$file"
cd "$dir"
for test_ in "${TESTS[@]}"; do
run_test $test_
done
cd - >/dev/null
done
rm -rf "$dir"
report