roundup.sh | 
        ||
|---|---|---|
(c) 2010 Blake Mizerany - MIT License Spray roundup on your shells to eliminate weeds and bugs. If your shells survive roundup's deathly toxic properties, they are considered roundup-ready. roundup reads shell scripts to form test plans. Each test plan is sourced into a sandbox where each test is executed. See roundup-1-test.sh.html or roundup-5-test.sh.html for example test plans. Install 
NOTE:  Because test plans are sourced into roundup, roundup prefixes its
variable and function names with   | 
#!/bin/sh
 | |
Usage and Prerequisites | 
 | |
| 
 Exit if any following command exits with a non-zero status.  | 
set -e
 | |
| 
 The current version is set during   | 
ROUNDUP_VERSION="0.0.5"
export ROUNDUP_VERSION
 | |
| 
 Usage is defined in a specific comment syntax. It is   | 
#/ usage: roundup [--help|-h] [--version|-v] [plan ...]
roundup_usage() {
    grep '^#/' <"$0" | cut -c4-
}
while test "$#" -gt 0
do
    case "$1" in
        --help|-h)
            roundup_usage
            exit 0
            ;;
        --version|-v)
            echo "roundup version $ROUNDUP_VERSION"
            exit 0
            ;;
        --color)
            color=always
            shift
            ;;
        -)
            echo >&2 "roundup: unknown switch $1"
            exit 1
            ;;
        *)
            break
            ;;
    esac
done
 | |
| 
 Consider all scripts with names matching   | 
if [ "$#" -gt "0" ]
then
    roundup_plans="$@"
else
    roundup_plans="$(ls *-test.sh)"
fi
: ${color:="auto"}
 | |
| 
 Create a temporary storage place for test output to be retrieved for display after failing tests.  | 
roundup_tmp="$PWD/.roundup.$$"
mkdir -p $roundup_tmp
trap "rm -rf \"$roundup_tmp\"" EXIT INT
 | |
| 
 Tracing failures  | 
roundup_trace() {
 | |
| 
 Delete the first two lines that represent roundups execution of the test function. They are useless to the user.  | 
    sed '1d'                                   |
 | |
| 
 Trim the two left most   | 
    sed 's/^++//'                              |
 | |
| 
 Indent the output by 4 spaces to align under the test name in the summary.  | 
    sed 's/^/    /'                            |
 | |
| 
 Highlight the last line to bring notice to where the error occurred.  | 
    sed "\$s/\(.*\)/$mag\1$clr/"
}
 | |
| 
 Other helpers  | 
 | |
| 
 Track the test stats while outputting a real-time report. This takes input on stdin. Each input line must come in the format of: 
 | 
roundup_summarize() {
    set -e
 | |
| 
 Colors for output  | 
 | |
| 
 Use colors if we are writing to a tty device.  | 
    if (test -t 1) || (test $color = always)
    then
        red=$(printf "\033[31m")
        grn=$(printf "\033[32m")
        mag=$(printf "\033[35m")
        clr=$(printf "\033[m")
        cols=$(tput cols)
    fi
 | |
| 
 Make these available to   | 
    export red grn mag clr
    ntests=0
    passed=0
    failed=0
    : ${cols:=10}
    while read status name
    do
        case $status in
        p)
            ntests=$(expr $ntests + 1)
            passed=$(expr $passed + 1)
            printf "  %-48s " "$name:"
            printf "$grn[PASS]$clr\n"
            ;;
        f)
            ntests=$(expr $ntests + 1)
            failed=$(expr $failed + 1)
            printf "  %-48s " "$name:"
            printf "$red[FAIL]$clr\n"
            roundup_trace < "$roundup_tmp/$name"
            ;;
        d)
            printf "%s\n" "$name"
            ;;
        esac
    done
 | |
| 
 Test Summary Display the summary now that all tests are finished.  | 
    yes = | head -n 57 | tr -d '\n'
    printf "\n"
    printf "Tests:  %3d | " $ntests
    printf "Passed: %3d | " $passed
    printf "Failed: %3d"    $failed
    printf "\n"
 | |
| 
 Exit with an error if any tests failed  | 
    test $failed -eq 0 || exit 2
}
 | |
Sandbox Test Runs | 
 | |
| 
 The above checks guarantee we have at least one test. We can now move through each specified test plan, determine its test plan, and administer each test listed in a isolated sandbox.  | 
for roundup_p in $roundup_plans
do
 | |
| 
 Create a sandbox, source the test plan, run the tests, then leave without a trace.  | 
    (
 | |
| 
 Consider the description to be the   | 
        roundup_desc=$(basename "$roundup_p" -test.sh)
 | |
| 
 Define functions for roundup(5)  | 
 | |
| 
 A custom description is recommended, but optional.  Use   | 
        describe() {
            roundup_desc="$*"
        }
 | |
| 
 Provide default   | 
        before() { :; }
        after() { :; }
 | |
| 
 Seek test methods and aggregate their names, forming a test plan. This is done before populating the sandbox with tests to avoid odd conflicts.  | 
 | |
| 
 TODO: I want to do this with sed only. Please send a patch if you know a cleaner way.  | 
        roundup_plan=$(
            grep "^it_.*()" $roundup_p           |
            sed "s/\(it_[a-zA-Z0-9_]*\).*$/\1/g"
        )
 | |
| 
 We have the test plan and are in our sandbox with roundup(5) defined. Now we source the plan to bring its tests into scope.  | 
        . ./$roundup_p
 | |
| 
 Output the description signal  | 
        printf "d %s" "$roundup_desc" | tr "\n" " "
        printf "\n"
        for roundup_test_name in $roundup_plan
        do
 | |
| 
 Any number of things are possible in   | 
            (
 | |
| 
 If   | 
                before
 | |
| 
 Momentarily turn off auto-fail to give us access to the tests
exit status in   | 
                set +e
                (
 | |
| 
 Set   | 
                    set -xe
                    $roundup_test_name
                ) >"$roundup_tmp/$roundup_test_name" 2>&1
 | |
| 
 We need to capture the exit status before returning the   | 
                roundup_result=$?
 | |
| 
 It's safe to return to normal operation.  | 
                set -e
 | |
| 
 If   | 
                after
 | |
| 
 This is the final step of a test. Print its pass/fail signal and name.  | 
                if [ "$roundup_result" -ne 0 ]
                then printf "f"
                else printf "p"
                fi
                printf " $roundup_test_name\n"
            )
        done
    )
done |
 | |
| 
 All signals are piped to this for summary.  | 
roundup_summarize
 | 
 | 
 | ||