-
Notifications
You must be signed in to change notification settings - Fork 56
Contributing assert-extras.sh #13
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
37740cc
5656971
ce33aea
50816b2
0667d56
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,76 @@ | ||
| #!/usr/bin/env bash | ||
|
|
||
| # assert-extras.sh 1.1 - supplementary bash unit testing functions | ||
| # Note: This script should be sourced together with assert.sh, | ||
| # it is dependent on the functionality provided by that script. | ||
|
|
||
| # assert_success <command> [stdin] | ||
| assert_success() { | ||
| assert_raises "$1" 0 "${2:-}" | ||
| } | ||
|
|
||
| # assert_failure <command> [stdin] | ||
| assert_failure() { | ||
| (( tests_ran++ )) || : | ||
| [[ -z "$DISCOVERONLY" ]] || return | ||
| status=0 | ||
| (eval "$1" <<< ${2:-}) > /dev/null 2>&1 || status=$? | ||
| if [[ "$status" != "0" ]]; then | ||
| [[ -z "$DEBUG" ]] || echo -n . | ||
| return | ||
| fi | ||
| _assert_fail "program terminated with a zero return code; expecting non-zero return code" \ | ||
| "$1" "$2" | ||
| } | ||
|
|
||
| # assert_contains <command> <expected output...> | ||
| assert_contains() { | ||
| _assert_with_grep '-F' "$@" | ||
| } | ||
|
|
||
| # assert_matches <command> <expected output...> | ||
| assert_matches() { | ||
| _assert_with_grep '-E' "$@" | ||
| } | ||
|
|
||
| # assert_startswith <command> <expected start to stdout> | ||
| assert_startswith() { | ||
| assert_success "[[ '$($1)' == '$2'* ]]" | ||
| } | ||
|
|
||
| # assert_endswith <command> <expected start to stdout> | ||
| assert_endswith() { | ||
| assert_success "[[ '$($1)' == *'$2' ]]" | ||
| } | ||
|
|
||
| # _assert_with_grep <grep modifiers> <command> <expected output...> | ||
| _assert_with_grep() { | ||
| local grep_modifier="$1" | ||
| local output="$($2)" | ||
| shift 2 | ||
|
|
||
| while [ $# != 0 ]; do | ||
| assert_raises "echo '$output' | $GREP $grep_modifier '$1'" 0 || return 1 | ||
| shift | ||
| done | ||
| } | ||
|
|
||
| # Returns the resolved command, preferring any gnu-versions of the cmd (prefixed with 'g') on | ||
| # non-Linux systems such as Mac OS, and falling back to the standard version if not. | ||
| _cmd() { | ||
| local cmd="$1" | ||
|
|
||
| local gnu_cmd="g$cmd" | ||
| local gnu_cmd_found=$(which "$gnu_cmd" 2> /dev/null) | ||
| if [ "$gnu_cmd_found" ]; then | ||
| echo "$gnu_cmd_found" | ||
| else | ||
| if [ "$(uname)" == 'Darwin' ]; then | ||
| echo "Warning: Cannot find gnu version of command '$cmd' ($gnu_cmd) on path." \ | ||
| "Falling back to standard command" >&2 | ||
| fi | ||
| echo "cmd" | ||
| fi | ||
| } | ||
|
|
||
| GREP=$(_cmd grep) | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -75,7 +75,7 @@ assert_end() { | |
| tests_endtime="$(date +%s%N)" | ||
| # required visible decimal place for seconds (leading zeros if needed) | ||
| local tests_time="$( \ | ||
| printf "%010d" "$(( ${tests_endtime/%N/000000000} | ||
| printf "%010d" "$(( ${tests_endtime/%N/000000000} | ||
| - ${tests_starttime/%N/000000000} ))")" # in ns | ||
| tests="$tests_ran ${*:+$* }tests" | ||
| [[ -n "$DISCOVERONLY" ]] && echo "collected $tests." && _assert_reset && return | ||
|
|
@@ -94,6 +94,8 @@ assert_end() { | |
| echo "$tests_failed of $tests failed$report_time." | ||
| fi | ||
| tests_failed_previous=$tests_failed | ||
| tests_ran_total=$(($tests_ran_total + $tests_ran)) | ||
| tests_failed_total=$(($tests_failed_total + $tests_failed)) | ||
| [[ $tests_failed -gt 0 ]] && tests_suite_status=1 | ||
| _assert_reset | ||
| } | ||
|
|
@@ -103,7 +105,7 @@ assert() { | |
| (( tests_ran++ )) || : | ||
| [[ -z "$DISCOVERONLY" ]] || return | ||
| expected=$(echo -ne "${2:-}") | ||
| result="$(eval 2>/dev/null $1 <<< ${3:-})" || true | ||
| result="$(eval 2>/dev/null "$1" <<< ${3:-})" || true | ||
|
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Wrapping the command ($1) in quotes for both assert and assert_raises enables support for multiline input. See new tests added to test.sh to prove this. |
||
| if [[ "$result" == "$expected" ]]; then | ||
| [[ -z "$DEBUG" ]] || echo -n . | ||
| return | ||
|
|
@@ -119,7 +121,7 @@ assert_raises() { | |
| (( tests_ran++ )) || : | ||
| [[ -z "$DISCOVERONLY" ]] || return | ||
| status=0 | ||
| (eval $1 <<< ${3:-}) > /dev/null 2>&1 || status=$? | ||
| (eval "$1" <<< ${3:-}) > /dev/null 2>&1 || status=$? | ||
| expected=${2:-0} | ||
| if [[ "$status" -eq "$expected" ]]; then | ||
| [[ -z "$DEBUG" ]] || echo -n . | ||
|
|
@@ -139,6 +141,7 @@ _assert_fail() { | |
| fi | ||
| tests_errors[$tests_failed]="$report" | ||
| (( tests_failed++ )) || : | ||
| return 1 | ||
|
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This allows us to check if an assertion has failed or not. For example we can now do: |
||
| } | ||
|
|
||
| skip_if() { | ||
|
|
@@ -178,6 +181,8 @@ _skip() { | |
|
|
||
| _assert_reset | ||
| : ${tests_suite_status:=0} # remember if any of the tests failed so far | ||
| : ${tests_ran_total:=0} # remember the total number of tests ran (inc. failures) | ||
| : ${tests_failed_total:=0} # remember the total number of test failures | ||
| _assert_cleanup() { | ||
| local status=$? | ||
| # modify exit code if it's not already non-zero | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,122 @@ | ||
| #!/usr/bin/env bash | ||
|
|
||
| source assert.sh | ||
| source assert-extras.sh | ||
|
|
||
| assert "echo foo" "foo" | ||
| assert_raises "true" 0 | ||
| assert_raises "exit 127" 127 | ||
|
|
||
| assert_end sanity | ||
|
|
||
| ### | ||
| ### assert_success tests | ||
| ### | ||
|
|
||
| # Tests expecting success | ||
| assert_success "true" | ||
| assert_success "echo foo" | ||
| assert_success "cat" "foo" | ||
|
|
||
| # Tests expecting failure | ||
| assert_raises 'assert_success "false"' 1 | ||
| assert_raises 'assert_success "exit 1"' 1 | ||
|
|
||
| assert_end assert_success | ||
|
|
||
| ### | ||
| ### assert_failure tests | ||
| ### | ||
|
|
||
| # Tests expecting success | ||
| assert_failure "false" | ||
| assert_failure "exit 1" | ||
| assert_failure "exit -1" | ||
| assert_failure "exit 42" | ||
| assert_failure "exit -42" | ||
|
|
||
| # Tests expecting failure | ||
| assert_raises 'assert_failure "true"' 1 | ||
| assert_raises 'assert_failure "echo foo"' 1 | ||
|
|
||
| assert_end assert_failure | ||
|
|
||
| ### | ||
| ### assert_contains tests | ||
| ### | ||
|
|
||
| # Tests expecting success | ||
| assert_contains "echo foo" "foo" | ||
| assert_contains "echo foobar" "foo" | ||
| assert_contains "echo foo bar" "foo" | ||
| assert_contains "echo foo bar" "bar" | ||
| assert_contains "echo foo bar" "foo bar" | ||
|
|
||
| # Tests expecting failure | ||
| assert_failure 'assert_contains "echo foo" "foot"' | ||
| assert_failure 'assert_contains "echo foo" "f.."' | ||
|
|
||
| # Multi-word argument tests | ||
| assert_contains "echo foo bar" "foo bar" | ||
| assert_failure 'assert_contains "echo foo; echo bar" "foo bar"' | ||
|
|
||
| # Multi-argument tests | ||
| assert_contains "echo foo bar baz" "foo" "baz" | ||
| assert_failure 'assert_contains "echo foo bar baz" "bar" "foo baz"' | ||
|
|
||
| assert_end assert_contains | ||
|
|
||
| ### | ||
| ### assert_matches tests | ||
| ### | ||
|
|
||
| # Tests expecting success | ||
| assert_matches "echo foo" "f.." | ||
| assert_matches "echo foobar" "f." | ||
| assert_matches "echo foo bar" "^foo bar$" | ||
| assert_matches "echo foo bar" "[az ]+" | ||
|
|
||
| # Tests expecting failure | ||
| assert_failure 'assert_matches "echo foot" "foo$"' | ||
|
|
||
| # Multi-word argument tests | ||
| assert_matches "echo foo bar" "foo .*" | ||
| assert_failure 'assert_matches "echo foo; echo bar" "foo .*"' | ||
|
|
||
| # Multi-argument tests | ||
| assert_matches "echo foo bar baz" "^f.." "baz$" | ||
| assert_failure 'assert_matches "echo foo bar baz" "bar" "foo baz"' | ||
|
|
||
| assert_end assert_matches | ||
|
|
||
| ### | ||
| ### assert_startswith tests | ||
| ### | ||
|
|
||
| # Tests expecting success | ||
| assert_startswith "echo foo" "f" | ||
| assert_startswith "echo foo" "foo" | ||
| assert_startswith "echo foo; echo bar" "foo" | ||
|
|
||
| # Tests expecting failure | ||
| assert_failure 'assert_startswith "echo foo" "oo"' | ||
| assert_failure 'assert_startswith "echo foo; echo bar" "foo bar"' | ||
| assert_failure 'assert_startswith "echo foo" "."' | ||
|
|
||
| assert_end assert_startswith | ||
|
|
||
| ### | ||
| ### assert_endswith tests | ||
| ### | ||
|
|
||
| # Tests expecting success | ||
| assert_endswith "echo foo" "oo" | ||
| assert_endswith "echo foo" "foo" | ||
| assert_endswith "echo foo; echo bar" "bar" | ||
|
|
||
| # Tests expecting failure | ||
| assert_failure 'assert_endswith "echo foo" "f"' | ||
| assert_failure 'assert_endswith "echo foo; echo bar" "foo bar"' | ||
| assert_failure 'assert_endswith "echo foo" "."' | ||
|
|
||
| assert_end assert_endswith |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,7 +1,5 @@ | ||
| #!/bin/bash | ||
|
|
||
| set -e | ||
|
|
||
| . assert.sh | ||
|
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We remove this because failed assertions now return an rc of 1 which would stop this test script with |
||
|
|
||
| assert "echo" # no output expected | ||
|
|
@@ -60,7 +58,7 @@ assert "_clean; skip_if false; assert_raises true; assert_end;" \ | |
| assert "_clean; skip_if bash -c 'exit 1'; assert_raises false; assert_end;" \ | ||
| "all 0 tests passed." | ||
| # subshells and pipes can be used in skip as well (albeit escaped) | ||
| assert "_clean; skip_if 'cat /etc/passwd | grep \$(echo \$USER)'; | ||
| assert "_clean; skip_if 'id | grep \$(echo \$USER)'; | ||
|
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This also works on Mac OS X, as the user isn't guaranteed to be in /etc/passwd on Mac OS. |
||
| assert_raises false; assert_end;" \ | ||
| "all 0 tests passed." | ||
| assert_end output | ||
|
|
@@ -96,8 +94,9 @@ assert "_clean; x=0; assert 'x=1'; assert_raises 'x=2'; echo \$x" 0 | |
| assert "_clean; x=0; assert 'export x=1'; assert_raises 'export x=2'; | ||
| echo \$x" 0 | ||
| # options do not leak | ||
| assert_raises "set +e" | ||
| assert_raises "shopt -o errexit" | ||
| assert_raises "shopt -o errexit" 1 | ||
|
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Because of the removal of |
||
| assert_raises "set -e" | ||
| assert_raises "shopt -o errexit" 1 | ||
| # skip properly resets all options | ||
| assert_raises "_clean; set +e; skip; assert_raises false; shopt -o errexit" 1 | ||
| assert_raises "_clean; set -e; skip; assert_raises false; shopt -o errexit" | ||
|
|
@@ -153,12 +152,18 @@ _date=22; | |
| assert_end" "all 1 tests passed in 2.000s." | ||
| # commit: supported formatting codes | ||
| assert "echo %s" "%s" | ||
| assert "echo -n %s | wc -c" "2" | ||
| # We trim the output from wc as the BSD version (on Mac OS) contains leading spaces | ||
| assert "echo -n %s | wc -c | tr -d '[[:space:]]'" "2" | ||
| # date with no nanosecond support | ||
| date() { # date mock | ||
| echo "123N" | ||
| } | ||
| assert '_clean DEBUG=1 INVARIANT=; tests_starttime="0N"; assert_end' \ | ||
| '\nall 0 tests passed in 123.000s.' | ||
| unset -f date # bring back original date | ||
| # commit: Supporting multiline inputs | ||
| # We trim the output from wc as the BSD version (on Mac OS) contains leading spaces | ||
| assert 'echo "this | ||
| is a multiline echo" | wc -l | tr -d "[[:space:]]"' "2" | ||
| assert 'echo -e "this\nis a multiline echo" | wc -l | tr -d "[[:space:]]"' "2" | ||
| assert_end regression | ||
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This needs to be
echo "$cmd".Right now this doesn't work in linux. Because the command it tries to use is
cmdinstead ofgrep. Tests in test-extras.sh fails with: