lehmannro / assert.sh

bash unit testing framework
GNU Lesser General Public License v3.0
486 stars 57 forks source link

assert_contains function #10

Open jamesbriggs opened 10 years ago

jamesbriggs commented 10 years ago

Hi Robert.

Here's the assert_contains() function I wrote for regex matching.

Usage is: assert_contains "str" "regex" [0|1], where 0=expected match, 1=nomatch

assert_contains() {

assert_contains [expected](%28 tests_ran++ %29) || :

[[ -n "$DISCOVERONLY" ]] && return || true
str=${1:-}
regex=${2:-}
expected=${3:-0}
# status = 0 match, 1 = no match
status=1

# try the match. there's 3 possible outcomes:
#
#1) it may succeed and be captured if user specified parentheses: status=0 and match="something"
#2) it may succeed and not be captured if parentheses not used: status=0 and match=""
#3) it may fail to match: status=1 and match=""

match=""
if [[ $str =~ $regex ]]; then
    status=0
    match=${BASH_REMATCH[1]} # maybe some kind of capture is available
fi

if [[ "$status" -eq "$expected" ]]; then
    [[ -n "$DEBUG" ]] && echo -n . || true
    return
fi

if [ $status -eq 0 ] && [ -z "$match" ]; then
   if [[ $str =~ ($regex) ]]; then # the previous regex succeeded but no capture in $match, so try again with capturing parenthesess for debugging
      match=${BASH_REMATCH[1]}
   fi
fi

_assert_fail "match terminated with code $status and match '$match' instead of $expected" "$str" "$expected"

}

jamesbriggs commented 10 years ago

The beginning of code block should have read:

assert_contains() {

assert_contains <str> <regex> [expected](%28 tests_ran++ %29) || :

[[ -n "$DISCOVERONLY" ]] && return || true
str=${1:-}
regex=${2:-}
expected=${3:-0}
lehmannro commented 9 years ago

I think I would usually just pair assert with grep in these cases. Is there any clear advantage I'm missing? Otherwise I'd prefer not to introduce more complexity into the API.

dansoton commented 9 years ago

First of all, great project Robert, I was very happy to come across this.

Regarding this issue though, just an outsider's take on this is I think the trade off is where do you want the complexity - either in the tests written to use this framework, or in the underlying framework implementation.

I understand the desire to keep the assert API simple, but the fact I went searching for this functionality is probably an indication that assert_contains is perhaps fairly common request.

The downside with keeping it too simple is that people like me who will tire of writing: assert_raises "foo | grep bar &> /dev/null" 0

too many times instead of:

assert_contains "foo" "bar"

will have to write their own assert-extras.sh script to source alongside assert.sh to add these sort of functions. (I can see me also wanting assert_starts_with, and assert_matches for regex matching btw.)

On one hand this is probably exactly what should happen, everyone can write their own scripts separate to assert.sh to stop it getting bloated. However the fact we all have to write these fairly standard assertions means collective wasted time and more possibilities for bugs. Therefore if not added to assert.sh, a common assert-extras.sh in this github repo that people can source alongside if they want to, may be a nice middleground.

dansoton commented 9 years ago

As a follow-up I've created a Pull Request (https://github.com/lehmannro/assert.sh/pull/13) contributing this functionality as suggested above (in new optional assert-extras.sh).

Alternatively it is available in my fork: https://github.com/dansoton/assert.sh/tree/assert-extras