Skip to content

Commit

Permalink
Collect all errors
Browse files Browse the repository at this point in the history
* test: add initial red-tests

* feat: add error collector
  • Loading branch information
KyleKing committed Sep 24, 2022
1 parent 4fef29b commit fea1e5e
Show file tree
Hide file tree
Showing 3 changed files with 54 additions and 7 deletions.
17 changes: 12 additions & 5 deletions .github/workflows/python-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,16 @@ jobs:
pylint --disable=consider-using-f-string abcmeta/
- name: Test
run: |
TEST_1="AttributeError: Derived class 'ABCDerived' has not implemented 'method_1' method of the parent class 'ABCParent'"
TEST_2="Derived method expected to get 3 parameters but gets 2"
TEST_3="Derived method expected to get 'name:<class 'str'>' paramter's type, but gets 'name:<class 'int'>'"
TEST_4="Derived method expected to get 'name' paramter, but gets 'family'"
TEST_5="Derived method expected to return in 'typing.Dict[str, str]' type, but returns 'typing.Dict[str, int]'"
TEST_MULTI="$TEST_1\|Derived method expected to get 'name:<class 'str'>' paramter's type, but gets 'name:<class 'int'>'\|$TEST_4"
PYTHONPATH=. python tests/correct_class_test.py
PYTHONPATH=. python tests/incorrect_class_1_test.py |& grep -F "AttributeError: Derived class 'ABCDerived' has not implemented 'method_1' method of the parent class 'ABCParent'"
PYTHONPATH=. python tests/incorrect_class_2_test.py |& grep -F "Derived method expected to get 3 parameters but gets 2"
PYTHONPATH=. python tests/incorrect_class_3_test.py |& grep -F "Derived method expected to get 'name:<class 'str'>' paramter's type, but gets 'name:<class 'int'>'"
PYTHONPATH=. python tests/incorrect_class_4_test.py |& grep -F "Derived method expected to get 'name' paramter, but gets 'family'"
PYTHONPATH=. python tests/incorrect_class_5_test.py |& grep -F "Derived method expected to return in 'typing.Dict[str, str]' type, but returns 'typing.Dict[str, int]'"
PYTHONPATH=. python tests/incorrect_class_1_test.py |& grep -F $TEST_1
PYTHONPATH=. python tests/incorrect_class_2_test.py |& grep -F $TEST_2
PYTHONPATH=. python tests/incorrect_class_3_test.py |& grep -F $TEST_3
PYTHONPATH=. python tests/incorrect_class_4_test.py |& grep -F $TEST_4
PYTHONPATH=. python tests/incorrect_class_5_test.py |& grep -F $TEST_5
PYTHONPATH=. python tests/multiple_incorrect_methods_test.py |& grep -cG $TEST_MULTI | grep 3
9 changes: 7 additions & 2 deletions abcmeta/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,7 @@ def __init_subclass__(cls):
"""Python built-in method."""
super().__init_subclass__()

errors = []
for name, obj in vars(cls.__base__).items():

# Ignore uncallable methods.
Expand All @@ -156,12 +157,13 @@ def __init_subclass__(cls):

# Make sure the derived class has implemented the abstract method.
if name not in cls.__dict__:
raise AttributeError(
errors.append(
"Derived class '{}' has not implemented '{}' method of the"
" parent class '{}'.".format(
cls.__name__, name, cls.__base__.__name__
)
)
continue

derived_method = getattr(cls, name)

Expand All @@ -181,7 +183,10 @@ def __init_subclass__(cls):
diff_details = _compare_signatures_details(
obj_method_signature, derived_method_signature
)
raise AttributeError(
errors.append(
"Signature of the derived method is not the same as parent"
" class:\r\n{}".format(_prepare_text_to_raise(diff, diff_details))
)

if errors:
raise AttributeError("\n\n".join(errors))
35 changes: 35 additions & 0 deletions tests/multiple_incorrect_methods_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
"""Test for abcmeta library.
Test for multiple errors.
"""
from typing import Dict, Text, Tuple

from abcmeta import ABC, abstractmethod


class ABCParent(ABC):
@abstractmethod
def method_1(self, name, age):
pass

@abstractmethod
def method_2(self, name: Text, age: int) -> Dict[Text, Text]:
"""Abstract method."""

def method_3(self):
pass

@abstractmethod
def method_4(self, name: Text, age: int) -> Tuple[Text, Text]:
"""Abstract method."""


class ABCDerived(ABCParent):
def method_(self, name, age): # Intentional typo (Same error as Test 1)
pass

def method_2(self, name: int, age: int) -> Dict[Text, Text]: # New
return {"name": "test"}

def method_4(self, family: Text, age: int) -> Tuple[Text, Text]: # Test 4
return ("name", "test")

0 comments on commit fea1e5e

Please sign in to comment.