Skip to content

Commit

Permalink
feat!: add type annotation check (#5)
Browse files Browse the repository at this point in the history
* feat!: type check meta defaults

* feat!: type check args
  • Loading branch information
movedempackets authored Aug 11, 2024
1 parent 09b9907 commit c72a2b9
Show file tree
Hide file tree
Showing 11 changed files with 287 additions and 77 deletions.
2 changes: 1 addition & 1 deletion tests/functional/test_functional_nodes_leaf_list_node.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ def test_given_instance_of_leaf_list_node_subclass_with_entries_when_to_xml_is_c
user.append((john := "John Doe"))
user.append((jane := "Jane Doe"))

# When to_xml is called.
# When to_xml is called with attrs.
xml = user.to_xml(attrs={"operation": "create"})

# Then for each entry XML element with attrs returned.
Expand Down
2 changes: 2 additions & 0 deletions tests/functional/test_functional_nodes_node.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ class ContainerNode(Node):
class Interfaces(ContainerNode):
"""Represents a subclass of ContainerNode."""

__identifier__ = "interfaces"


def test_when_node_instantiated_then_exception_is_raised():
"""Test when node instantiated then exception is raised."""
Expand Down
14 changes: 9 additions & 5 deletions tests/unit/test_unit_nodes_init_node.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,11 @@
from yapyang.nodes import InitNode, Node


class MockInitNode(InitNode):
class InitNodeSubclass(InitNode):
"""Represents a subclass of InitNode."""

__identifier__ = "init_node_subclass"


@patch.object(Node, "__init__")
def test_given_init_node_subclass_when_instantiated_then_node_initializer_called(
Expand All @@ -23,7 +25,7 @@ def test_given_init_node_subclass_when_instantiated_then_node_initializer_called
with pytest.raises(AttributeError):
# Then exception is raised for attributes that Node __init__
# Mock did not create.
MockInitNode()
InitNodeSubclass()

# Then Node __init__ Mock was called.
node_init.assert_called()
Expand All @@ -47,13 +49,15 @@ def test_given_init_node_subclass_when_instantiated_with_args_and_kwargs_then_cl
# Given Mock _cls_meta_args_resolver that returns Mock iterator
# when called.
mock = MagicMock(return_value=mock_iterator)
MockInitNode._cls_meta_args_resolver = mock
InitNodeSubclass._cls_meta_args_resolver = mock

# When instantiated with args and kwargs.
instance = MockInitNode(*args, **kwargs)
instance = InitNodeSubclass(*args, **kwargs)

# Then Mock _cls_meta_args_resolver was called with args and kwargs.
MockInitNode._cls_meta_args_resolver.assert_called_once_with(args, kwargs)
InitNodeSubclass._cls_meta_args_resolver.assert_called_once_with(
args, kwargs
)

# Then Mock iterator __iter__ was called.
mock_iterator.__iter__.assert_called()
Expand Down
14 changes: 8 additions & 6 deletions tests/unit/test_unit_nodes_leaf_list_node.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,19 @@
from yapyang.nodes import LeafListNode, Node


class MockLeafListNode(LeafListNode):
class LeafListNodeSubclass(LeafListNode):
"""Represents a subclass of LeafListNode."""

__identifier__ = "leaf_list_node_subclass"


def test_given_leaf_list_node_subclass_when_instantiated_then_entries_attribute_created():
"""Test given leaf list node subclass when instantiated then entries attribute created."""

# Given LeafListNode subclass.

# When instantiated.
user = MockLeafListNode()
user = LeafListNodeSubclass()

# Then entries attribute created.
assert "entries" in user.__dict__
Expand All @@ -33,7 +35,7 @@ def test_given_leaf_list_node_subclass_when_instantiated_then_node_initializer_c
# Given LeafListNode subclass.

# When instantiated.
MockLeafListNode()
LeafListNodeSubclass()

# Then Node __init__ Mock was called.
node_init.assert_called()
Expand All @@ -56,16 +58,16 @@ def test_given_instance_of_leaf_list_node_subclass_when_append_is_called_with_va
# Given Mock _cls_meta_args_resolver that returns Mock iterator
# when called.
mock = MagicMock(return_value=mock_iterator)
MockLeafListNode._cls_meta_args_resolver = mock
LeafListNodeSubclass._cls_meta_args_resolver = mock

# Given instance of LeafListNode subclass.
instance = MockLeafListNode()
instance = LeafListNodeSubclass()

# When append is called with value.
instance.append(*value)

# Then Mock _cls_meta_args_resolver was called with value.
MockLeafListNode._cls_meta_args_resolver.assert_called_once_with(
LeafListNodeSubclass._cls_meta_args_resolver.assert_called_once_with(
value, dict()
)

Expand Down
21 changes: 13 additions & 8 deletions tests/unit/test_unit_nodes_list_node.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,16 @@
class FirstOrLastName(LeafNode):
"""Represents a ListNode child node."""

__identifier__ = "first_or_last_name"

value: str


class MockListNode(ListNode):
class ListNodeSubclass(ListNode):
"""Represents a subclass of ListNode."""

__key__: str = "firstname"
__identifier__ = "list_node_subclass"
__key__ = "firstname"

firstname: FirstOrLastName
lastname: FirstOrLastName
Expand All @@ -31,7 +34,7 @@ def test_given_list_node_subclass_when_instantiated_then_entries_attribute_creat
# Given ListNode subclass.

# When instantiated.
interface = MockListNode()
interface = ListNodeSubclass()

# Then entries attribute created.
assert "entries" in interface.__dict__
Expand All @@ -50,7 +53,7 @@ def test_given_list_node_subclass_when_instantiated_then_node_initializer_called
with pytest.raises(AttributeError):
# Then exception is raised for attributes that Node __init__
# Mock did not create.
MockListNode()
ListNodeSubclass()

# Then Node __init__ Mock was called.
node_init.assert_called()
Expand All @@ -66,7 +69,7 @@ def test_given_instance_of_list_node_subclass_when_append_is_called_with_args_an
# Given tuple of cls_arg, value pairs.
cls_arg_value_pairs = tuple(
(cls_arg, FirstOrLastName(random.choice(string.ascii_letters)))
for cls_arg in MockListNode.__meta__["__args__"]
for cls_arg in ListNodeSubclass.__meta__["__args__"]
)

# Given Mock iterator with __iter__ method that returns a tuple
Expand All @@ -77,16 +80,18 @@ def test_given_instance_of_list_node_subclass_when_append_is_called_with_args_an
# Given Mock _cls_meta_args_resolver that returns Mock iterator
# when called.
mock = MagicMock(return_value=mock_iterator)
MockListNode._cls_meta_args_resolver = mock
ListNodeSubclass._cls_meta_args_resolver = mock

# Given instance of ListNode subclass.
instance = MockListNode()
instance = ListNodeSubclass()

# When append is called with args and kwargs.
instance.append(*args, **kwargs)

# Then Mock _cls_meta_args_resolver was called with args and kwargs.
MockListNode._cls_meta_args_resolver.assert_called_once_with(args, kwargs)
ListNodeSubclass._cls_meta_args_resolver.assert_called_once_with(
args, kwargs
)

# Then Mock iterator __iter__ was called.
mock_iterator.__iter__.assert_called()
Expand Down
11 changes: 3 additions & 8 deletions tests/unit/test_unit_nodes_module_node.py
Original file line number Diff line number Diff line change
@@ -1,20 +1,15 @@
"""This module contains unit tests for nodes ModuleNode."""

import typing as t

from yapyang.nodes import ModuleNode


def test_given_module_node_has_annotated_dunder_namespace_cls_attribute_when_module_node_object_created_then_module_node_meta_contains_cls_attribute_annotation_and_default():
"""Test given module node has annotated dunder namespace cls attribute when module node object created then module node meta contains cls attribute annotation and default."""
def test_given_module_node_has_annotated_dunder_namespace_cls_attribute_when_module_node_object_created_then_module_node_meta_contains_cls_attribute_annotation():
"""Test given module node has annotated dunder namespace cls attribute when module node object created then module node meta contains cls attribute annotation."""

# Given ModuleNode has annotated dunder namespace cls attribute.
__namespace__ = "__namespace__"

# When ModuleNode object created.

# Then ModuleNode meta contains cls attribute annotation.
assert ModuleNode.__meta__[__namespace__] is t.Optional[str]

# Then ModuleNode meta defaults contains cls attribute default.
assert ModuleNode.__meta__["__defaults__"][__namespace__] is None
assert ModuleNode.__meta__[__namespace__] is str
Loading

0 comments on commit c72a2b9

Please sign in to comment.