Skip to content

Commit

Permalink
Test suite type hint metadata fixturization x 7.
Browse files Browse the repository at this point in the history
This commit is the last in a commit chain fundamentally refactoring our
test suite to leverage space- and time-efficient `pytest` session-scoped
fixtures rather than space- and time-inefficient ad-hoc machinery
previously defined by the `beartype_test.a00_unit.data.hint.pep`
subpackage, which @leycec requires to preserve personal sanity while
maintaining this lumbering juggernaut but nobody else particularly cares
about. It's best *not* to ask what this is about. Just know that our
test suite is demonstrably improving into something maintainable that
will no longer destroy @leycec's precious sanity points.
(*Cylindrical cyanide iodide, dude!*)
  • Loading branch information
leycec committed Nov 4, 2023
1 parent fcb5d67 commit 744182f
Show file tree
Hide file tree
Showing 6 changed files with 328 additions and 259 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
# --------------------( LICENSE )--------------------
# --------------------( LICENSE )--------------------
# Copyright (c) 2014-2023 Beartype authors.
# See "LICENSE" for further details.

Expand All @@ -10,34 +10,42 @@
:mod:`beartype._util.hint.nonpep.utilnonpeptest` submodule.
'''

# ....................{ IMPORTS }....................
#!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
# ....................{ IMPORTS }....................
#!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
# WARNING: To raise human-readable test errors, avoid importing from
# package-specific submodules at module scope.
#!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
from pytest import raises
#!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

# ....................{ TESTS ~ validator }....................
def test_die_unless_hint_nonpep() -> None:
# ....................{ TESTS ~ validator }....................
def test_die_unless_hint_nonpep(not_hints_nonpep) -> None:
'''
Test the
:func:`beartype._util.hint.nonpep.utilnonpeptest.die_unless_hint_nonpep`
validator.
Parameters
----------
not_hints_nonpep : frozenset
Frozen set of various objects that are *not* PEP-noncompliant type hints
exercising well-known edge cases.
'''

# Defer test-specific imports.
from beartype.roar import BeartypeDecorHintNonpepException
from beartype._util.hint.nonpep.utilnonpeptest import (
die_unless_hint_nonpep)
from beartype_test.a00_unit.data.hint.data_hint import (
NOT_HINTS_UNHASHABLE, HINTS_NONPEP, NOT_HINTS_NONPEP,)
HINTS_NONPEP,
NOT_HINTS_UNHASHABLE,
)
from pytest import raises

# Assert this function accepts PEP-noncompliant type hints.
for hint_nonpep in HINTS_NONPEP:
die_unless_hint_nonpep(hint_nonpep)

# Assert this function rejects objects excepted to be rejected.
for not_hint_nonpep in NOT_HINTS_NONPEP:
for not_hint_nonpep in not_hints_nonpep:
with raises(BeartypeDecorHintNonpepException):
die_unless_hint_nonpep(not_hint_nonpep)

Expand All @@ -46,25 +54,33 @@ def test_die_unless_hint_nonpep() -> None:
with raises(BeartypeDecorHintNonpepException):
die_unless_hint_nonpep(not_hint_unhashable)

# ....................{ TESTS ~ tester }....................
def test_is_hint_nonpep() -> None:
# ....................{ TESTS ~ tester }....................
def test_is_hint_nonpep(not_hints_nonpep) -> None:
'''
Test the
:func:`beartype._util.hint.nonpep.utilnonpeptest.is_hint_nonpep`
tester.
Parameters
----------
not_hints_nonpep : frozenset
Frozen set of various objects that are *not* PEP-noncompliant type hints
exercising well-known edge cases.
'''

# Defer test-specific imports.
from beartype._util.hint.nonpep.utilnonpeptest import is_hint_nonpep
from beartype_test.a00_unit.data.hint.data_hint import (
NOT_HINTS_UNHASHABLE, HINTS_NONPEP, NOT_HINTS_NONPEP,)
HINTS_NONPEP,
NOT_HINTS_UNHASHABLE,
)

# Assert this function accepts PEP-noncompliant type hints.
for hint_nonpep in HINTS_NONPEP:
assert is_hint_nonpep(hint=hint_nonpep, is_str_valid=True) is True

# Assert this function rejects objects excepted to be rejected.
for not_hint_nonpep in NOT_HINTS_NONPEP:
for not_hint_nonpep in not_hints_nonpep:
assert is_hint_nonpep(hint=not_hint_nonpep, is_str_valid=True) is False

# Assert this function rejects unhashable objects.
Expand All @@ -73,26 +89,33 @@ def test_is_hint_nonpep() -> None:
hint=non_hint_unhashable, is_str_valid=True) is False


def test_is_hint_nonpep_tuple() -> None:
def test_is_hint_nonpep_tuple(not_hints_nonpep) -> None:
'''
Test the
:func:`beartype._util.hint.nonpep.utilnonpeptest._is_hint_nonpep_tuple`
tester.
Parameters
----------
not_hints_nonpep : frozenset
Frozen set of various objects that are *not* PEP-noncompliant type hints
exercising well-known edge cases.
'''

# Defer test-specific imports.
from beartype._util.hint.nonpep.utilnonpeptest import (
_is_hint_nonpep_tuple)
from beartype._util.hint.nonpep.utilnonpeptest import _is_hint_nonpep_tuple
from beartype_test.a00_unit.data.hint.data_hint import (
NOT_HINTS_UNHASHABLE, HINTS_NONPEP, NOT_HINTS_NONPEP,)
HINTS_NONPEP,
NOT_HINTS_UNHASHABLE,
)

# Assert this function accepts PEP-noncompliant tuples.
for hint_nonpep in HINTS_NONPEP:
assert _is_hint_nonpep_tuple(hint_nonpep, True) is isinstance(
hint_nonpep, tuple)

# Assert this function rejects objects excepted to be rejected.
for not_hint_nonpep in NOT_HINTS_NONPEP:
for not_hint_nonpep in not_hints_nonpep:
assert _is_hint_nonpep_tuple(not_hint_nonpep, True) is False

# Assert this function rejects unhashable objects.
Expand Down
2 changes: 2 additions & 0 deletions beartype_test/a00_unit/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,10 @@
# by submodules of this subpackage.
from beartype_test.a00_unit.data.hint.data_hint import (
hints_meta,
not_hints_nonpep,
)
from beartype_test.a00_unit.data.hint.pep.data_pep import (
hints_pep_hashable,
hints_pep_meta,
)
from beartype_test.a00_unit.data.hint.util.data_hintmetautil import (
Expand Down
83 changes: 45 additions & 38 deletions beartype_test/a00_unit/data/hint/data_hint.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,18 +21,16 @@
HINTS_NONPEP_META,
)
from beartype_test.a00_unit.data.hint.pep.data_pep import (
HINTS_PEP_HASHABLE,
HINTS_PEP_IGNORABLE_SHALLOW,
HINTS_PEP_IGNORABLE_DEEP,
HINTS_PEP_META,
)
from pytest import fixture

# ....................{ FIXTURES }....................
@fixture(scope='session')
def hints_meta(hints_pep_meta) -> 'List[HintNonpepMetadata]':
def hints_meta(hints_pep_meta) -> 'Tuple[HintNonpepMetadata]':
'''
Session-scoped fixture yielding a list of **PEP-agnostic type hint
Session-scoped fixture yielding a tuple of **PEP-agnostic type hint
metadata** (i.e.,
:class:`beartype_test.a00_unit.data.hint.util.data_hintmetacls.HintNonpepMetadata`
instances, each describing a sample type hint exercising an edge case in the
Expand All @@ -41,13 +39,53 @@ def hints_meta(hints_pep_meta) -> 'List[HintNonpepMetadata]':
Parameters
----------
hints_pep_meta : List[beartype_test.a00_unit.data.hint.util.data_hintmetacls.HintPepMetadata]
List of PEP-compliant type hint metadata describing sample PEP-compliant
type hints exercising edge cases in the :mod:`beartype` codebase.
hints_pep_meta : Tuple[beartype_test.a00_unit.data.hint.util.data_hintmetacls.HintPepMetadata]
Tuple of PEP-compliant type hint metadata describing PEP-compliant type
hints exercising edge cases in the :mod:`beartype` codebase.
'''

yield hints_pep_meta + HINTS_NONPEP_META

# ....................{ FIXTURES ~ not : sets }....................
@fixture(scope='session')
def not_hints_nonpep(hints_pep_hashable) -> frozenset:
'''
Session-scoped fixture yielding a frozen set of various objects that are
*not* PEP-noncompliant type hints exercising well-known edge cases.
Parameters
----------
hints_pep_hashable : frozenset
Tuple of PEP-compliant type hint metadata describing PEP-compliant type
hints exercising edge cases in the :mod:`beartype` codebase.
'''

yield frozenset((
# Set comprehension of tuples containing PEP-compliant type hints. Although
# tuples containing PEP-noncompliant type hints are themselves valid
# PEP-noncompliant type hints supported by @beartype, tuples containing
# PEP-compliant type hints are invalid and thus unsupported.
{
# Tuple containing this PEP-compliant type hint...
(int, hint_pep_hashable, NoneType,)
# For each hashable PEP-compliant type hint...
for hint_pep_hashable in hints_pep_hashable
# That is neither:
# * An isinstanceable class.
# * A string-based forward reference.
#
# Both are unique edge cases supported as both PEP 484-compliant outside
# tuples *AND* beartype-specific inside tuples. Including these hints
# here would erroneously cause tests to treat tuples containing these
# hints as *NOT* tuple type hints.
if not isinstance(hint_pep_hashable, (str, type))
} |
# Set comprehension of hashable PEP-compliant non-class type hints.
hints_pep_hashable |
# Hashable objects invalid as type hints (e.g., scalars).
NOT_HINTS_HASHABLE
))

# ....................{ NON-HINTS ~ sets }....................
#FIXME: Refactor *ALL* remaining globals below into comparable fixtures, please.
NOT_HINTS_HASHABLE = frozenset((
Expand Down Expand Up @@ -155,37 +193,6 @@ def __repr__(self) -> str:
'''

# ....................{ NOT ~ sets }....................
NOT_HINTS_NONPEP = frozenset((
# Set comprehension of tuples containing PEP-compliant type hints. Although
# tuples containing PEP-noncompliant type hints are themselves valid
# PEP-noncompliant type hints supported by @beartype, tuples containing
# PEP-compliant type hints are invalid and thus unsupported.
{
# Tuple containing this PEP-compliant type hint...
(int, hint_pep_hashable, NoneType,)
# For each hashable PEP-compliant type hint...
for hint_pep_hashable in HINTS_PEP_HASHABLE
# That is neither:
# * An isinstanceable class.
# * A string-based forward reference.
#
# Both are unique edge cases supported as both PEP 484-compliant outside
# tuples *AND* beartype-specific inside tuples. Including these hints
# here would erroneously cause tests to treat tuples containing these
# hints as *NOT* tuple type hints.
if not isinstance(hint_pep_hashable, (str, type))
} |
# Set comprehension of hashable PEP-compliant non-class type hints.
HINTS_PEP_HASHABLE |
# Hashable objects invalid as type hints (e.g., scalars).
NOT_HINTS_HASHABLE
))
'''
Tuple of various objects that are *not* PEP-noncompliant type hints exercising
well-known edge cases.
'''


NOT_HINTS_PEP = (
# PEP-noncompliant type hints.
HINTS_NONPEP |
Expand Down

0 comments on commit 744182f

Please sign in to comment.