class TestInputy(unittest.TestCase): """ Test case for inputy functionality Here, it is not necessary to test whether the prompted message has the correct format because it uses the methods already tested in the Printy test cases """ def setUp(self): self.inputy = Printy() str_valid_test = "Valid String" int_valid_test = 23 float_valid_test = 45.6 bool_valid_test = False def test_normalize_options_not_enough_options_raises_value_error(self): """ Tests that passing a list with less than 2 items as 'options' raises a Value Error when input_type is different than 'bool' """ with self.assertRaises(ValueError): self.inputy._normalize_options([], self.inputy.STR) def test_normalize_options_bool_more_than_two_items_get_the_first_two( self): """ Tests that passing more than 2 items as options for input_type 'bool' returns only the first two """ options = ['yes', 'no', 'Yep', 'Nope'] normalized_options = self.inputy._normalize_options( options, self.inputy.BOOL) expected_options = {'1': 'yes', '2': 'no'} self.assertEqual(normalized_options, expected_options) def test_normalize_options_bool_less_than_two_items_returns_tru_false( self): """ Tests that passing more than 2 items as options for input_type 'bool' returns only the first two """ options = ['yes'] normalized_options = self.inputy._normalize_options( options, self.inputy.BOOL) expected_options = {'1': 'True', '2': 'False'} self.assertEqual(normalized_options, expected_options) def test_check_boolean_case_insensitive(self): """ Test that passing a different case for one of the options still returns the value """ options = {'1': 'y', '2': 'n'} value = 'Y' result, valid = self.inputy.check_boolean(value, options, 'i') self.assertEqual(result, True) self.assertEqual(valid, True) def test_check_boolean_case_sensitive(self): """ Test that passing a different case for one of the options returns an invalid value """ options = {'1': 'y', '2': 'n'} value = 'Y' result, valid = self.inputy.check_boolean(value, options, '') self.assertEqual(result, False) self.assertEqual(valid, False) def test_check_integer_no_condition(self): """ Tests that passing no condition to check an integer returns the value """ positive_value = 5 negative_value = -5 condition = '' result_positive, valid_positive = self.inputy.check_integer( str(positive_value), condition) result_negative, valid_negative = self.inputy.check_integer( str(negative_value), condition) self.assertTrue(valid_positive) self.assertTrue(valid_negative) self.assertEqual(result_positive, 5) self.assertEqual(result_negative, -5) def test_check_integer_condition_only_positive(self): """ Test that passing a condition '-' to the check_integer function will return a valid value only when the value is negative """ positive_value = 5 negative_value = -5 condition = '-' result_positive, valid_positive = self.inputy.check_integer( str(positive_value), condition) result_negative, valid_negative = self.inputy.check_integer( str(negative_value), condition) self.assertFalse(valid_positive) self.assertTrue(valid_negative) self.assertEqual(result_positive, 5) self.assertEqual(result_negative, -5) def test_check_integer_condition_only_negative(self): """ Test that passing a condition '-' to the check_integer function will return a valid value only when the value is negative """ positive_value = 5 negative_value = -5 condition = '+' result_positive, valid_positive = self.inputy.check_integer( str(positive_value), condition) result_negative, valid_negative = self.inputy.check_integer( str(negative_value), condition) self.assertTrue(valid_positive) self.assertFalse(valid_negative) self.assertEqual(result_positive, 5) self.assertEqual(result_negative, -5) def test_check_float_no_condition(self): """ Tests that passing no condition to check a float returns the value """ positive_value = 5.0 negative_value = -5.0 condition = '' result_positive, valid_positive = self.inputy.check_float( str(positive_value), condition) result_negative, valid_negative = self.inputy.check_float( str(negative_value), condition) self.assertTrue(valid_positive) self.assertTrue(valid_negative) self.assertEqual(result_positive, 5.0) self.assertEqual(result_negative, -5.0) def test_check_float_condition_only_positive(self): """ Test that passing a condition '-' to the check_float function will return a valid value only when the value is negative """ positive_value = 5.0 negative_value = -5.0 condition = '-' result_positive, valid_positive = self.inputy.check_float( str(positive_value), condition) result_negative, valid_negative = self.inputy.check_float( str(negative_value), condition) self.assertFalse(valid_positive) self.assertTrue(valid_negative) self.assertEqual(result_positive, 5.0) self.assertEqual(result_negative, -5.0) def test_check_float_condition_only_negative(self): """ Test that passing a condition '-' to the check_float function will return a valid value only when the value is negative """ positive_value = 5.0 negative_value = -5.0 condition = '+' result_positive, valid_positive = self.inputy.check_float( str(positive_value), condition) result_negative, valid_negative = self.inputy.check_float( str(negative_value), condition) self.assertTrue(valid_positive) self.assertFalse(valid_negative) self.assertEqual(result_positive, 5.0) self.assertEqual(result_negative, -5.0) def test_check_string_options_by_number_case_sensitive(self): """ Tests that, passing a set of options, the correct value is returned if user enters the number of the item in the list (case sensitive scenario) """ options = {'1': 'Oranges', '2': 'Apples', '3': 'Pineapples'} selected = 3 expected_returned_value = options[str(selected)] result, valid = self.inputy.check_string(str(selected), options, '') self.assertTrue(valid) self.assertEqual(result, expected_returned_value) def test_check_string_options_by_number_case_insensitive(self): """ Tests that, passing a set of options, the correct value is returned if user enters the number of the item in the list (case insensitive scenario) """ options = {'1': 'Oranges', '2': 'Apples', '3': 'Pineapples'} selected = 3 expected_returned_value = options[str(selected)] result, valid = self.inputy.check_string(str(selected), options, 'i') self.assertTrue(valid) self.assertEqual(result, expected_returned_value) def test_check_string_options_invalid_by_number_case_insensitive(self): """ Tests that, passing a set of options, the correct value is returned if user enters the number of the item in the list (case insensitive scenario) """ options = {'1': 'Oranges', '2': 'Apples', '3': 'Pineapples'} selected = 6 # invalid expected_returned_value = str(selected) result, valid = self.inputy.check_string(str(selected), options, 'i') self.assertFalse(valid) self.assertEqual(result, expected_returned_value) def test_check_string_options_case_insensitive(self): """ Test that passing a different case for one of the options still returns the value """ options = {'1': 'Oranges', '2': 'Apples', '3': 'Pineapples'} selected_capital_case = 'ORANGES' selected_lower_case = 'oranges' expected_returned_value = options['1'] result_capital, valid_capital = self.inputy.check_string( selected_capital_case, options, 'i') result_lower, valid_lower = self.inputy.check_string( selected_lower_case, options, 'i') self.assertTrue(valid_capital) self.assertTrue(valid_lower) self.assertEqual(result_capital, expected_returned_value) self.assertEqual(result_lower, expected_returned_value) def test_check_string_case_sensitive(self): """ Test that passing a different case for one of the options returns an invalid value """ options = {'1': 'Oranges', '2': 'Apples', '3': 'Pineapples'} selected_capital_case = 'ORANGES' selected_matched_case = 'Oranges' expected_returned_value = options['1'] result_capital, valid_capital = self.inputy.check_string( selected_capital_case, options, '') result_matched, valid_matched = self.inputy.check_string( selected_matched_case, options, '') self.assertFalse(valid_capital) self.assertTrue(valid_matched) self.assertEqual(result_matched, expected_returned_value) @mock.patch('builtins.input', return_value=str_valid_test) def test_passing_no_parameters_returns_a_value_str(self, mock_input): """ Testing 'inputy' as a normal 'input()' function """ result_str = self.inputy.format_input() self.assertEqual(result_str, self.str_valid_test) @mock.patch('builtins.input', return_value=int_valid_test) def test_passing_no_parameters_returns_a_value_str_from_int( self, mock_input): """ Testing 'inputy' as a normal 'input()' function """ result_str_from_int = self.inputy.format_input() self.assertEqual(result_str_from_int, str(self.int_valid_test)) @mock.patch('builtins.input', side_effect=[ str_valid_test, bool_valid_test, float_valid_test, None, int_valid_test ]) def test_passed_invalid_when_requested_int(self, mock_input): """ Test that, when specifying the users has to enter an integer, the message is prompted until a valid number is passed """ result_valid_int = self.inputy.format_input(type='int') self.assertEqual(result_valid_int, self.int_valid_test) @mock.patch( 'builtins.input', side_effect=[None, str_valid_test, bool_valid_test, float_valid_test]) def test_passed_invalid_when_requested_float(self, mock_input): """ Test that, when specifying the users has to enter a number, the message is prompted until a valid number is passed """ result_valid_int = self.inputy.format_input(type='float') self.assertEqual(result_valid_int, self.float_valid_test) @mock.patch( 'builtins.input', side_effect=[str_valid_test, None, int_valid_test, bool_valid_test]) def test_passed_invalid_when_requested_boolean(self, mock_input): """ Test that, when specifying the user has to enter a boolean the message is prompted until a boolean is passed """ result_valid_boolean = self.inputy.format_input(type='bool') self.assertEqual(result_valid_boolean, self.bool_valid_test) @mock.patch('builtins.input', side_effect=[str_valid_test, None, int_valid_test, 'True']) def test_passed_invalid_when_requested_boolean_str(self, mock_input): """ Test that, when specifying the user has to enter a boolean the message is prompted until a test case insensitive with the name of one of the boolean values is passed """ result_valid_boolean = self.inputy.format_input(type='bool') self.assertEqual(result_valid_boolean, True) @mock.patch('builtins.input', return_value=str_valid_test) def test_passing_and_invalid_input_type(self, mock_input): """ Tests that passing and invalid input type raises an InvalidInputType exception. We mock the input() just in case the tests reaches that section """ invalid_input_type = 'not_int_nor_float' with self.assertRaises(InvalidInputType) as e: self.inputy.format_input(type=invalid_input_type) self.assertEqual(e.exception.input_type, invalid_input_type) def test_converting_value_to_integer(self): number_as_string_value = '2' invalid_string = 'Not a number as a string' none_value = None self.assertEqual(Printy._to_int(number_as_string_value), 2) self.assertEqual(Printy._to_int(none_value), None) with self.assertRaises(ValueError): Printy._to_int(invalid_string) def test_max_digits(self): """ Tests restriction when passing a max_digits parameter """ max_digits = 3 invalid_number = '1234' valid_number = '123' invalid_number_value, invalid_number_valid_value = self.inputy._check_number( int, value=invalid_number, max_digits=max_digits) valid_number_value, valid_number_valid_value = self.inputy._check_number( int, valid_number, max_digits=max_digits) self.assertTrue(valid_number_valid_value) self.assertFalse(invalid_number_valid_value) def test_max_decimals(self): """ Tests restriction when passing a max_decimals parameter """ max_decimals = 3 invalid_number = '1234.1234' valid_number = '1234.123' invalid_number_value, invalid_number_valid_value = self.inputy._check_number( float, value=invalid_number, max_decimals=max_decimals) valid_number_value, valid_number_valid_value = self.inputy._check_number( float, valid_number, max_decimals=max_decimals) self.assertTrue(valid_number_valid_value) self.assertFalse(invalid_number_valid_value)
class TestInputy(unittest.TestCase): """ Test case for inputy functionality Here, it is not necessary to test whether the prompted message has the correct format because it uses the methods already tested in the Printy test cases """ def setUp(self): self.inputy = Printy() str_valid_test = "Valid String" int_valid_test = 23 float_valid_test = 45.6 bool_valid_test = False def test_get_bool_options_case_insensitive(self): """ Tests returning True for the insensitive value if 'i' is passed as the first character of the 'options' parameter """ options = 'i{y/n}' insensitive, true_option, false_option = self.inputy.get_bool_options( options) self.assertTrue(insensitive) self.assertEqual(true_option, 'y') self.assertEqual(false_option, 'n') def test_get_bool_options_case_sensitive(self): """ Tests returning True for the insensitive value if no 'i' is passed as the first character of the 'options' parameter """ options = 'y/n' insensitive, true_option, false_option = self.inputy.get_bool_options( options) self.assertFalse(insensitive) self.assertEqual(true_option, 'y') self.assertEqual(false_option, 'n') def test_default_value_options(self): """ Tests return the default 'True' and 'False' and case insensitive if no options are passed """ options = '' insensitive, true_option, false_option = self.inputy.get_bool_options( options) self.assertTrue(insensitive) self.assertTrue(true_option) self.assertFalse(false_option) def test_passing_wrong_flag_for_case_insensitive(self): """ Tests that passing a value different than 'i' for the insensitive flag in in 'options' parameter when the type is bool, raises an exception """ options = 'f{y/n}' with self.assertRaises(BoolOptionsNotValid) as e: self.inputy.get_bool_options(options) self.assertEqual(e.exception.options, options) def test_passing_invalid_options_to_bool_type(self): """ Tests that passing an invalid option value to the parameter 'options' raises an BoolOptionsNotValid """ invalid_options = "jgnlf" with self.assertRaises(BoolOptionsNotValid) as e: self.inputy.get_bool_options(invalid_options) self.assertEqual(e.exception.options, invalid_options) def test_get_int_options(self): """ Test returning valid options""" positive = '+' negative = '-' int_options_positive = self.inputy.get_int_options(positive) int_options_negative = self.inputy.get_int_options(negative) self.assertEqual(positive, int_options_positive) self.assertEqual(negative, int_options_negative) def test_passing_long_character_as_int_options(self): """ Tests that passing more than one character (only + or - are allowed) raises an exception """ long_int_options_one = '+-' long_int_options_two = 'plus' with self.assertRaises(IntOptionsNotValid) as e_one: self.inputy.get_int_options(long_int_options_one) with self.assertRaises(IntOptionsNotValid) as e_two: self.inputy.get_int_options(long_int_options_two) self.assertEqual(e_one.exception.options, long_int_options_one) self.assertEqual(e_two.exception.options, long_int_options_two) def test_check_boolean_case_sensitive_returns_value_converted(self): """ tests that passing a value (according to the options) to a type='bool' returns a converted value (True or False) """ options = 'y/n' value_true = 'y' value_false = 'n' returned_value_true, valid_value_true = self.inputy.check_boolean( value_true, options) returned_value_false, valid_value_false = self.inputy.check_boolean( value_false, options) self.assertEqual(returned_value_true, True) self.assertEqual(returned_value_false, False) self.assertTrue(valid_value_true) self.assertTrue(valid_value_false) def test_check_boolean_case_insensitive_returns_value_converted(self): """ tests that passing a value with different case (according to the options as case insensitive) to a type='bool' returns a converted value (True or False) """ options = 'i{y/n}' value_true = 'Y' value_false = 'N' returned_value_true, valid_value_true = self.inputy.check_boolean( value_true, options) returned_value_false, valid_value_false = self.inputy.check_boolean( value_false, options) self.assertEqual(returned_value_true, True) self.assertEqual(returned_value_false, False) self.assertTrue(valid_value_true) self.assertTrue(valid_value_false) def test_check_boolean_invalid_value(self): """ tests passing an invalid value to check_bool returns False as the value and also False as 'valid_value' """ options = 'i{y/n}' value_true = 'Yes' value_false = 'No' returned_value_true, valid_value_true = self.inputy.check_boolean( value_true, options) returned_value_false, valid_value_false = self.inputy.check_boolean( value_false, options) self.assertEqual(returned_value_true, False) self.assertEqual(returned_value_false, False) self.assertFalse(valid_value_true) self.assertFalse(valid_value_false) def test_check_integer_returns_converted_value(self): """ tests that check_integer returns the value converted as integer""" value = 34 returned_value, valid_value = self.inputy.check_integer(value) self.assertTrue(isinstance(returned_value, int)) self.assertEqual(returned_value, value) self.assertTrue(valid_value) def test_check_integer_with_positive_option(self): """ Tests that passing '+' as options for type='int' returns the converted value and valid_value as False if it is not a positive number """ opts_positive = '+' valid_int = 34 invalid_int = -34 return_valid_int, valid_value_valid_int = self.inputy.check_integer( valid_int, opts_positive) return_invalid_int, valid_value_invalid_int = self.inputy.check_integer( invalid_int, opts_positive) self.assertTrue(isinstance(return_valid_int, int)) self.assertEqual(return_valid_int, valid_int) self.assertTrue(valid_value_valid_int) self.assertTrue(isinstance(return_invalid_int, int)) self.assertEqual(return_invalid_int, invalid_int) self.assertFalse(valid_value_invalid_int) def test_check_integer_with_negative_option(self): """ Tests that passing '-' as options for type='int' returns the converted value and valid_value as False if it is not a negative number """ opts_positive = '-' valid_int = -34 invalid_int = 34 return_valid_int, valid_value_valid_int = self.inputy.check_integer( valid_int, opts_positive) return_invalid_int, valid_value_invalid_int = self.inputy.check_integer( invalid_int, opts_positive) self.assertTrue(isinstance(return_valid_int, int)) self.assertEqual(return_valid_int, valid_int) self.assertTrue(valid_value_valid_int) self.assertTrue(isinstance(return_invalid_int, int)) self.assertEqual(return_invalid_int, invalid_int) self.assertFalse(valid_value_invalid_int) def test_check_float_returns_converted_value(self): """ tests that check_float returns the value converted as float""" value = 34.5 returned_value, valid_value = self.inputy.check_float(value) self.assertTrue(isinstance(returned_value, float)) self.assertEqual(returned_value, value) self.assertTrue(valid_value) def test_check_float_with_positive_option(self): """ Tests that passing '+' as options for type='float' returns the converted value and valid_value as False if it is not a positive number """ opts_positive = '+' valid_int = 34.5 invalid_int = -34.5 return_valid_int, valid_value_valid_int = self.inputy.check_float( valid_int, opts_positive) return_invalid_int, valid_value_invalid_int = self.inputy.check_float( invalid_int, opts_positive) self.assertTrue(isinstance(return_valid_int, float)) self.assertEqual(return_valid_int, valid_int) self.assertTrue(valid_value_valid_int) self.assertTrue(isinstance(return_invalid_int, float)) self.assertEqual(return_invalid_int, invalid_int) self.assertFalse(valid_value_invalid_int) def test_check_float_with_negative_option(self): """ Tests that passing '-' as options for type='float' returns the converted value and valid_value as False if it is not a negative number """ opts_positive = '-' valid_int = -34.0 invalid_int = 34.0 return_valid_int, valid_value_valid_int = self.inputy.check_float( valid_int, opts_positive) return_invalid_int, valid_value_invalid_int = self.inputy.check_float( invalid_int, opts_positive) self.assertTrue(isinstance(return_valid_int, float)) self.assertEqual(return_valid_int, valid_int) self.assertTrue(valid_value_valid_int) self.assertTrue(isinstance(return_invalid_int, float)) self.assertEqual(return_invalid_int, invalid_int) self.assertFalse(valid_value_invalid_int) @mock.patch('builtins.input', return_value=str_valid_test) def test_passing_no_parameters_returns_a_value_str(self, mock_input): """ Testing 'inputy' as a normal 'input()' function """ result_str = self.inputy.format_input() self.assertEqual(result_str, self.str_valid_test) @mock.patch('builtins.input', return_value=int_valid_test) def test_passing_no_parameters_returns_a_value_str_from_int( self, mock_input): """ Testing 'inputy' as a normal 'input()' function """ result_str_from_int = self.inputy.format_input() self.assertEqual(result_str_from_int, str(self.int_valid_test)) @mock.patch('builtins.input', side_effect=[ str_valid_test, bool_valid_test, float_valid_test, None, int_valid_test ]) def test_passed_invalid_when_requested_int(self, mock_input): """ Test that, when specifying the users has to enter an integer, the message is prompted until a valid number is passed """ result_valid_int = self.inputy.format_input(type='int') self.assertEqual(result_valid_int, self.int_valid_test) @mock.patch( 'builtins.input', side_effect=[None, str_valid_test, bool_valid_test, float_valid_test]) def test_passed_invalid_when_requested_float(self, mock_input): """ Test that, when specifying the users has to enter a number, the message is prompted until a valid number is passed """ result_valid_int = self.inputy.format_input(type='float') self.assertEqual(result_valid_int, self.float_valid_test) @mock.patch( 'builtins.input', side_effect=[str_valid_test, None, int_valid_test, bool_valid_test]) def test_passed_invalid_when_requested_boolean(self, mock_input): """ Test that, when specifying the user has to enter a boolean the message is prompted until a boolean is passed """ result_valid_boolean = self.inputy.format_input(type='bool') self.assertEqual(result_valid_boolean, self.bool_valid_test) @mock.patch('builtins.input', side_effect=[str_valid_test, None, int_valid_test, 'true']) def test_passed_invalid_when_requested_boolean_str(self, mock_input): """ Test that, when specifying the user has to enter a boolean the message is prompted until a test case insensitive with the name of one of the boolean values is passed """ result_valid_boolean = self.inputy.format_input(type='bool') self.assertEqual(result_valid_boolean, True) @mock.patch('builtins.input', return_value=str_valid_test) def test_passing_and_invalid_input_type(self, mock_input): """ Tests that passing and invalid input type raises an InvalidInputType exception. We mock the input() just in case the tests reaches that section """ invalid_input_type = 'not_int_nor_float' with self.assertRaises(InvalidInputType) as e: self.inputy.format_input(type=invalid_input_type) self.assertEqual(e.exception.input_type, invalid_input_type)