teddecor.UnitTest.Asserts.AssertThat

  1from __future__ import annotations
  2
  3from typing import Any, Callable, Union, Dict
  4
  5from ...TED.markup import TED
  6from ...Exceptions import RangedException
  7
  8
  9__all__ = ["assertThat", "Matcher", "Raises", "eq", "gt", "lt"]
 10
 11
 12def stringify(value: Union[tuple[Any], list[Any], Dict[str, Any]]) -> str:
 13    output = []
 14    if type(value) in (tuple, list):
 15        for elem in value:
 16            output.append(str(elem))
 17    elif isinstance(value, dict):
 18        for key, elem in value.items():
 19            output.append(f"{key}={elem}")
 20
 21    return ", ".join(output)
 22
 23
 24def check_args(
 25    args: Union[list[Any], tuple[Any]],
 26    kwargs: Dict[str, Any],
 27    arg_count: int = 1,
 28    arg_and_kwarg: bool = False,
 29    vkwargs: list[str] = [],
 30) -> bool:
 31    params = [stringify(args), stringify(kwargs)]
 32    if "" in params:
 33        params.remove("")
 34    params = ", ".join(params)
 35    if not arg_and_kwarg and len(args) > 0 and len(kwargs) > 0:
 36        RangedException(
 37            TED.encode(f"_is({params})"),
 38            "Too many values to compare",
 39            5,
 40            5 + len(params),
 41            "Can not have args and kwargs at the same time",
 42        ).throw()
 43    elif len(args) > arg_count:
 44        RangedException(
 45            TED.encode(f"_is({params})"),
 46            "Too many values to compare",
 47            5,
 48            5 + len(params),
 49            "Too many arguments",
 50        ).throw()
 51    else:
 52        for key, value in kwargs.items():
 53            if key not in vkwargs:
 54                RangedException(
 55                    TED.encode(f"{key}={value}"),
 56                    "Too many values to compare",
 57                    0,
 58                    len(f"{key}"),
 59                    "Invalid keyword argument",
 60                ).throw()
 61
 62    return True
 63
 64
 65def Matcher(func: Callable):
 66    """Wraps a matcher for assertThat.
 67
 68    Args:
 69        func (Callable): The matcher function that will return a callable to match against the actual value in assertThat.
 70
 71    Note:
 72        Matchers must return functions that raise AssertionError when a condition is not met.
 73    """
 74
 75    def inner(*args, **kwargs):
 76        return func(*args, **kwargs)
 77
 78    return inner
 79
 80
 81def assertThat(actual: Any, matcher: Matcher) -> None:
 82    """Passes the actual value into the matcher.
 83
 84    Args:
 85        actual (Any): The value to pass to the matcher
 86        matcher (Matcher): Matcher function that checks a condition
 87
 88    Raises:
 89        AssertionError: If the matcher's condition fails
 90    """
 91    matcher(actual)
 92
 93
 94@Matcher
 95def eq(*args, **kwargs) -> Callable:
 96    """Assert that the actual value is equal to the expected value.
 97
 98    Returns:
 99        Callable: A matcher that checks if the actual is equal to the expected.
100    """
101
102    def equal(actual: Any):
103        """Assert that the actual value is the same type and equal to the expected value.
104
105        Args:
106            actual (Any): Any value that is matched against the argument value.
107
108        Raises:
109            AssertionError: If the actual value is the incorrect type.
110            AssertionError: If the actual value does not equal the expected.
111        """
112
113        expected: Any = args[0]
114        """Expected value that actual should match"""
115
116        if not isinstance(actual, type(expected)):
117            raise AssertionError(f"Expected {type(expected)} but found {type(actual)}")
118        elif actual != expected:
119            raise AssertionError("Actual value is not equal to the expected value.")
120
121    if check_args(args=args, kwargs=kwargs):
122        return equal
123
124
125class Raises:
126    """Assert that the code ran inside the `with` keyword raises an exception."""
127
128    def __init__(self, exception: Exception = Exception):
129        self._exception = exception
130
131    def __enter__(self):
132        return self
133
134    def __exit__(self, exc_type, exc_val, exc_tb):
135        if exc_val is not None:
136            if not isinstance(exc_val, self._exception):
137                raise AssertionError(
138                    f"Unexpected exception raised {exc_val.__class__}"
139                ) from exc_val
140            else:
141                return True
142        else:
143            raise AssertionError("No exception raised")
144
145
146@Matcher
147def gt(*args, **kwargs) -> Callable:
148    """Assert that the actual value is greater than the expected value.
149
150    Returns:
151        Callable: A matcher that checks if the actual is greater than the expected.
152    """
153
154    def greater_than(actual: Any):
155        """Assert that the actual value is the same type and greater than the expected value.
156
157        Args:
158            actual (Any): Any value that is matched against the argument value.
159
160        Raises:
161            AssertionError: If the actual value is the incorrect type.
162            AssertionError: If the actual value is less than the expected.
163        """
164
165        expected: Any = args[0]
166        """Expected value that actual should match"""
167
168        if not isinstance(actual, type(expected)):
169            raise AssertionError(f"Expected {type(expected)} but found {type(actual)}")
170        elif actual < expected:
171            raise AssertionError("Actual value is less than the expected value.")
172
173    if check_args(args=args, kwargs=kwargs):
174        return greater_than
175
176
177@Matcher
178def lt(*args, **kwargs) -> Callable:
179    """Assert that the actual value is less than the expected value.
180
181    Returns:
182        Callable: A matcher that checks if the actual is less than the expected.
183    """
184
185    def less_than(actual: Any):
186        """Assert that the actual value is the same type and less than the expected value.
187
188        Args:
189            actual (Any): Any value that is matched against the argument value.
190
191        Raises:
192            AssertionError: If the actual value is the incorrect type.
193            AssertionError: If the actual value is greater than the expected.
194        """
195
196        expected: Any = args[0]
197        """Expected value that actual should match"""
198
199        if not isinstance(actual, type(expected)):
200            raise AssertionError(f"Expected {type(expected)} but found {type(actual)}")
201        elif actual > expected:
202            raise AssertionError("Actual value is greater than the expected value.")
203
204    if check_args(args=args, kwargs=kwargs):
205        return less_than
def assertThat(actual: Any, matcher: <function Matcher>) -> None:
82def assertThat(actual: Any, matcher: Matcher) -> None:
83    """Passes the actual value into the matcher.
84
85    Args:
86        actual (Any): The value to pass to the matcher
87        matcher (Matcher): Matcher function that checks a condition
88
89    Raises:
90        AssertionError: If the matcher's condition fails
91    """
92    matcher(actual)

Passes the actual value into the matcher.

Args: actual (Any): The value to pass to the matcher matcher (Matcher): Matcher function that checks a condition

Raises: AssertionError: If the matcher's condition fails

def Matcher(func: Callable)
66def Matcher(func: Callable):
67    """Wraps a matcher for assertThat.
68
69    Args:
70        func (Callable): The matcher function that will return a callable to match against the actual value in assertThat.
71
72    Note:
73        Matchers must return functions that raise AssertionError when a condition is not met.
74    """
75
76    def inner(*args, **kwargs):
77        return func(*args, **kwargs)
78
79    return inner

Wraps a matcher for assertThat.

Args: func (Callable): The matcher function that will return a callable to match against the actual value in assertThat.

Note: Matchers must return functions that raise AssertionError when a condition is not met.

class Raises:
126class Raises:
127    """Assert that the code ran inside the `with` keyword raises an exception."""
128
129    def __init__(self, exception: Exception = Exception):
130        self._exception = exception
131
132    def __enter__(self):
133        return self
134
135    def __exit__(self, exc_type, exc_val, exc_tb):
136        if exc_val is not None:
137            if not isinstance(exc_val, self._exception):
138                raise AssertionError(
139                    f"Unexpected exception raised {exc_val.__class__}"
140                ) from exc_val
141            else:
142                return True
143        else:
144            raise AssertionError("No exception raised")

Assert that the code ran inside the with keyword raises an exception.

Raises(exception: Exception = )
129    def __init__(self, exception: Exception = Exception):
130        self._exception = exception
def eq(*args, **kwargs)
76    def inner(*args, **kwargs):
77        return func(*args, **kwargs)
def gt(*args, **kwargs)
76    def inner(*args, **kwargs):
77        return func(*args, **kwargs)
def lt(*args, **kwargs)
76    def inner(*args, **kwargs):
77        return func(*args, **kwargs)