-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #16 from frank113/feature/issue-11_start_pytest_te…
…sting
- Loading branch information
Showing
11 changed files
with
246 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
name: CI Testing | ||
|
||
on: | ||
push: | ||
pull_request: | ||
|
||
workflow_dispatch: | ||
|
||
jobs: | ||
testing: | ||
runs-on: ubuntu-latest | ||
steps: | ||
- uses: actions/checkout@v2 | ||
- uses: actions/setup-python@v2 | ||
with: | ||
python-version: '3.x' | ||
|
||
- name: Install deps | ||
run: | | ||
pip3 --version | ||
pip3 install .[dev] | ||
- name: Run tests | ||
run: pytest | ||
|
||
code_style_checking: | ||
uses: ./.github/workflows/styling.yml |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -10,6 +10,7 @@ on: | |
paths: | ||
- "**.py" | ||
workflow_dispatch: | ||
workflow_call: | ||
|
||
jobs: | ||
code_style_checking: | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
from hypothesis import settings | ||
|
||
# Set default profile to use 500 examples | ||
settings.register_profile("default", max_examples=500) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
from hypothesis import strategies as st | ||
|
||
from regexfactory.pattern import ESCAPED_CHARACTERS | ||
|
||
# Strategy to generate characters that are not used in escapes | ||
non_escape_char = st.characters(blacklist_characters=list(ESCAPED_CHARACTERS)) | ||
|
||
|
||
# Strategy to generate text that avoids escaped characters | ||
non_escaped_text = st.text(min_size=1, alphabet=non_escape_char) | ||
|
||
|
||
# Strategy to produce either None or a positive integer | ||
optional_step = st.one_of(st.none(), st.integers(min_value=1)) | ||
|
||
|
||
def build_bounds(lower_bound, step) -> range: | ||
""" | ||
Function to generate a tuple of (lower, upper) in which lower < upper | ||
""" | ||
upper_bound = lower_bound + step | ||
return range(lower_bound, upper_bound + 1) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
from typing import Optional | ||
|
||
import pytest | ||
from hypothesis import given | ||
from hypothesis import strategies as st | ||
from strategies import build_bounds, optional_step | ||
|
||
from regexfactory import Amount, ValidPatternType | ||
|
||
|
||
def build_amount( | ||
pattern: ValidPatternType, | ||
start: int, | ||
or_more: bool, | ||
greedy: bool, | ||
step: Optional[int], | ||
): | ||
""" | ||
General Amount builder. Note that the `j` parameter is constructed as | ||
the step plus start when step is defined. When step is None we assume | ||
that no upper bound is present. | ||
""" | ||
stop_value = None | ||
if step is not None: | ||
stop_value = start + step | ||
return Amount( | ||
pattern=pattern, i=start, j=stop_value, or_more=or_more, greedy=greedy | ||
) | ||
|
||
|
||
@pytest.mark.patterns | ||
@given(st.text(min_size=1), st.integers(min_value=1)) | ||
def test_amount_single_count(word, count): | ||
""" | ||
Test to ensure that when `or_more=False` and no upper bound is | ||
provided the regex will be of the form word{count}. | ||
""" | ||
actual = Amount(word, i=count, or_more=False) | ||
assert actual.regex == "{word}{{{count}}}".format(word=word, count=str(count)) | ||
|
||
|
||
@pytest.mark.patterns | ||
@given( | ||
st.text(min_size=1), | ||
st.builds( | ||
build_bounds, | ||
lower_bound=st.integers(min_value=1), | ||
step=st.integers(min_value=1), | ||
), | ||
) | ||
def test_amount_lower_upper(word, bound: range): | ||
""" | ||
Test to ensure that if a lower and upper bound are provided then the | ||
regex of the resulting `Amount` will be of the form {word}{lower,upper}. | ||
""" | ||
actual = Amount(word, bound.start, bound.stop) | ||
expected = "{word}{{{lower},{upper}}}".format( | ||
word=word, lower=str(bound.start), upper=str(bound.stop) | ||
) | ||
assert actual.regex == expected | ||
|
||
|
||
@pytest.mark.patterns | ||
@given(st.text(min_size=1), st.integers(min_value=1)) | ||
def test_amount_or_more(word, count): | ||
""" | ||
Test to ensure that when `or_more=True` and no upper bound is | ||
provided the regex will be of the form word{count,}. | ||
""" | ||
actual = Amount(word, count, or_more=True) | ||
assert actual.regex == "{word}{{{count},}}".format(word=word, count=str(count)) | ||
|
||
|
||
@pytest.mark.patterns | ||
@given( | ||
st.builds( | ||
build_amount, | ||
pattern=st.text(min_size=1), | ||
start=st.integers(min_value=1), | ||
or_more=st.booleans(), | ||
greedy=st.just(False), | ||
step=optional_step, | ||
) | ||
) | ||
def test_amount_non_greedy(amt): | ||
""" | ||
Test to ensure that instances of Amount with greedy as False will end with "?" | ||
""" | ||
assert amt.regex.endswith("?") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
import pytest | ||
from hypothesis import example, given | ||
from hypothesis import strategies as st | ||
from strategies import non_escaped_text | ||
|
||
from regexfactory.pattern import join | ||
|
||
|
||
@pytest.mark.pattern | ||
@given(st.lists(elements=non_escaped_text, min_size=1, max_size=10, unique=True)) | ||
@example(words=["0", "1"]) | ||
def test_join(words: list): | ||
""" | ||
Tests to capture that the join function concatenates the expressions and | ||
each word in the list is found in the larger regex. | ||
""" | ||
joined_regex = join(*words) | ||
assert joined_regex.regex == "".join(words) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
import re | ||
|
||
import pytest | ||
from hypothesis import example, given | ||
from hypothesis import strategies as st | ||
from strategies import non_escaped_text | ||
|
||
from regexfactory import Or | ||
|
||
|
||
@pytest.mark.patterns | ||
@given( | ||
st.lists( | ||
non_escaped_text, | ||
min_size=1, | ||
max_size=10, | ||
) | ||
) | ||
@example(arr=["0", "0"]) | ||
def test_matching_or(arr: list): | ||
actual = Or(*arr) | ||
if len(arr) == 1: | ||
assert isinstance(actual.match(arr[0]), re.Match) | ||
else: | ||
for value in arr: | ||
assert isinstance(actual.match(value), re.Match) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
import pytest | ||
|
||
from regexfactory import Range | ||
|
||
|
||
@pytest.mark.patterns | ||
def test_numeric_range(): | ||
start = "0" | ||
end = "9" | ||
assert Range(start, end).regex == "[0-9]" | ||
|
||
|
||
@pytest.mark.patterns | ||
@pytest.mark.parametrize( | ||
"start, stop, expected", | ||
[ | ||
("0", "9", "[0-9]"), | ||
("a", "f", "[a-f]"), | ||
("r", "q", "[r-q]"), | ||
("A", "Z", "[A-Z]"), | ||
], | ||
) | ||
def test_range_parameters(start, stop, expected): | ||
actual = Range(start=start, stop=stop) | ||
assert actual.regex == expected |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
import re | ||
|
||
import pytest | ||
from hypothesis import given | ||
from hypothesis import strategies as st | ||
from strategies import non_escape_char | ||
|
||
from regexfactory import Set | ||
|
||
|
||
@pytest.mark.patterns | ||
@given(st.lists(elements=non_escape_char, min_size=1)) | ||
def test_set(chars: list): | ||
actual = Set(*chars) | ||
for value in chars: | ||
assert isinstance(actual.match(value), re.Match) |