#! /usr/bin/env python | |
import sys,os,subprocess,signal | |
from stat import * | |
#!/bin/bash | |
# assert.sh 1.0 - bash unit testing framework | |
# Copyright (C) 2009, 2010, 2011, 2012 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 <http://www.gnu.org/licenses/>. | |
export DISCOVERONLY=${DISCOVERONLY:-} | |
# assert.sh 1.0 - bash unit testing framework | |
# Copyright (C) 2009, 2010, 2011, 2012 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 <http://www.gnu.org/licenses/>. | |
os.environ['DISCOVERONLY'] = '' if dir().count('DISCOVERONLY') == 0 else DISCOVERONLY | |
export DEBUG=${DEBUG:-} | |
os.environ['DEBUG'] = '' if dir().count('DEBUG') == 0 else DEBUG | |
export STOP=${STOP:-} | |
os.environ['STOP'] = '' if dir().count('STOP') == 0 else STOP | |
export INVARIANT=${INVARIANT:-} | |
os.environ['INVARIANT'] = '' if dir().count('INVARIANT') == 0 else INVARIANT | |
export CONTINUE=${CONTINUE:-} | |
os.environ['CONTINUE'] = '' if dir().count('CONTINUE') == 0 else CONTINUE | |
args="$(getopt -n "$0" -l \ verbose,help,stop,discover,invariant,continue vhxdic $*)" \ || exit -1 | |
args=str(os.popen("getopt -n \""+str(__file__)+"\" -l verbose,help,stop,discover,invariant,continue vhxdic "+str(" ".join(sys.argv[1:]))).read()) or 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 <<EOF Usage: $0 [options] Language-agnostic unit tests for subprocesses. Options: -v, --verbose generate output for every individual test case -x, --stop stop running tests after the first failure -i, --invariant do not measure timings to remain invariant between runs -d, --discover collect test suites only, do not run any tests -c, --continue do not modify exit code to test suite status -h show brief usage information and exit --help show this help message and exit EOF exit 0;; -v|--verbose) DEBUG=1;; -x|--stop) STOP=1;; -i|--invariant) INVARIANT=1;; -d|--discover) DISCOVERONLY=1;; -c|--continue) CONTINUE=1;; esac done | |
for arg in [args]: if ( str(arg) == '-h'): print(str(__file__) + " [-vxidc]","[--verbose] [--stop] [--invariant] [--discover] [--continue]") print(str(os.popen("sed \"s/./ /g\" <<< \""+str(__file__)+"\"").read()) + " [-h] [--help]") exit(0) elif ( str(arg) == '--help'): _rc = subprocess.call("cat",shell=True,stdin=subprocess.PIPE) _rc.communicate("Usage: " + str(__file__) + " [options]\nLanguage-agnostic unit tests for subprocesses.\n\nOptions:\n -v, --verbose generate output for every individual test case\n -x, --stop stop running tests after the first failure\n -i, --invariant do not measure timings to remain invariant between runs\n -d, --discover collect test suites only, do not run any tests\n -c, --continue do not modify exit code to test suite status\n -h show brief usage information and exit\n --help show this help message and exit\n") exit(0) elif ( str(arg) == '-v' or str(arg) == '--verbose'): DEBUG=1 elif ( str(arg) == '-x' or str(arg) == '--stop'): STOP=1 elif ( str(arg) == '-i' or str(arg) == '--invariant'): INVARIANT=1 elif ( str(arg) == '-d' or str(arg) == '--discover'): DISCOVERONLY=1 elif ( str(arg) == '-c' or str(arg) == '--continue'): CONTINUE=1 | |
printf -v _indent "\n\t" # local format helper | |
_indent = "\n\t" | |
_assert_reset() { tests_ran=0 tests_failed=0 tests_errors=() tests_starttime="$(date +%s.%N)" # seconds_since_epoch.nanoseconds } | |
# local format helper | |
def _assert_reset () : global tests_ran global tests_failed global tests_errors global tests_starttime tests_ran=0 tests_failed=0 tests_errors=() tests_starttime=str(os.popen("date +%s.%N").read()) | |
assert_end() { # assert_end [suite ..] tests_endtime="$(date +%s.%N)" tests="$tests_ran ${*:+$* }tests" [[ -n "$DISCOVERONLY" ]] && echo "collected $tests." && _assert_reset && return [[ -n "$DEBUG" ]] && echo [[ -z "$INVARIANT" ]] && report_time=" in $(bc \ <<< "${tests_endtime%.N} - ${tests_starttime%.N}" \ | sed -e 's/\.\([0-9]\{0,3\}\)[0-9]*/.\1/' -e 's/^\./0./')s" \ || report_time= if [[ "$tests_failed" -eq 0 ]]; then echo "all $tests passed$report_time." else for error in "${tests_errors[@]}"; do echo "$error"; done echo "$tests_failed of $tests failed$report_time." fi tests_failed_previous=$tests_failed [[ $tests_failed -gt 0 ]] && tests_suite_status=1 _assert_reset return $tests_failed_previous } | |
# seconds_since_epoch.nanoseconds | |
def assert_end () : global tests_endtime global tests global tests_ran global DISCOVERONLY global DEBUG global INVARIANT global report_time global tests_starttime global tests_failed global tests_errors global error global tests_failed_previous global tests_suite_status # assert_end [suite ..] | |
tests_endtime=str(os.popen("date +%s.%N").read()) tests=str(tests_ran) + " " + str('' if len(sys.argv) < 2 else " ".join(sys.argv[1:]) ) + "tests" (str(DISCOVERONLY) != '') and print("collected " + str(tests) + ".") and _assert_reset() and return (str(DEBUG) != '') and print() ('str(INVARIANT)' not in globals()) and report_time=" in " + str(os.popen("bc <<< \""+str(tests_endtime%.N)+" - "+str(tests_starttime%.N)+"\" | sed -e \"s/\\\\.\\\\([0-9]\\\\{0,3\\\\}\\\\)[0-9]*/.\\\\1/\" -e \"s/^\\\\./0./\"").read()) + "s" or report_time= if (str(tests_failed) == 0 ): print("all " + str(tests) + " passed" + str(report_time) + ".") else: for error in [str(tests_errors[@])]: print(str(error)) print(str(tests_failed) + " of " + str(tests) + " failed" + str(report_time) + ".") tests_failed_previous=tests_failed tests_failed > 0 and tests_suite_status=1 _assert_reset() return(tests_failed_previous) | |
assert() { # assert <command> <expected stdout> [stdin] (( tests_ran++ )) || : [[ -n "$DISCOVERONLY" ]] && return || true # printf required for formatting printf -v expected "x${2:-}" # x required to overwrite older results result="$(eval 2>/dev/null $1 <<< ${3:-})" || true # Note: $expected is already decorated if [[ "x$result" == "$expected" ]]; then [[ -n "$DEBUG" ]] && echo -n . || true 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" } | |
def assert () : global DISCOVERONLY global result global expected global DEBUG # assert <command> <expected stdout> [stdin] | |
tests_ran++ or (str(DISCOVERONLY) != '') and return or True # printf required for formatting | |
expected = "x" + str('' if dir().count('2') == 0 else sys.argv[2]) # x required to overwrite older results | |
result=str(os.popen("eval 2>/dev/null "+str(sys.argv[1])+" <<< "+str('' if dir().count('3') == 0 else sys.argv[3])).read()) or True # Note: $expected is already decorated | |
if ("x" + str(result) == str(expected) ): (str(DEBUG) != '') and print(.) or True return result=str(os.popen("sed -e :a -e \"\\"+str(DOLLAR_EXCLAMATION)+"N;s/\\\\n/\\\\\\\\n/;ta\" <<< \""+str(result)+"\"").read()) ('str(result)' not in globals()) and result="nothing" or result="\"" + str(result) + "\"" ('str(sys.argv[2])' not in globals()) and expected="nothing" or expected="\"" + str(sys.argv[2]) + "\"" _rc = subprocess.call(["_assert_fail","expected " + str(expected) + str(DOLLAR_UNDERBAR) + "got " + str(result),str(sys.argv[1]),str(sys.argv[3])]) | |
assert_raises() { # assert_raises <command> <expected code> [stdin] (( tests_ran++ )) || : [[ -n "$DISCOVERONLY" ]] && return || true status=0 (eval $1 <<< ${3:-}) > /dev/null 2>&1 || status=$? expected=${2:-0} if [[ "$status" -eq "$expected" ]]; then [[ -n "$DEBUG" ]] && echo -n . || true return fi _assert_fail "program terminated with code $status instead of $expected" "$1" "$3" } | |
def assert_raises () : global DISCOVERONLY global status global expected global DEBUG # assert_raises <command> <expected code> [stdin] | |
tests_ran++ or (str(DISCOVERONLY) != '') and return or True status=0 ( exec(sys.argv[1]) ) > /dev/null 2>&1 or status=_rc expected='0' if dir().count('2') == 0 or 2 == '' else sys.argv[2] if (str(status) == str(expected) ): (str(DEBUG) != '') and print(.) or True return _rc = subprocess.call(["_assert_fail","program terminated with code " + str(status) + " instead of " + str(expected),str(sys.argv[1]),str(sys.argv[3])]) | |
_assert_fail() { # _assert_fail <failure> <command> <stdin> [[ -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++ )) || : } | |
def _assert_fail () : global DEBUG global report global tests_ran global STOP global tests_errors global tests_failed # _assert_fail <failure> <command> <stdin> | |
(str(DEBUG) != '') and print("X") report="test #" + str(tests_ran) + " \"" + str(sys.argv[2]) + str('' if dir().count('3') == 0 or 3 == '' else <<< sys.argv[3]) + "\" failed:" + str(DOLLAR_UNDERBAR) + str(sys.argv[1]) if ((str(STOP) != '') ): (str(DEBUG) != '') and print() print(str(report)) exit(1) tests_errors[tests_failed]=str(report) tests_failed++ or | |
_assert_reset | |
_assert_reset() | |
: ${tests_suite_status:=0} # remember if any of the tests failed so far | |
tests_suite_status=('0' if dir().count('tests_suite_status') == 0 or tests_suite_status == '' else tests_suite_status) | |
_assert_cleanup() { local status=$? # modify exit code if it's not already non-zero [[ $status -eq 0 && -z $CONTINUE ]] && exit $tests_suite_status } | |
# remember if any of the tests failed so far | |
def _assert_cleanup () : global CONTINUE global tests_suite_status status=_rc # modify exit code if it's not already non-zero | |
status == 0 and ('CONTINUE' not in globals()) and exit(tests_suite_status) | |
trap _assert_cleanup EXIT | |
signal.signal(signal.SIGEXIT,_assert_cleanup) | |
ÿ |