Skip to content

Commit

Permalink
Test suite type hint metadata fixturization x 3.
Browse files Browse the repository at this point in the history
This commit is the next 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.
(*Essen Sie delicate delicatessen!*)
  • Loading branch information
leycec committed Oct 31, 2023
1 parent 3a234ac commit 533df02
Show file tree
Hide file tree
Showing 10 changed files with 289 additions and 190 deletions.
16 changes: 11 additions & 5 deletions beartype_test/a00_unit/a40_api/door/a00_type/test_door_typehint.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
# See "LICENSE" for further details.

'''
**Beartype Decidedly Object-Oriented Runtime-checking (DOOR) API object-oriented
unit tests.**
Beartype **Decidedly Object-Oriented Runtime-checking (DOOR) API
object-oriented** unit tests.
This submodule unit tests the subset of the public API of the public
:mod:`beartype.door` subpackage that is object-oriented.
Expand Down Expand Up @@ -69,21 +69,27 @@ def test_door_typehint_new() -> None:
typehint = TypeHint(b'Is there, that from the boundaries of the sky')


def test_door_typehint_mapping() -> None:
def test_door_typehint_mapping(iter_hints_piths_meta) -> None:
'''
Test that the :meth:`beartype.door.TypeHint.__new__` factory method
successfully creates and returns an instance of a concrete subclass of the
abstract :class:`beartype.door.TypeHint` superclass conditionally handling
the kind of low-level type hint passed to that factory method.
Parameters
----------
iter_hints_piths_meta : Callable[[], Iterable[beartype_test.a00_unit.data.hint.util.data_hintmetautil.HintPithMetadata]]
Factory function creating and returning a generator iteratively yielding
``HintPithMetadata`` instances, each describing a sample type hint
exercising an edge case in the :mod:`beartype` codebase paired with a
related object either satisfying or violating that hint.
'''

# ....................{ IMPORTS }....................
# Defer test-specific imports.
from beartype.door import TypeHint
from beartype_test.a00_unit.data.hint.util.data_hintmetacls import (
HintPepMetadata)
from beartype_test.a00_unit.data.hint.util.data_hintmetautil import (
iter_hints_piths_meta)

# ....................{ ASSERTS }....................
# For each predefined type hint and associated metadata...
Expand Down
48 changes: 36 additions & 12 deletions beartype_test/a00_unit/a60_check/a90_door/test_checkdoor.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,17 @@
# Prevent pytest from capturing and displaying all expected non-fatal
# beartype-specific warnings emitted by this test. Urgh!
@ignore_warnings(BeartypeDecorHintPep585DeprecationWarning)
def test_door_die_if_unbearable() -> None:
def test_door_die_if_unbearable(iter_hints_piths_meta) -> None:
'''
Test the :class:`beartype.door.die_if_unbearable` raiser function.
Parameters
----------
iter_hints_piths_meta : Callable[[], Iterable[beartype_test.a00_unit.data.hint.util.data_hintmetautil.HintPithMetadata]]
Factory function creating and returning a generator iteratively yielding
``HintPithMetadata`` instances, each describing a sample type hint
exercising an edge case in the :mod:`beartype` codebase paired with a
related object either satisfying or violating that hint.
'''

# ....................{ IMPORTS }....................
Expand All @@ -38,8 +46,6 @@ def test_door_die_if_unbearable() -> None:
)
from beartype_test.a00_unit.data.hint.util.data_hintmetacls import (
HintPithUnsatisfiedMetadata)
from beartype_test.a00_unit.data.hint.util.data_hintmetautil import (
iter_hints_piths_meta)
from pytest import raises

# ....................{ PASS }....................
Expand Down Expand Up @@ -95,14 +101,22 @@ def test_door_die_if_unbearable() -> None:

# See above for @ignore_warnings() discussion.
@ignore_warnings(BeartypeDecorHintPep585DeprecationWarning)
def test_door_typehint_die_if_unbearable() -> None:
def test_door_typehint_die_if_unbearable(iter_hints_piths_meta) -> None:
'''
Test the :meth:`beartype.door.TypeHint.die_if_unbearable` raiser method.
This test intentionally tests only the core functionality of this tester to
avoid violating Don't Repeat Yourself (DRY). This tester internally defers
to the procedural :class:`beartype.door.die_if_unbearable` tester, already
exhaustively tested by preceding unit tests.
Parameters
----------
iter_hints_piths_meta : Callable[[], Iterable[beartype_test.a00_unit.data.hint.util.data_hintmetautil.HintPithMetadata]]
Factory function creating and returning a generator iteratively yielding
``HintPithMetadata`` instances, each describing a sample type hint
exercising an edge case in the :mod:`beartype` codebase paired with a
related object either satisfying or violating that hint.
'''

# ....................{ IMPORTS }....................
Expand All @@ -114,8 +128,6 @@ def test_door_typehint_die_if_unbearable() -> None:
)
from beartype_test.a00_unit.data.hint.util.data_hintmetacls import (
HintPithUnsatisfiedMetadata)
from beartype_test.a00_unit.data.hint.util.data_hintmetautil import (
iter_hints_piths_meta)
from contextlib import suppress
from pytest import raises

Expand Down Expand Up @@ -151,9 +163,17 @@ def test_door_typehint_die_if_unbearable() -> None:
# ....................{ TESTS ~ testers }....................
# See above for @ignore_warnings() discussion.
@ignore_warnings(BeartypeDecorHintPep585DeprecationWarning)
def test_door_is_bearable() -> None:
def test_door_is_bearable(iter_hints_piths_meta) -> None:
'''
Test the :class:`beartype.door.is_bearable` tester function.
Parameters
----------
iter_hints_piths_meta : Callable[[], Iterable[beartype_test.a00_unit.data.hint.util.data_hintmetautil.HintPithMetadata]]
Factory function creating and returning a generator iteratively yielding
``HintPithMetadata`` instances, each describing a sample type hint
exercising an edge case in the :mod:`beartype` codebase paired with a
related object either satisfying or violating that hint.
'''

# ..................{ IMPORTS }..................
Expand All @@ -166,8 +186,6 @@ def test_door_is_bearable() -> None:
)
from beartype_test.a00_unit.data.hint.util.data_hintmetacls import (
HintPithUnsatisfiedMetadata)
from beartype_test.a00_unit.data.hint.util.data_hintmetautil import (
iter_hints_piths_meta)
from beartype_test.a00_unit.data.hint.data_hint import HINTS_IGNORABLE
from pytest import raises

Expand Down Expand Up @@ -238,14 +256,22 @@ class RollsItsLoudWatersToTheOceanWaves(object):

# See above for @ignore_warnings() discussion.
@ignore_warnings(BeartypeDecorHintPep585DeprecationWarning)
def test_door_typehint_is_bearable() -> None:
def test_door_typehint_is_bearable(iter_hints_piths_meta) -> None:
'''
Test the :meth:`beartype.door.TypeHint.is_bearable` tester method.
This test intentionally tests only the core functionality of this tester to
avoid violating Don't Repeat Yourself (DRY). This tester internally defers
to the procedural :class:`beartype.door.is_bearable` tester, already
exhaustively tested by preceding unit tests.
Parameters
----------
iter_hints_piths_meta : Callable[[], Iterable[beartype_test.a00_unit.data.hint.util.data_hintmetautil.HintPithMetadata]]
Factory function creating and returning a generator iteratively yielding
``HintPithMetadata`` instances, each describing a sample type hint
exercising an edge case in the :mod:`beartype` codebase paired with a
related object either satisfying or violating that hint.
'''

# ....................{ IMPORTS }....................
Expand All @@ -254,8 +280,6 @@ def test_door_typehint_is_bearable() -> None:
from beartype.roar import BeartypeDoorNonpepException
from beartype_test.a00_unit.data.hint.util.data_hintmetacls import (
HintPithUnsatisfiedMetadata)
from beartype_test.a00_unit.data.hint.util.data_hintmetautil import (
iter_hints_piths_meta)
from contextlib import suppress

# ....................{ PASS }....................
Expand Down
12 changes: 9 additions & 3 deletions beartype_test/a00_unit/a70_decor/a60_main/test_beartype.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
# Prevent pytest from capturing and displaying all expected non-fatal
# beartype-specific warnings emitted by the @beartype decorator below. Urgh!
@ignore_warnings(BeartypeDecorHintPep585DeprecationWarning)
def test_beartype() -> None:
def test_beartype(iter_hints_piths_meta) -> None:
'''
Test the :func:`beartype.beartype` decorator with respect to type-checking
code dynamically generated by the
Expand All @@ -41,6 +41,14 @@ def test_beartype() -> None:
.. _issue #5:
https://github.com/beartype/beartype/issues/5
Parameters
----------
iter_hints_piths_meta : Callable[[], Iterable[beartype_test.a00_unit.data.hint.util.data_hintmetautil.HintPithMetadata]]
Factory function creating and returning a generator iteratively yielding
``HintPithMetadata`` instances, each describing a sample type hint
exercising an edge case in the :mod:`beartype` codebase paired with a
related object either satisfying or violating that hint.
'''

# ....................{ IMPORTS }....................
Expand All @@ -56,8 +64,6 @@ def test_beartype() -> None:
HintPepMetadata,
HintPithUnsatisfiedMetadata,
)
from beartype_test.a00_unit.data.hint.util.data_hintmetautil import (
iter_hints_piths_meta)
from beartype_test._util.pytroar import raises_uncached
# from pytest import warns
# from pytest import deprecated_call
Expand Down
6 changes: 6 additions & 0 deletions beartype_test/a00_unit/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,12 @@
# ....................{ IMPORTS }....................
# Import all subpackage-specific fixtures implicitly required by tests defined
# by submodules of this subpackage.
from beartype_test.a00_unit.data.hint.data_hint import (
hints_meta,
)
from beartype_test.a00_unit.data.hint.pep.data_pep import (
hints_pep_meta,
)
from beartype_test.a00_unit.data.hint.util.data_hintmetautil import (
iter_hints_piths_meta,
)
29 changes: 21 additions & 8 deletions beartype_test/a00_unit/data/hint/data_hint.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,17 +26,30 @@
HINTS_PEP_IGNORABLE_DEEP,
HINTS_PEP_META,
)
from pytest import fixture

# ....................{ HINTS ~ tuples }....................
HINTS_META = HINTS_PEP_META + HINTS_NONPEP_META
'''
Tuple of all **PEP-agnostic type hint metadata** (i.e.,
:class:`HintPepMetadata` instances describing test-specific type hints with
metadata leveraged by various testing scenarios -- including both PEP-compliant
and -noncompliant type hints).
'''
# ....................{ FIXTURES }....................
@fixture(scope='session')
def hints_meta(hints_pep_meta) -> 'List[HintNonpepMetadata]':
'''
Session-scoped fixture yielding a list 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
:mod:`beartype` codebase -- including both PEP-compliant and -noncompliant
type hints).
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.
'''

yield hints_pep_meta + HINTS_NONPEP_META

# ....................{ NON-HINTS ~ sets }....................
#FIXME: Refactor *ALL* remaining globals below into comparable fixtures, please.
NOT_HINTS_HASHABLE = frozenset((
# Scalar that is neither a type nor string (i.e., forward reference).
0.12345678910111213141516,
Expand Down
38 changes: 19 additions & 19 deletions beartype_test/a00_unit/data/hint/pep/data_pep.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,19 @@
# ....................{ IMPORTS }....................
from pytest import fixture

# ....................{ FIXTURES }....................
@fixture(scope='session')
def hints_pep_meta() -> 'List[HintPepMetadata]':
'''
Session-scoped fixture yielding a list of **PEP-compliant type hint
metadata** (i.e.,
:class:`beartype_test.a00_unit.data.hint.util.data_hintmetacls.HintPepMetadata`
instances, each describing a sample PEP-compliant type hint exercising an
edge case in the :mod:`beartype` codebase).
'''

yield HINTS_PEP_META

# ....................{ SETS }....................
# Initialized by the _init() function below.
HINTS_PEP_HASHABLE = None
Expand Down Expand Up @@ -122,18 +135,6 @@
'''

# ....................{ TUPLES }....................
@fixture(scope='session')
def hints_pep_meta() -> 'List[HintPepMetadata]':
'''
Session-scoped fixture returning a list of **type hint metadata** (i.e.,
:class:`beartype_test.a00_unit.data.hint.util.data_hintmetacls.HintPepMetadata`
instances, each describing a sample type hint exercising an edge case in the
:mod:`beartype` codebase).
'''

return HINTS_PEP_META


#FIXME: Replace all usage of this with the "hints_pep_meta" fixture, please.
# Initialized by the _init() function below.
HINTS_PEP_META = []
Expand Down Expand Up @@ -165,6 +166,8 @@ def _init() -> None:
hints_pep_meta_pep593)
from beartype_test.a00_unit.data.hint.pep.proposal._data_pep604 import (
hints_pep_meta_pep604)
from beartype_test.a00_unit.data.hint.pep.proposal._data_pep675 import (
hints_pep_meta_pep675)

# Submodule globals to be redefined below.
global \
Expand All @@ -178,6 +181,7 @@ def _init() -> None:
hints_pep_meta_pep589,
hints_pep_meta_pep593,
hints_pep_meta_pep604,
hints_pep_meta_pep675,
)

# For each fixture defining a "HINTS_PEP_META" subiterable, extend the main
Expand All @@ -199,10 +203,8 @@ def _init() -> None:
_data_pep544,
_data_pep585,
_data_pep586,
_data_pep589,
_data_pep593,
_data_pep604,
_data_pep675,
)

# Current submodule, obtained via the standard idiom. See also:
Expand All @@ -216,10 +218,8 @@ def _init() -> None:
_data_pep544,
_data_pep585,
_data_pep586,
# _data_pep589,
_data_pep593,
_data_pep604,
_data_pep675,
)

# Initialize all private submodules of this subpackage.
Expand All @@ -242,9 +242,9 @@ def _init() -> None:
# Frozen sets defined *AFTER* initializing these private submodules and
# thus the lower-level globals required by these sets.
HINTS_PEP_HASHABLE = frozenset(
hint_pep_meta.hint
for hint_pep_meta in HINTS_PEP_META
if is_object_hashable(hint_pep_meta.hint)
pep_meta.hint
for pep_meta in HINTS_PEP_META
if is_object_hashable(pep_meta.hint)
)
HINTS_PEP_IGNORABLE_DEEP = frozenset(HINTS_PEP_IGNORABLE_DEEP)
HINTS_PEP_IGNORABLE_SHALLOW = frozenset(HINTS_PEP_IGNORABLE_SHALLOW)
Expand Down
4 changes: 2 additions & 2 deletions beartype_test/a00_unit/data/hint/pep/proposal/_data_pep589.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,8 +103,8 @@ class ToMuse(TypedDict, total=False):
# PEP-noncompliant instance of an isinstanceable type.
separate_fantasy: Union[Type[Exception], bytes]

# ..................{ TUPLES }..................
# Add PEP-specific type hint metadata to this tuple global.
# ..................{ LISTS }..................
# Add PEP-specific type hint metadata to this list.
hints_pep_meta.extend((
# ................{ TYPEDDICT }................
# Empty typed dictionary. Look, this is ridiculous. What can you do?
Expand Down

0 comments on commit 533df02

Please sign in to comment.