Skip to content

Commit

Permalink
🧪 Integrate Hypothesis in tests (#860)
Browse files Browse the repository at this point in the history
Co-authored-by: Sviatoslav Sydorenko (Святослав Сидоренко) <wk.cvs.github@sydorenko.org.ua>
Co-authored-by: J. Nick Koston <nick@koston.org>
  • Loading branch information
3 people authored Oct 5, 2024
1 parent 755ba9c commit ba2c6f7
Show file tree
Hide file tree
Showing 4 changed files with 97 additions and 0 deletions.
4 changes: 4 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@ repos:
alias: mypy-py313
name: MyPy, for Python 3.13
additional_dependencies:
- hypothesis
- lxml # dep of `--txt-report`, `--cobertura-xml-report` & `--html-report`
- multidict
- pytest
Expand All @@ -128,6 +129,7 @@ repos:
alias: mypy-py312
name: MyPy, for Python 3.12
additional_dependencies:
- hypothesis
- lxml # dep of `--txt-report`, `--cobertura-xml-report` & `--html-report`
- multidict
- pytest
Expand All @@ -143,6 +145,7 @@ repos:
alias: mypy-py310
name: MyPy, for Python 3.10
additional_dependencies:
- hypothesis
- lxml # dep of `--txt-report`, `--cobertura-xml-report` & `--html-report`
- multidict
- pytest
Expand All @@ -160,6 +163,7 @@ repos:
alias: mypy-py38
name: MyPy, for Python 3.8
additional_dependencies:
- hypothesis
- lxml # dep of `--txt-report`, `--cobertura-xml-report` & `--html-report`
- multidict
- pytest
Expand Down
3 changes: 3 additions & 0 deletions CHANGES/860.contrib.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Started testing with Hypothesis -- by :user:`webknjaz` and :user:`bdraco`.

Special thanks to :user:`Zac-HD` for helping us get started with this framework.
1 change: 1 addition & 0 deletions requirements/test.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
-r cython.txt
covdefaults
hypothesis>=6.0
idna==3.10
multidict==6.1.0
pytest==8.3.3
Expand Down
89 changes: 89 additions & 0 deletions tests/test_quoting.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
from typing import Type

import pytest
from hypothesis import assume, example, given, note
from hypothesis import strategies as st

from yarl._quoting import NO_EXTENSIONS
from yarl._quoting_py import _Quoter as _PyQuoter
Expand All @@ -16,6 +20,10 @@ def quoter(request):
def unquoter(request):
return request.param

quoters = [_PyQuoter, _CQuoter]
quoter_ids = ["PyQuoter", "CQuoter"]
unquoters = [_PyUnquoter, _CUnquoter]
unquoter_ids = ["PyUnquoter", "CUnquoter"]
else:

@pytest.fixture(params=[_PyQuoter], ids=["py_quoter"])
Expand All @@ -26,6 +34,11 @@ def quoter(request):
def unquoter(request):
return request.param

quoters = [_PyQuoter]
quoter_ids = ["PyQuoter"]
unquoters = [_PyUnquoter]
unquoter_ids = ["PyUnquoter"]


def hexescape(char):
"""Escape char as RFC 2396 specifies"""
Expand Down Expand Up @@ -455,3 +468,79 @@ def test_quoter_path_with_plus(quoter):
def test_unquoter_path_with_plus(unquoter):
s = "/test/x+y%2Bz/:+%2B/"
assert "/test/x+y+z/:++/" == unquoter(unsafe="+")(s)


@given(safe=st.text(), protected=st.text(), qs=st.booleans(), requote=st.booleans())
def test_fuzz__PyQuoter(safe, protected, qs, requote):
"""Verify that _PyQuoter can be instantiated with any valid arguments."""
assert _PyQuoter(safe=safe, protected=protected, qs=qs, requote=requote)


@given(ignore=st.text(), unsafe=st.text(), qs=st.booleans())
def test_fuzz__PyUnquoter(ignore, unsafe, qs):
"""Verify that _PyUnquoter can be instantiated with any valid arguments."""
assert _PyUnquoter(ignore=ignore, unsafe=unsafe, qs=qs)


@example(text_input="0")
@given(
text_input=st.text(
alphabet=st.characters(max_codepoint=127, blacklist_characters="%")
),
)
@pytest.mark.parametrize("quoter", quoters, ids=quoter_ids)
@pytest.mark.parametrize("unquoter", unquoters, ids=unquoter_ids)
def test_quote_unquote_parameter(
quoter: Type[_PyQuoter],
unquoter: Type[_PyUnquoter],
text_input: str,
) -> None:
quote = quoter()
unquote = unquoter()
text_quoted = quote(text_input)
note(f"text_quoted={text_quoted!r}")
text_output = unquote(text_quoted)
assert text_input == text_output


@example(text_input="0")
@given(
text_input=st.text(
alphabet=st.characters(max_codepoint=127, blacklist_characters="%")
),
)
@pytest.mark.parametrize("quoter", quoters, ids=quoter_ids)
@pytest.mark.parametrize("unquoter", unquoters, ids=unquoter_ids)
def test_quote_unquote_parameter_requote(
quoter: Type[_PyQuoter],
unquoter: Type[_PyUnquoter],
text_input: str,
) -> None:
quote = quoter(requote=True)
unquote = unquoter()
text_quoted = quote(text_input)
note(f"text_quoted={text_quoted!r}")
text_output = unquote(text_quoted)
assert text_input == text_output


@example(text_input="0")
@given(
text_input=st.text(
alphabet=st.characters(max_codepoint=127, blacklist_characters="%")
),
)
@pytest.mark.parametrize("quoter", quoters, ids=quoter_ids)
@pytest.mark.parametrize("unquoter", unquoters, ids=unquoter_ids)
def test_quote_unquote_parameter_path_safe(
quoter: Type[_PyQuoter],
unquoter: Type[_PyUnquoter],
text_input: str,
) -> None:
quote = quoter()
unquote = unquoter(ignore="/%", unsafe="+")
assume("+" not in text_input and "/" not in text_input)
text_quoted = quote(text_input)
note(f"text_quoted={text_quoted!r}")
text_output = unquote(text_quoted)
assert text_input == text_output

0 comments on commit ba2c6f7

Please sign in to comment.