Skip to content
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

Add assert_regex #43

Merged
merged 8 commits into from
May 29, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
}