Perchun_Pak

Untitled

Sep 18th, 2022 (edited)
667
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 4.33 KB | None | 0 0
  1. from __future__ import annotations
  2.  
  3. import pytest
  4. import abc
  5. import typing
  6.  
  7. IMPLEMENTATION = typing.TypeVar("IMPLEMENTATION", bound=typing.Callable)
  8.  
  9.  
  10. class BaseStatusResponseTest(abc.ABC):
  11.     EXPECTED_VALUES: typing.Optional[typing.List[typing.Tuple[str, typing.Any]]] = None
  12.     EXPECTED_TYPES: typing.Optional[typing.List[typing.Tuple[str, typing.Type]]] = None
  13.  
  14.     # TODO Delete attributes for deprecations tests after 2022-08
  15.     DEPRECATED_FIELDS: typing.Optional[typing.List[str]] = None
  16.     # tuple will be unpacked with `*` and dict with `**`
  17.     DEPRECATED_OLD_INIT_PASSED_ARGS: typing.Optional[typing.Union[tuple, dict]] = None
  18.     DEPRECATED_NEW_INIT_PASSED_ARGS: typing.Optional[typing.Union[tuple, dict]] = None
  19.  
  20.     @pytest.fixture(scope="class", autouse=True)
  21.     def _init(self):
  22.         """Perform checks to validate the class."""
  23.         if self.EXPECTED_TYPES and self.EXPECTED_VALUES:
  24.             expected_values_keys = list(dict(self.EXPECTED_VALUES).keys())
  25.  
  26.             for key in dict(self.EXPECTED_TYPES).keys():
  27.                 if key in expected_values_keys:
  28.                     raise ValueError("You can't test the type of attribute, if already testing its value.")
  29.  
  30.     @abc.abstractmethod
  31.     def build(self) -> typing.Any:
  32.         ...
  33.  
  34.     # implementations for tests
  35.  
  36.     def _test_values_of_attributes(self, build, field, value):
  37.         assert getattr(build, field) == value
  38.  
  39.     def _test_types_of_attributes(self, build, field, type_):
  40.         assert isinstance(getattr(build, field), type_)
  41.  
  42.     # TODO Delete these implementations for deprecations after 2022-08
  43.  
  44.     def _test_deprecated_fields_raise_warning(self, build, field):
  45.         with pytest.deprecated_call():
  46.             getattr(build, field)
  47.  
  48.     def _init_old_signature_raises_warning(self, build):
  49.         with pytest.deprecated_call():
  50.             # cant make it in one line, because of syntax error
  51.             if isinstance(tuple, self.DEPRECATED_OLD_INIT_PASSED_ARGS):
  52.                 type(build)(*self.DEPRECATED_OLD_INIT_PASSED_ARGS)
  53.             else:
  54.                 type(build)(**self.DEPRECATED_OLD_INIT_PASSED_ARGS)
  55.  
  56.     def _init_new_signature_does_not_raise_warning(self, build):
  57.         # cant make it in one line, because of syntax error
  58.         if isinstance(tuple, self.DEPRECATED_NEW_INIT_PASSED_ARGS):
  59.             type(build)(*self.DEPRECATED_NEW_INIT_PASSED_ARGS)
  60.         else:
  61.             type(build)(**self.DEPRECATED_NEW_INIT_PASSED_ARGS)
  62.  
  63.     @property
  64.     def _implementations_table(self) -> typing.Dict[str, typing.Tuple[IMPLEMENTATION, typing.Callable[[IMPLEMENTATION], IMPLEMENTATION]]]:
  65.         # a key must be a test name. the first element in tuple must be implementation of a test.
  66.         # and second element of tuple is callable, which accepts implementation of a test, and returns it back
  67.         # this can be used to apply decorators such as `pytest.mark.parametrize`
  68.         result: typing.Dict[str, typing.Tuple[IMPLEMENTATION, typing.Callable[[IMPLEMENTATION], IMPLEMENTATION]]] = {}
  69.  
  70.         if self.EXPECTED_VALUES:
  71.             result["test_values_of_attributes"] = (self._test_values_of_attributes, pytest.mark.parametrize("field,value", self.EXPECTED_VALUES))
  72.         if self.EXPECTED_TYPES:
  73.             result["test_types_of_attributes"] = (self._test_types_of_attributes, pytest.mark.parametrize("field,type_", self.EXPECTED_TYPES))
  74.  
  75.         # TODO Delete these implementations for deprecations after 2022-08
  76.         if self.DEPRECATED_FIELDS:
  77.             result["test_deprecated_fields_raise_warning"] = (self._test_deprecated_fields_raise_warning, pytest.mark.parametrize("field", self.DEPRECATED_FIELDS))
  78.         if self.DEPRECATED_OLD_INIT_PASSED_ARGS:
  79.             result["test_init_old_signature_raises_warning"] = (self._init_old_signature_raises_warning, lambda func: func)
  80.         if self.DEPRECATED_NEW_INIT_PASSED_ARGS:
  81.             result["test_init_new_signature_does_not_raise_warning"] = (self._init_new_signature_does_not_raise_warning, pytest.mark.filterwarnings("error"))
  82.  
  83.         return result
  84.  
  85.  
  86. _T = typing.TypeVar("_T", bound=BaseStatusResponseTest)
  87.  
  88.  
  89. def construct_status_response_test(class_: _T) -> _T:
  90.     for test_name, (implementation, decorator) in class_._implementations_table.items():
  91.         setattr(class_, test_name, decorator(implementation))
  92.  
  93.     return class_
  94.  
Advertisement
Add Comment
Please, Sign In to add comment