#!/bin/bash # assert.sh 1.1 - bash unit testing framework # Copyright (C) 2009-2015 Robert Lehmann # # http://github.com/lehmannro/assert.sh # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License as published # by the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with this program. If not, see . export DISCOVERONLY=${DISCOVERONLY:-} export DEBUG=${DEBUG:-} export STOP=${STOP:-} export INVARIANT=${INVARIANT:-} export CONTINUE=${CONTINUE:-} args="$(getopt -n "$0" -l \ verbose,help,stop,discover,invariant,continue vhxdic $*)" \ || exit -1 for arg in $args; do case "$arg" in -h) echo "$0 [-vxidc]" \ "[--verbose] [--stop] [--invariant] [--discover] [--continue]" echo "`sed 's/./ /g' <<< "$0"` [-h] [--help]" exit 0;; --help) cat < [stdin] (( tests_ran++ )) || : [[ -z "$DISCOVERONLY" ]] || return expected=$(echo -ne "${2:-}") result="$(eval 2>/dev/null $1 <<< ${3:-})" || true if [[ "$result" == "$expected" ]]; then [[ -z "$DEBUG" ]] || echo -n . return fi result="$(sed -e :a -e '$!N;s/\n/\\n/;ta' <<< "$result")" [[ -z "$result" ]] && result="nothing" || result="\"$result\"" [[ -z "$2" ]] && expected="nothing" || expected="\"$2\"" _assert_fail "expected $expected${_indent}got $result" "$1" "$3" } assert_raises() { # assert_raises [stdin] (( tests_ran++ )) || : [[ -z "$DISCOVERONLY" ]] || return status=0 (eval $1 <<< ${3:-}) > /dev/null 2>&1 || status=$? expected=${2:-0} if [[ "$status" -eq "$expected" ]]; then [[ -z "$DEBUG" ]] || echo -n . return fi _assert_fail "program terminated with code $status instead of $expected" "$1" "$3" } _assert_fail() { # _assert_fail [[ -n "$DEBUG" ]] && echo -n X report="test #$tests_ran \"$2${3:+ <<< $3}\" failed:${_indent}$1" if [[ -n "$STOP" ]]; then [[ -n "$DEBUG" ]] && echo echo "$report" exit 1 fi tests_errors[$tests_failed]="$report" (( tests_failed++ )) || : } skip_if() { # skip_if (eval $@) > /dev/null 2>&1 && status=0 || status=$? [[ "$status" -eq 0 ]] || return skip } skip() { # skip (no arguments) shopt -q extdebug && tests_extdebug=0 || tests_extdebug=1 shopt -q -o errexit && tests_errexit=0 || tests_errexit=1 # enable extdebug so returning 1 in a DEBUG trap handler skips next command shopt -s extdebug # disable errexit (set -e) so we can safely return 1 without causing exit set +o errexit tests_trapped=0 trap _skip DEBUG } _skip() { if [[ $tests_trapped -eq 0 ]]; then # DEBUG trap for command we want to skip. Do not remove the handler # yet because *after* the command we need to reset extdebug/errexit (in # another DEBUG trap.) tests_trapped=1 [[ -z "$DEBUG" ]] || echo -n s return 1 else trap - DEBUG [[ $tests_extdebug -eq 0 ]] || shopt -u extdebug [[ $tests_errexit -eq 1 ]] || set -o errexit return 0 fi } _assert_reset : ${tests_suite_status:=0} # remember if any of the tests failed so far _assert_cleanup() { local status=$? # modify exit code if it's not already non-zero [[ $status -eq 0 && -z $CONTINUE ]] && exit $tests_suite_status } trap _assert_cleanup EXIT