Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- from __future__ import annotations
- import pytest
- import abc
- import typing
- IMPLEMENTATION = typing.TypeVar("IMPLEMENTATION", bound=typing.Callable)
- class BaseStatusResponseTest(abc.ABC):
- EXPECTED_VALUES: typing.Optional[typing.List[typing.Tuple[str, typing.Any]]] = None
- EXPECTED_TYPES: typing.Optional[typing.List[typing.Tuple[str, typing.Type]]] = None
- # TODO Delete attributes for deprecations tests after 2022-08
- DEPRECATED_FIELDS: typing.Optional[typing.List[str]] = None
- # tuple will be unpacked with `*` and dict with `**`
- DEPRECATED_OLD_INIT_PASSED_ARGS: typing.Optional[typing.Union[tuple, dict]] = None
- DEPRECATED_NEW_INIT_PASSED_ARGS: typing.Optional[typing.Union[tuple, dict]] = None
- @pytest.fixture(scope="class", autouse=True)
- def _init(self):
- """Perform checks to validate the class."""
- if self.EXPECTED_TYPES and self.EXPECTED_VALUES:
- expected_values_keys = list(dict(self.EXPECTED_VALUES).keys())
- for key in dict(self.EXPECTED_TYPES).keys():
- if key in expected_values_keys:
- raise ValueError("You can't test the type of attribute, if already testing its value.")
- @abc.abstractmethod
- def build(self) -> typing.Any:
- ...
- # implementations for tests
- def _test_values_of_attributes(self, build, field, value):
- assert getattr(build, field) == value
- def _test_types_of_attributes(self, build, field, type_):
- assert isinstance(getattr(build, field), type_)
- # TODO Delete these implementations for deprecations after 2022-08
- def _test_deprecated_fields_raise_warning(self, build, field):
- with pytest.deprecated_call():
- getattr(build, field)
- def _init_old_signature_raises_warning(self, build):
- with pytest.deprecated_call():
- # cant make it in one line, because of syntax error
- if isinstance(tuple, self.DEPRECATED_OLD_INIT_PASSED_ARGS):
- type(build)(*self.DEPRECATED_OLD_INIT_PASSED_ARGS)
- else:
- type(build)(**self.DEPRECATED_OLD_INIT_PASSED_ARGS)
- def _init_new_signature_does_not_raise_warning(self, build):
- # cant make it in one line, because of syntax error
- if isinstance(tuple, self.DEPRECATED_NEW_INIT_PASSED_ARGS):
- type(build)(*self.DEPRECATED_NEW_INIT_PASSED_ARGS)
- else:
- type(build)(**self.DEPRECATED_NEW_INIT_PASSED_ARGS)
- @property
- def _implementations_table(self) -> typing.Dict[str, typing.Tuple[IMPLEMENTATION, typing.Callable[[IMPLEMENTATION], IMPLEMENTATION]]]:
- # a key must be a test name. the first element in tuple must be implementation of a test.
- # and second element of tuple is callable, which accepts implementation of a test, and returns it back
- # this can be used to apply decorators such as `pytest.mark.parametrize`
- result: typing.Dict[str, typing.Tuple[IMPLEMENTATION, typing.Callable[[IMPLEMENTATION], IMPLEMENTATION]]] = {}
- if self.EXPECTED_VALUES:
- result["test_values_of_attributes"] = (self._test_values_of_attributes, pytest.mark.parametrize("field,value", self.EXPECTED_VALUES))
- if self.EXPECTED_TYPES:
- result["test_types_of_attributes"] = (self._test_types_of_attributes, pytest.mark.parametrize("field,type_", self.EXPECTED_TYPES))
- # TODO Delete these implementations for deprecations after 2022-08
- if self.DEPRECATED_FIELDS:
- result["test_deprecated_fields_raise_warning"] = (self._test_deprecated_fields_raise_warning, pytest.mark.parametrize("field", self.DEPRECATED_FIELDS))
- if self.DEPRECATED_OLD_INIT_PASSED_ARGS:
- result["test_init_old_signature_raises_warning"] = (self._init_old_signature_raises_warning, lambda func: func)
- if self.DEPRECATED_NEW_INIT_PASSED_ARGS:
- result["test_init_new_signature_does_not_raise_warning"] = (self._init_new_signature_does_not_raise_warning, pytest.mark.filterwarnings("error"))
- return result
- _T = typing.TypeVar("_T", bound=BaseStatusResponseTest)
- def construct_status_response_test(class_: _T) -> _T:
- for test_name, (implementation, decorator) in class_._implementations_table.items():
- setattr(class_, test_name, decorator(implementation))
- return class_
Advertisement
Add Comment
Please, Sign In to add comment