Skip to content

Commit

Permalink
Merge pull request #43 from rico-chet/assert-equal-regexp
Browse files Browse the repository at this point in the history
 Add `assert_regex`
  • Loading branch information
martin-schulze-vireso authored May 29, 2022
2 parents 397c735 + d950f28 commit 6ad25d9
Show file tree
Hide file tree
Showing 4 changed files with 174 additions and 0 deletions.
35 changes: 35 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -693,6 +693,41 @@ An error is displayed if the specified extended regular expression is invalid.
This option and partial matching (`--partial` or `-p`) are mutually exclusive.
An error is displayed when used simultaneously.

### `assert_regex`

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

Fail if the value (first parameter) does not match the pattern (second
parameter).

```bash
@test 'assert_regex()' {
assert_regex 'what' 'x$'
}
```

On failure, the value and the pattern are displayed.

```
-- values does not match regular expression --
value : what
pattern : x$
--
```

If the value 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 succeeds but is fragile, i.e. prone to being overwritten as a side
effect of other actions.

<!-- 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 @@ -29,3 +29,4 @@ source "$(dirname "${BASH_SOURCE[0]}")/src/assert_output.bash"
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"
56 changes: 56 additions & 0 deletions src/assert_regex.bash
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
# `assert_regex`
#
# This function is similar to `assert_equal` but uses pattern matching instead
# of equality, by wrapping `[[ value =~ pattern ]]`.
#
# Fail if the value (first parameter) does not match the pattern (second
# parameter).
#
# ```bash
# @test 'assert_regex()' {
# assert_regex 'what' 'x$'
# }
# ```
#
# On failure, the value and the pattern are displayed.
#
# ```
# -- values does not match regular expression --
# value : what
# pattern : x$
# --
# ```
#
# If the value 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 succeeds but is fragile, i.e. prone to being overwritten as a side
# effect of other actions.
assert_regex() {
local -r value="${1}"
local -r pattern="${2}"

if [[ '' =~ ${pattern} ]] || (( ${?} == 2 )); then
echo "Invalid extended regular expression: \`${pattern}'" \
| batslib_decorate 'ERROR: assert_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}" \
'case' "${case_sensitive}" \
| batslib_decorate 'value does not match regular expression' \
| fail
fi
}
82 changes: 82 additions & 0 deletions test/assert_regex.bats
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
#!/usr/bin/env bats

load test_helper

#
# Literal matching
#

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

@test "assert_regex() <value> <pattern>: fails if no <value> substring matches extended regular expression <pattern>" {
run assert_regex 'bcd' '^[a-z]b[c-z]+'
assert_test_fail <<'ERR_MSG'
-- value does not match regular expression --
value : bcd
pattern : ^[a-z]b[c-z]+
case : sensitive
--
ERR_MSG
}

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

assert_regex 'abcd' 'b.d'
declare -p BASH_REMATCH
[ "${BASH_REMATCH[0]}" = 'bcd' ]
}

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

assert_regex 'aBc' 'ABC'
}

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

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

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

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

0 comments on commit 6ad25d9

Please sign in to comment.