TypeError


TypeError is raised when an object is used in a way that it should not be. This helps understand how to use functions and classes

preview

Here are the tests I have by the end of the chapter

 1import unittest
 2import src.type_error
 3
 4
 5class TestTypeError(unittest.TestCase):
 6
 7    def test_type_error_w_non_callables(self):
 8        src.type_error.none()
 9        src.type_error.false()
10        src.type_error.true()
11        src.type_error.a_list()
12        src.type_error.a_dictionary()
13
14    def test_type_error_w_function_signatures(self):
15        src.type_error.function_00('a')
16        src.type_error.function_01('a', 'b')
17        src.type_error.function_02('a', 'b', 'c')
18        src.type_error.function_03('a', 'b', 'c', 'd')
19
20    def test_type_error_w_objects_that_do_not_mix(self):
21        with self.assertRaises(TypeError):
22            None + 1
23        with self.assertRaises(TypeError):
24            'text' + 0.1
25        with self.assertRaises(TypeError):
26            (1, 2, 3, 'n') - {1, 2, 3, 'n'}
27
28
29# Exceptions Encountered
30# AssertionError
31# AttributeError
32# TypeError

requirements

test_type_error_w_non_callables

There are objects that can NOT be called

RED: make it fail

  • I add an import statement at the top of test_type_error.py

    1import unittest
    2import src.type_error
    
  • I change test_failure to test_type_error_w_non_callables

    5class TestTypeError(unittest.TestCase):
    6
    7    def test_type_error_w_non_callables(self):
    8        src.type_error.none()
    

    the terminal shows AttributeError

    AttributeError: module 'src.type_error' has no attribute 'none'
    
  • I add it to the list of Exceptions encountered

    11# Exceptions Encountered
    12# AssertionError
    13# AttributeError
    

GREEN: make it pass

  • I open type_error.py from the src folder to open it in the editor of my Integrated Development Environment (IDE), then add the name and point it to None

    1none = None
    

    the terminal shows TypeError

    TypeError: 'NoneType' object is not callable
    

    the () to the right of src.type_error.none makes it a call, and the name none points to None which is NOT callable

  • I add the error to the list of Exceptions encountered in test_type_error.py

    11# Exceptions Encountered
    12# AssertionError
    13# AttributeError
    14# TypeError
    
  • I make none a function in type_error.py to make it callable

    1def none():
    2    return None
    

    the test passes

I can call a function but I cannot call None

REFACTOR: make it better

  • I add another failing line to test_type_error.py

    7    def test_type_error_w_non_callables(self):
    8        src.type_error.none()
    9        src.type_error.false()
    

    the terminal shows AttributeError

    AttributeError: module 'src.type_error' has no attribute 'false'
    
  • I add the name to type_error.py and point it to False

    1def none():
    2    return None
    3
    4
    5false = False
    

    the terminal shows TypeError

    TypeError: 'bool' object is not callable
    
  • I make the variable a function

    1def none():
    2    return None
    3
    4def false():
    5    return False
    

    the terminal shows green again

  • I add a line to test the other boolean in test_type_error.py

     7    def test_type_error_w_non_callables(self):
     8        src.type_error.none()
     9        src.type_error.false()
    10        src.type_error.true()
    

    the terminal shows AttributeError

    AttributeError: module 'src.type_error' has no attribute 'true'
    
  • I add the name and point it to True in type_error.py

    5def false():
    6    return False
    7
    8
    9true = True
    

    the terminal shows TypeError

    TypeError: 'bool' object is not callable
    
  • I make it a function

     5def false():
     6    return False
     7
     8
     9def true():
    10    return True
    

    the test passes. I can call a function but I cannot call a boolean

  • I add another line to test_type_error.py

     7    def test_type_error_w_non_callables(self):
     8        src.type_error.none()
     9        src.type_error.false()
    10        src.type_error.true()
    11        src.type_error.a_list()
    

    the terminal shows AttributeError

    AttributeError: module 'src.type_error' has no attribute 'a_list'
    
  • I add the name and point it to a list in type_error.py

     9def true():
    10    return True
    11
    12
    13a_list = [1, 2, 3, 'n']
    

    the terminal shows TypeError

    TypeError: 'list' object is not callable
    
  • I make a_list a function

     9def true():
    10    return True
    11
    12
    13def a_list():
    14    return [1, 2, 3, 'n']
    

    the test passes. I can call a function but I cannot call a list

  • I add a new failing line to test_type_error.py

     9      src.type_error.false()
    10      src.type_error.true()
    11      src.type_error.a_list()
    12      src.type_error.a_dictionary()
    13
    14
    15# Exceptions Encountered
    

    the terminal shows AttributeError

    AttributeError: module 'src.type_error' has no attribute 'a_dictionary'
    
  • I add the name to and point it to a dictionary in type_error.py

    13def a_list():
    14    return [1, 2, 3, 'n']
    15
    16
    17a_dictionary = {'key': 'value'}
    

    the terminal shows TypeError

    TypeError: 'dict' object is not callable
    
  • I change it to a function

    13def a_list():
    14    return [1, 2, 3, 'n']
    15
    16
    17def a_dictionary():
    18    return {'key': 'value'}
    

    the terminal shows green again.

It is safe to say that I cannot call data structures but I can call functions


test_type_error_w_function_signatures

When I call a function I have to match its definition also known as its signature

RED: make it fail

  • I add a new test to test_type_error.py

    12        src.type_error.a_dictionary()
    13
    14    def test_type_error_w_function_signatures(self):
    15        src.type_error.function_00('a')
    16
    17
    18# Exceptions Encountered
    

    the terminal shows AttributeError

    AttributeError: module 'src.type_error' has no attribute 'function_00'
    

GREEN: make it pass

  • I add the function to type_error.py

    17def a_dictionary():
    18    return {'key': 'value'}
    19
    20
    21def function_00():
    22    return None
    

    the terminal shows TypeError

    TypeError: function_00() takes 0 positional arguments but 1 was given
    

    because function_00 is called with 'a' as input but the definition does not accept any inputs

  • I add a name in parentheses to the function definition

    21def function_00(the_input):
    22    return None
    

    the test passes

I have to call a function in a way that matches its definition or I get TypeError

REFACTOR: make it better

  • I add a new failing line to test_type_error.py

    14def test_type_error_w_function_signatures(self):
    15    src.type_error.function_00('a')
    16    src.type_error.function_01('a', 'b')
    

    the terminal shows AttributeError

    AttributeError: module 'src.type_error' has no attribute 'function_01'. Did you mean: 'function_00'?
    
  • I add the function to type_error.py

    21def function_00(the_input):
    22    return None
    23
    24
    25def function_01(the_input):
    26    return None
    

    the terminal shows TypeError

    TypeError: function_01() takes 1 positional argument but 2 were given
    
  • I add another name in parentheses so that the call to the function and its definition match

    25def function_01(first_input, second_input):
    26  return None
    

    the test passes

  • I add another failing line to test_type_error.py

    14    def test_type_error_w_function_signatures(self):
    15        src.type_error.function_00('a')
    16        src.type_error.function_01('a', 'b')
    17        src.type_error.function_02('a', 'b', 'c')
    

    the terminal shows AttributeError

    AttributeError: module 'src.type_error' has no attribute 'function_02'. Did you mean: 'function_00'?
    
  • I add the function to type_error.py

    25def function_01(first_input, second_input):
    26    return None
    27
    28
    29def function_02(first_input, second_input):
    30    return None
    

    the terminal shows TypeError

    TypeError: function_02() takes 2 positional arguments but 3 were given
    
  • I add another name in parentheses to make the number of inputs match in type_error.p

    29def function_02(first_input, second_input, input_3):
    30    return None
    

    the test passes

  • I add one more failing line in test_type_error.py

    14    def test_type_error_w_function_signatures(self):
    15        src.type_error.function_00('a')
    16        src.type_error.function_01('a', 'b')
    17        src.type_error.function_02('a', 'b', 'c')
    18        src.type_error.function_03('a', 'b', 'c', 'd')
    

    the terminal shows AttributeError

    AttributeError: module 'src.type_error' has no attribute 'function_03'. Did you mean: 'function_00'?
    
  • I add the function to type_error.py

    29def function_02(first_input, second_input, input_3):
    30    return None
    31
    32
    33def function_03(first_input, second_input, input_3):
    34    return None
    

    the terminal shows TypeError

    TypeError: function_03() takes 3 positional arguments but 4 were given
    
  • I add a 4th name in parentheses to the definition

    33def function_03(first_input, second_input, input_3, input_4):
    34    return None
    

    the test passes

I have to call a function with the same number of inputs its definition expects


test_type_error_w_objects_that_do_not_mix

Some operations do not work if the objects are not of the same type

RED: make it fail

I add a new test with a failing line in test_type_error.py

18        src.type_error.function_03('a', 'b', 'c', 'd')
19
20    def test_type_error_w_objects_that_do_not_mix(self):
21        None + 1
22
23
24# Exceptions Encountered

the terminal shows TypeError

TypeError: unsupported operand type(s) for +: 'NoneType' and 'int'

I cannot do arithmetic with None

GREEN: make it pass

I add the assertRaises method

20    def test_type_error_w_objects_that_do_not_mix(self):
21        with self.assertRaises(TypeError):
22            None + 1

the test passes

REFACTOR: make it better

  • I add another failing line to the test

    20    def test_type_error_w_objects_that_do_not_mix(self):
    21        with self.assertRaises(TypeError):
    22            None + 1
    23        'text' + 0.1
    

    the terminal shows TypeError

    TypeError: can only concatenate str (not "float") to str
    

    I cannot add something that is not a string to a string. I use assertRaises to handle the Exception

    20    def test_type_error_w_objects_that_do_not_mix(self):
    21        with self.assertRaises(TypeError):
    22            None + 1
    23        with self.assertRaises(TypeError):
    24            'text' + 0.1
    

    the test passes

  • I add another failing line

    20    def test_type_error_w_objects_that_do_not_mix(self):
    21        with self.assertRaises(TypeError):
    22            None + 1
    23        with self.assertRaises(TypeError):
    24            'text' + 0.1
    25        (1, 2, 3, 'n') - {1, 2, 3, 'n'}
    

    the terminal shows TypeError

    TypeError: unsupported operand type(s) for -: 'tuple' and 'set'
    

    I add assertRaises

    20    def test_type_error_w_objects_that_do_not_mix(self):
    21        with self.assertRaises(TypeError):
    22            None + 1
    23        with self.assertRaises(TypeError):
    24            'text' + 0.1
    25        with self.assertRaises(TypeError):
    26            (1, 2, 3, 'n') - {1, 2, 3, 'n'}
    27
    28# Exceptions Encountered
    

    the terminal shows all tests are passing


test_calculator_raises_type_error

the calculator is needed for this part

  • I exit the tests by pressing ctrl+c on the keyboard in the terminal

  • I change directory to the calculator folder

    cd calculator
    

    the terminal shows

    .../pumping_python/calculator
    
  • I activate the virtual environment

    source .venv/bin/activate
    

    the terminal shows

    (.venv) .../pumping_python/calculator
    
  • I run the tests with pytest-watch

    pytest-watch
    

    the terminal shows

    ======================== test session starts =========================
    platform linux -- Python 3.X.7, pytest-9.0.1, pluggy-1.6.0
    rootdir: /workspaces/pumping_python/pumping_python/calculator
    collected 4 items
    
    tests/test_calculator.py ....                                  [100%]
    
    ========================= 4 passed in 0.01s ==========================
    
  • I hold ctrl (Windows/Linux) or option or command (MacOS) on the keyboard and use the mouse to click on tests/test_calculator.py to open it in the editor

RED: make it fail

I add a new failing test to show that I can NOT do an arithmetic operation with something that is not a number

33    def test_division(self):
34        while self.random_y == 0:
35            with self.assertRaises(ZeroDivisionError):
36                src.calculator.divide(self.random_x, self.random_y)
37            self.random_y = a_random_number()
38        else:
39            self.assertEqual(
40                src.calculator.divide(self.random_x, self.random_y),
41                self.random_x/self.random_y
42            )
43
44    def test_calculator_raises_type_error(self):
45        src.calculator.add(self.random_x, None)
46
47
48# Exceptions Encountered

the terminal shows TypeError

TypeError: unsupported operand type(s) for +: 'int' and 'NoneType'

GREEN: make it pass

I add assertRaises

44    def test_calculator_raises_type_error(self):
45        with self.assertRaises(TypeError):
46            src.calculator.add(self.random_x, None)

the test passes

REFACTOR: make it better

  • I add a failing line for division

    44    def test_calculator_raises_type_error(self):
    45        with self.assertRaises(TypeError):
    46            src.calculator.add(self.random_x, None)
    47        src.calculator.divide(self.random_x, None)
    

    the terminal shows TypeError

    TypeError: unsupported operand type(s) for /: 'int' and 'NoneType'
    

    I add assertRaises

    44    def test_calculator_raises_type_error(self):
    45        with self.assertRaises(TypeError):
    46            src.calculator.add(self.random_x, None)
    47        with self.assertRaises(TypeError):
    48            src.calculator.divide(self.random_x, None)
    

    the test passes

  • I add another failing line, this time for multiplication

    44    def test_calculator_raises_type_error(self):
    45        with self.assertRaises(TypeError):
    46            src.calculator.add(self.random_x, None)
    47        with self.assertRaises(TypeError):
    48            src.calculator.divide(self.random_x, None)
    49        src.calculator.multiply(self.random_x, None)
    

    the terminal shows TypeError

    TypeError: unsupported operand type(s) for *: 'int' and 'NoneType'
    

    I add assertRaises

    44    def test_calculator_raises_type_error(self):
    45        with self.assertRaises(TypeError):
    46            src.calculator.add(self.random_x, None)
    47        with self.assertRaises(TypeError):
    48            src.calculator.divide(self.random_x, None)
    49        with self.assertRaises(TypeError):
    50            src.calculator.multiply(self.random_x, None)
    

    the test passes

  • I add another one for subtraction

    44    def test_calculator_raises_type_error(self):
    45        with self.assertRaises(TypeError):
    46            src.calculator.add(self.random_x, None)
    47        with self.assertRaises(TypeError):
    48            src.calculator.divide(self.random_x, None)
    49        with self.assertRaises(TypeError):
    50            src.calculator.multiply(self.random_x, None)
    51        src.calculator.subtract(self.random_x, None)
    

    the terminal shows TypeError

    TypeError: unsupported operand type(s) for -: 'int' and 'NoneType'
    

    I add the assertRaises method

    44    def test_calculator_raises_type_error(self):
    45        with self.assertRaises(TypeError):
    46            src.calculator.add(self.random_x, None)
    47        with self.assertRaises(TypeError):
    48            src.calculator.divide(self.random_x, None)
    49        with self.assertRaises(TypeError):
    50            src.calculator.multiply(self.random_x, None)
    51        with self.assertRaises(TypeError):
    52            src.calculator.subtract(self.random_x, None)
    53
    54
    55# Exceptions Encountered
    

    the test passes


how to check if input is good

I want to add a condition to the calculator to make sure that what the functions receive are numbers. I can do this with TypeError

RED: make it fail

I add an exception handler to the add function in calculator.py

13def add(input_1, input_2):
14    try:
15        return input_1 + input_2
16    except TypeError:
17        return 'I only work with numbers'

the terminal shows AssertionError

AssertionError: TypeError not raised

because the add function now sends a message when TypeError is raised

GREEN: make it pass

I change the assertRaises to assertEqual in test_calculator.py

44def test_calculator_raises_type_error(self):
45    self.assertEqual(
46        src.calculator.add(self.random_x, None),
47        'I only work with numbers'
48    )
49    with self.assertRaises(TypeError):
50        src.calculator.divide(self.random_x, None)
51    with self.assertRaises(TypeError):
52        src.calculator.multiply(self.random_x, None)
53    with self.assertRaises(TypeError):
54        src.calculator.subtract(self.random_x, None)

the test passes

REFACTOR: make it better

  • I add an exception handler to the divide function in calculator.py

     9def divide(input_1, input_2):
    10    try:
    11        return input_1 / input_2
    12    except TypeError:
    13        return 'I only work with numbers'
    14
    15
    16def add(input_1, input_2):
    

    the terminal shows AssertionError

    AssertionError: TypeError not raised
    

    because the add function now sends a message when TypeError is raised

  • I change assertRaises to assertEqual in test_calculator.py

    44    def test_calculator_raises_type_error(self):
    45        self.assertEqual(
    46            src.calculator.add(self.random_x, None),
    47            'I only work with numbers'
    48        )
    49        self.assertEqual(
    50            src.calculator.divide(self.random_x, None),
    51            'I only work with numbers'
    52        )
    53        with self.assertRaises(TypeError):
    54            src.calculator.multiply(self.random_x, None)
    55        with self.assertRaises(TypeError):
    56            src.calculator.subtract(self.random_x, None)
    
  • I have the same exception handler in both functions in calculator.py. To follow The Do Not Repeat Yourself (DRY) Principle I can write a function that handles TypeError. The problem is how it takes care of the lines that change, that is

    • result = input_1 + input_2

    • result = input_1 / input_2

    I add a new function to calculator.py

     1def handle_type_error(function):
     2    def wrapper(input_1, input_2):
     3        try:
     4            return function(input_1, input_2)
     5        except TypeError:
     6            return 'I only work with numbers'
     7    return wrapper
     8
     9
    10def subtract(input_1, input_2):
    

    this new function (handle_type_error) takes a function as input. It has a function inside it named wrapper, which runs the input function and handles TypeError when raised

  • I use the new function as a wrapper for the add function

    18def divide(input_1, input_2):
    19    try:
    20        return input_1 / input_2
    21    except TypeError:
    22        return 'I only work with numbers'
    23
    24
    25@handle_type_error
    26def add(input_1, input_2):
    27    return input_1 + input_2
    

    the test is still green

  • I wrap the divide function as well

    18@handle_type_error
    19def divide(input_1, input_2):
    20    return input_1 / input_2
    21
    22
    23@handle_type_error
    24def add(input_1, input_2):
    25    return input_1 + input_2
    

    the test is still green

  • I use the wrapper with the multiply function

    14@handle_type_error
    15def multiply(input_1, input_2):
    16    return input_1 * input_2
    

    the terminal shows AssertionError

    AssertionError: TypeError not raised
    

    I change the assertRaises to assertEqual in test_calculator.py

    44    def test_calculator_raises_type_error(self):
    45        self.assertEqual(
    46            src.calculator.add(self.random_x, None),
    47            'I only work with numbers'
    48        )
    49        self.assertEqual(
    50            src.calculator.divide(self.random_x, None),
    51            'I only work with numbers'
    52        )
    53        self.assertEqual(
    54            src.calculator.multiply(self.random_x, None),
    55            'I only work with numbers'
    56        )
    57        with self.assertRaises(TypeError):
    58            src.calculator.subtract(self.random_x, None)
    

    the test passes

  • I add the wrapper to the subtract function

    10@handle_type_error
    11def subtract(input_1, input_2):
    12    return input_1 - input_2
    13
    14
    15@handle_type_error
    16def multiply(input_1, input_2):
    17    return input_1 * input_2
    

    the terminal shows AssertionError

    AssertionError: TypeError not raised
    

    I change assertRaises to assertEqual in calculator.py

    44    def test_calculator_raises_type_error(self):
    45        self.assertEqual(
    46            src.calculator.add(self.random_x, None),
    47            'I only work with numbers'
    48        )
    49        self.assertEqual(
    50            src.calculator.divide(self.random_x, None),
    51            'I only work with numbers'
    52        )
    53        self.assertEqual(
    54            src.calculator.multiply(self.random_x, None),
    55            'I only work with numbers'
    56        )
    57        self.assertEqual(
    58            src.calculator.subtract(self.random_x, None),
    59            'I only work with numbers'
    60        )
    61
    62
    63# Exceptions Encountered
    

    the test passes

  • I change the name of the test to be more descriptive

    44    def test_calculator_sends_a_message_when_inputs_are_not_numbers(self):
    45        self.assertEqual(
    

    The calculator now uses TypeError to send a message when bad inputs are passed, but there is a case I have not considered

  • Python allows using the + operator with strings but it does not work for the other arithmetic operations. I add a test to show this with the addition function

    57        self.assertEqual(
    58            src.calculator.subtract(self.random_x, None),
    59            'I only work with numbers'
    60        )
    61
    62    def test_calculator_with_strings(self):
    63        self.assertEqual(
    64            src.calculator.add('hello ', 'world'),
    65            None
    66        )
    67
    68
    69# Exceptions Encountered
    

    the terminal shows

    AssertionError: 'hello world' != None
    

    I change the expectation to match

    62    def test_calculator_with_strings(self):
    63        self.assertEqual(
    64            src.calculator.add('hello ', 'world'),
    65            'hello world'
    66        )
    

    the test passes

  • I add another assertion for division

    62    def test_calculator_with_strings(self):
    63        self.assertEqual(
    64            src.calculator.add('hello ', 'world'),
    65            'hello world'
    66        )
    67        self.assertEqual(
    68            src.calculator.divide('hello ', 'world'),
    69            'hello world'
    70        )
    

    the terminal shows AssertionError

    AssertionError: 'I only work with numbers' != 'hello world'
    

    the divide function raised TypeError which was handled by handle_type_error so I get a message back

  • I change the expectation in test_calculator.py

            self.assertEqual(
                src.calculator.divide('hello ', 'world'),
                'I only work with numbers'
            )
    

    the test passes

  • I want the add function to show the same message when it gets a string. I add a condition to handle_type_error in calculator.py

    1def handle_type_error(function):
    2    def wrapper(input_1, input_2):
    3        if isinstance(input_1, str) or isinstance(input_2, str):
    4            return 'I only work with numbers'
    5        try:
    6            return function(input_1, input_2)
    7        except TypeError:
    8            return 'I only work with numbers'
    9    return wrapper
    

    the terminal shows AssertionError

    AssertionError: 'I only work with numbers' != 'hello world'
    

    that’s more like it. The condition I added uses the isinstance function to check if input_1 and input_2 are strings

  • I change the expectation in test_calculator.py

    62    def test_calculator_with_strings(self):
    63        self.assertEqual(
    64            src.calculator.add('hello ', 'world'),
    65            'I only work with numbers'
    66        )
    67        self.assertEqual(
    68            src.calculator.divide('hello ', 'world'),
    69            'I only work with numbers'
    70        )
    

    the test passes

  • The message in handle_type_error is a duplication which means if I would have to change it in two places if needed. I use a variable instead so that any changes would only need to happen in one place

     1def handle_type_error(function):
     2    def wrapper(input_1, input_2):
     3        error_message = 'I only work with numbers'
     4        if isinstance(input_1, str) or isinstance(input_2, str):
     5            return error_message
     6        try:
     7            return function(input_1, input_2)
     8        except TypeError:
     9            return error_message
    10    return wrapper
    

    the test is still green

  • I change the name from handle_type_error to be more descriptive in calculator.py

    Tip

    you can use the Rename Symbol function of the Integrated Development Environment (IDE) to change everywhere handle_type_error is at once

     1def check_input(function):
     2    def wrapper(input_1, input_2):
     3        error_message = 'I only work with numbers'
     4        if isinstance(input_1, str) or isinstance(input_2, str):
     5            return error_message
     6        try:
     7            return function(input_1, input_2)
     8        except TypeError:
     9            return error_message
    10    return wrapper
    11
    12
    13@check_input
    14def subtract(input_1, input_2):
    15    return input_1 - input_2
    16
    17
    18@check_input
    19def multiply(input_1, input_2):
    20    return input_1 * input_2
    21
    22
    23@check_input
    24def divide(input_1, input_2):
    25    return input_1 / input_2
    26
    27
    28@check_input
    29def add(input_1, input_2):
    30    return input_1 + input_2
    

    the terminal still shows green

  • I add another assertion for multiplication in test_calculator.py

    67        self.assertEqual(
    68            src.calculator.divide('hello ', 'world'),
    69            'I only work with numbers'
    70        )
    71        self.assertEqual(
    72            src.calculator.multiply('hello', 'world'),
    73            None
    74        )
    

    the terminal shows AssertionError

    AssertionError: 'I only work with numbers' != None
    

    I change the expectation to match

    71        self.assertEqual(
    72            src.calculator.multiply('hello', 'world'),
    73            'I only work with numbers'
    74        )
    

    the test passes

  • I add another one for subtraction

    71        self.assertEqual(
    72            src.calculator.multiply('hello', 'world'),
    73            'I only work with numbers'
    74        )
    75        self.assertEqual(
    76            src.calculator.subtract('hello', 'world'),
    77            None
    78        )
    

    the terminal shows AssertionError

    AssertionError: 'I only work with numbers' != None
    

    I make the expectation match

    75        self.assertEqual(
    76            src.calculator.subtract('hello', 'world'),
    77            'I only work with numbers'
    78        )
    79
    80
    81# Exceptions Encountered
    

    the test passes


review

The calculator program can take 2 inputs and check if the inputs are good then do * addition * subtraction * multiplication and * division

Even though the program claims to only work with numbers, I did not add a test for floats, do you want to add those tests?

I ran tests for TypeError with * objects that are not callable * function definitions and * objects that do not mix * and the calculator program to use TypeError to make sure it gets the right inputs

Would you like to test Lists?


Click Here for the code I typed in this Chapter