import logging import pytest from dopt_basics import result_pattern @pytest.fixture(scope="module") def status_hdlr() -> result_pattern.StatusHandler: return result_pattern.StatusHandler() @pytest.fixture(scope="module") def dummy_logger() -> logging.Logger: logger = logging.getLogger("test") handlers = tuple(logger.handlers) for handler in handlers: logger.removeHandler(handler) logger.addHandler(logging.NullHandler()) return logger def test_NotSet(): not_set = result_pattern.NotSet() # using slots, dynamic attribute generation should not be possible with pytest.raises(AttributeError): not_set.test = "try to set value" # type: ignore def test_status_handler_properties(status_hdlr, dummy_logger): assert status_hdlr.logger is None assert status_hdlr._SUCCESS is not None assert status_hdlr.SUCCESS is not None assert isinstance(status_hdlr.SUCCESS, result_pattern.Status) assert status_hdlr.SUCCESS.code == 0 assert status_hdlr.SUCCESS.description == "SUCCESS" status_hdlr.logger = dummy_logger assert status_hdlr.logger is not None def test_status_handler_error_state_generation_FailCodeZero(status_hdlr): description: str = "test" message: str = "this is a test case" code: int = 0 with pytest.raises(ValueError, match="must not be zero since this value"): status_hdlr.error_state(code, description, message, None) def test_status_handler_error_state_generation_FailCodeNegative(status_hdlr): description: str = "test" message: str = "this is a test case" code: int = -100 with pytest.raises(ValueError, match="must not be smaller than zero"): status_hdlr.error_state(code, description, message, None) def test_status_handler_error_state_generation_SuccessWithoutException(status_hdlr): description: str = "test" message: str = "this is a test case" code: int = 100 err_state = status_hdlr.error_state(code, description, message, None) assert err_state.code == code assert err_state.description == description assert err_state.message == message assert err_state.ExceptionType is None def test_status_handler_error_state_generation_SuccessWithException(status_hdlr): description: str = "test" message: str = "this is a test case" code: int = 100 exception: Exception = ValueError(message) err_state = status_hdlr.error_state(code, description, message, exception) assert err_state.code == code assert err_state.description == description assert err_state.message == message assert err_state.ExceptionType is ValueError def test_status_handler_error_to_exception_FailWithoutException(status_hdlr): description: str = "test" message: str = "this is a test case" code: int = 100 err_state = status_hdlr.error_state(code, description, message, None) assert err_state.code == code assert err_state.description == description assert err_state.message == message assert err_state.ExceptionType is None with pytest.raises(ValueError, match="state where no exception is defined"): status_hdlr.error_to_exception(err_state) def test_status_handler_error_to_exception_SuccessWithException(status_hdlr): description: str = "test" message: str = "this is a test case" code: int = 100 exception: Exception = ValueError(message) err_state = status_hdlr.error_state(code, description, message, exception) assert err_state.code == code assert err_state.description == description assert err_state.message == message assert err_state.ExceptionType is ValueError exc = status_hdlr.error_to_exception(err_state) assert isinstance(exc, ValueError) assert str(exc) == message def test_status_handler_exception_to_error_Success(status_hdlr): description: str = "test" message: str = "this is a test case" code: int = 100 class TestException(Exception): """test""" exc = TestException(message) err_state = status_hdlr.exception_to_error(exc, code) assert err_state.code == code assert err_state.description == description assert err_state.message == message assert err_state.ExceptionType is TestException def test_status_handler_raise_for_status_Success(dummy_logger): status_hdlr = result_pattern.StatusHandler(dummy_logger) state = status_hdlr.SUCCESS assert status_hdlr.raise_for_status(state) is None def test_status_handler_raise_for_status_RaiseException(dummy_logger): status_hdlr = result_pattern.StatusHandler(dummy_logger) description: str = "test" message: str = "this is a test case" code: int = 100 exception: Exception = ValueError(message) err_state = result_pattern.Status( code=code, description=description, message=message, ExceptionType=type(exception) ) with pytest.raises(type(exception), match=message): status_hdlr.raise_for_status(err_state) def test_result_wrapper_class_FailInitNotSetNoException(): error_code = 146 test_result = result_pattern.NotSet() exception = None with pytest.raises(ValueError, match="Set >NotSet< without exception"): _: result_pattern.ResultWrapper[int] = result_pattern.ResultWrapper( result=test_result, exception=exception, code_on_error=error_code, ) def test_result_wrapper_class_FailInitSetResultWithException(): error_code = 146 test_result = 10 message = "Test of error message" exception = ValueError(message) with pytest.raises(ValueError, match="Set result with exception"): _: result_pattern.ResultWrapper[int] = result_pattern.ResultWrapper( result=test_result, exception=exception, code_on_error=error_code, ) def test_result_wrapper_class_Success(status_hdlr): # successful operation test_result = 10 error_code = 146 twrapper: result_pattern.ResultWrapper[int] = result_pattern.ResultWrapper( result=test_result, exception=None, code_on_error=error_code, ) assert twrapper.status == status_hdlr.SUCCESS assert twrapper.result == test_result assert twrapper.unwrap() == test_result assert twrapper.status.code != error_code assert twrapper.status.code == status_hdlr.SUCCESS.code def test_result_wrapper_class_FailureAccess(status_hdlr): # test for no result error_code = 146 test_result = result_pattern.NotSet() message = "Test of error message" exception = ValueError(message) twrapper: result_pattern.ResultWrapper[int] = result_pattern.ResultWrapper( result=test_result, exception=exception, code_on_error=error_code, ) assert twrapper.status != status_hdlr.SUCCESS assert twrapper.status.code == error_code with pytest.raises(result_pattern.WrapperAccessResultDespiteError): twrapper.result with pytest.raises(type(exception), match=message): _ = twrapper.unwrap() def test_wrap_result_ExceptionRaised(): MESSAGE = "Test case wrapped function decorator" error_code = 103 @result_pattern.wrap_result(error_code) def test_func_1() -> None: raise ValueError(MESSAGE) res = test_func_1() assert isinstance(res, result_pattern.ResultWrapper) assert res.status.code == error_code assert res.status.message == MESSAGE assert res.status.ExceptionType is ValueError with pytest.raises(ValueError, match=MESSAGE): res.unwrap() def test_wrap_result_NotNone_Success(status_hdlr): error_code = 103 @result_pattern.wrap_result(error_code) def test_func_2(x: str, y: str) -> int: return int(int(x) / int(y)) res = test_func_2("2", "1") assert res.result == 2 assert res.unwrap() == 2 assert res.status == status_hdlr.SUCCESS def test_wrap_result_NotNone_FailureZeroDivisionError(): error_code = 103 @result_pattern.wrap_result(error_code) def test_func_2(x: str, y: str) -> int: return int(int(x) / int(y)) res = test_func_2("2", "0") with pytest.raises(result_pattern.WrapperAccessResultDespiteError): res.result with pytest.raises(ZeroDivisionError): res.unwrap() assert res.status.code == error_code assert res.status.ExceptionType is ZeroDivisionError def test_wrap_result_NotNone_FailureValueErrorWithLogger(dummy_logger): error_code = 103 @result_pattern.wrap_result(error_code, logger=dummy_logger) def test_func_2(x: str, y: str) -> int: return int(int(x) / int(y)) res = test_func_2("2", "test") with pytest.raises(result_pattern.WrapperAccessResultDespiteError): res.result with pytest.raises(ValueError): res.unwrap() assert res.status.code == error_code assert res.status.ExceptionType is ValueError