Skip to content

Commit

Permalink
Merge pull request #44 from rico-chet/refute-equal-regex
Browse files Browse the repository at this point in the history
Add `refute_regex()`
  • Loading branch information
martin-schulze-vireso authored May 30, 2022
2 parents 6ad25d9 + baffb32 commit 990c47d
Show file tree
Hide file tree
Showing 4 changed files with 209 additions and 0 deletions.
44 changes: 44 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -728,6 +728,50 @@ Note that the `BASH_REMATCH` array is available immediately after the
assertion succeeds but is fragile, i.e. prone to being overwritten as a side
effect of other actions.

### `refute_regex`

This function is similar to `refute_equal` but uses pattern matching instead of
equality, by wrapping `! [[ value =~ pattern ]]`.

Fail if the value (first parameter) matches the pattern (second parameter).

```bash
@test 'refute_regex()' {
refute_regex 'WhatsApp' 'Threema'
}
```

On failure, the value, the pattern and the match are displayed.

```
@test 'refute_regex()' {
refute_regex 'WhatsApp' 'What.'
}
-- value matches regular expression --
value : WhatsApp
pattern : What.
match : Whats
case : sensitive
--
```

If the value or pattern is longer than one line then it is displayed in
*multi-line* format.

An error is displayed if the specified extended regular expression is invalid.

For description of the matching behavior, refer to the documentation of the
`=~` operator in the
[Bash manual]: https://www.gnu.org/software/bash/manual/html_node/Conditional-Constructs.html.

Note that the `BASH_REMATCH` array is available immediately after the assertion
fails but is fragile, i.e. prone to being overwritten as a side effect of other
actions like calling `run`. Thus, it's good practice to avoid using
`BASH_REMATCH` in conjunction with `refute_regex()`. The valuable information
the array contains is the matching part of the value which is printed in the
failing test log, as mentioned above.

<!-- REFERENCES -->

[bats]: https://github.com/bats-core/bats-core
Expand Down
1 change: 1 addition & 0 deletions load.bash
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,4 @@ source "$(dirname "${BASH_SOURCE[0]}")/src/refute_output.bash"
source "$(dirname "${BASH_SOURCE[0]}")/src/assert_line.bash"
source "$(dirname "${BASH_SOURCE[0]}")/src/refute_line.bash"
source "$(dirname "${BASH_SOURCE[0]}")/src/assert_regex.bash"
source "$(dirname "${BASH_SOURCE[0]}")/src/refute_regex.bash"
66 changes: 66 additions & 0 deletions src/refute_regex.bash
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
# `refute_regex`
#
# This function is similar to `refute_equal` but uses pattern matching instead
# of equality, by wrapping `! [[ value =~ pattern ]]`.
#
# Fail if the value (first parameter) matches the pattern (second parameter).
#
# ```bash
# @test 'refute_regex()' {
# refute_regex 'WhatsApp' 'Threema'
# }
# ```
#
# On failure, the value, the pattern and the match are displayed.
#
# ```
# @test 'refute_regex()' {
# refute_regex 'WhatsApp' 'What.'
# }
#
# -- value matches regular expression --
# value : WhatsApp
# pattern : What.
# match : Whats
# case : sensitive
# --
# ```
#
# If the value or pattern is longer than one line then it is displayed in
# *multi-line* format.
#
# An error is displayed if the specified extended regular expression is invalid.
#
# For description of the matching behavior, refer to the documentation of the
# `=~` operator in the
# [Bash manual]: https://www.gnu.org/software/bash/manual/html_node/Conditional-Constructs.html.
#
# Note that the `BASH_REMATCH` array is available immediately after the
# assertion fails but is fragile, i.e. prone to being overwritten as a side
# effect of other actions like calling `run`. Thus, it's good practice to avoid
# using `BASH_REMATCH` in conjunction with `refute_regex()`. The valuable
# information the array contains is the matching part of the value which is
# printed in the failing test log, as mentioned above.
refute_regex() {
local -r value="${1}"
local -r pattern="${2}"

if [[ '' =~ ${pattern} ]] || (( ${?} == 2 )); then
echo "Invalid extended regular expression: \`${pattern}'" \
| batslib_decorate 'ERROR: refute_regex' \
| fail
elif [[ "${value}" =~ ${pattern} ]]; then
if shopt -p nocasematch &>/dev/null; then
local case_sensitive=insensitive
else
local case_sensitive=sensitive
fi
batslib_print_kv_single_or_multi 8 \
'value' "${value}" \
'pattern' "${pattern}" \
'match' "${BASH_REMATCH[0]}" \
'case' "${case_sensitive}" \
| batslib_decorate 'value matches regular expression' \
| fail
fi
}
98 changes: 98 additions & 0 deletions test/refute_regex.bats
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
#!/usr/bin/env bats

load test_helper

#
# Literal matching
#

# Correctness
@test "refute_regex() <value> <pattern>: fails if a <value> substring matches extended regular expression <pattern>" {
run refute_regex 'abc' '^[a-z]b'
assert_test_fail <<'ERR_MSG'
-- value matches regular expression --
value : abc
pattern : ^[a-z]b
match : ab
case : sensitive
--
ERR_MSG
}

@test "refute_regex() <value> <pattern>: succeeds if no <value> substring matches extended regular expression <pattern>" {
run refute_regex 'bcd' '^[a-z]b[c-z]+'
assert_test_pass
}

@test "refute_regex() <value> <pattern>: provides results in BASH_REMATCH on failure" {
unset -v BASH_REMATCH

refute_regex 'abcd' 'b.d' \
|| {
declare -p BASH_REMATCH && \
[ "${BASH_REMATCH[0]}" = 'bcd' ]
}
}

@test "refute_regex() <value> <pattern>: matches case-insensitively when 'nocasematch' is set" {
shopt -s nocasematch

run refute_regex 'aBc' 'ABC'
assert_test_fail <<'ERR_MSG'
-- value matches regular expression --
value : aBc
pattern : ABC
match : aBc
case : insensitive
--
ERR_MSG
}

@test "refute_regex() <value> <pattern>: outputs multi-line <value> nicely when it fails" {
run refute_regex $'abc\n123' '^[a-z]b[c-z]+'
assert_test_fail <<'ERR_MSG'
-- value matches regular expression --
value (2 lines):
abc
123
pattern (1 lines):
^[a-z]b[c-z]+
match (1 lines):
abc
case (1 lines):
sensitive
--
ERR_MSG

shopt -s nocasematch
run refute_regex $'aBc\n123' '^[a-z]b[c-z]+'
assert_test_fail <<'ERR_MSG'
-- value matches regular expression --
value (2 lines):
aBc
123
pattern (1 lines):
^[a-z]b[c-z]+
match (1 lines):
aBc
case (1 lines):
insensitive
--
ERR_MSG
}

# Error handling
@test "refute_regex() <value> <pattern>: returns 1 and displays an error message if <pattern> is not a valid extended regular expression" {
run refute_regex value '[.*'

assert_test_fail <<'ERR_MSG'
-- ERROR: refute_regex --
Invalid extended regular expression: `[.*'
--
ERR_MSG
}

0 comments on commit 990c47d

Please sign in to comment.