how to make a calculator 3

I want the divide function in the calculator project to return a message when 0 is given as the second number, so that the program can continue to work after ZeroDivisionError is raised.


preview

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


open the project

  • I change directory to the calculator folder

    cd calculator
    

    the terminal shows I am in the calculator folder

    .../pumping_python/calculator
    
  • I use pytest-watcher to run the tests

    uv run pytest-watcher . --now
    

    the terminal shows

    rootdir: .../pumping_python/calculator
    configfile: pyproject.toml
    collected 4 items
    
    tests/test_calculator.py ....                                 [100%]
    
    ======================== 4 passed in X.YZs =========================
    
  • I hold ctrl on the keyboard, then click on tests/test_calculator.py to open it in the editor


test_division_handles_zero_division_error


RED: make it fail


I change the assertRaises to assertEqual in test_division

42      def test_division(self):
43          self.assertEqual(
44              src.calculator.divide(
45                  self.random_first_number,
46                  self.random_second_number
47              ),
48              self.random_first_number/self.random_second_number
49          )
50          self.assertEqual(
51              src.calculator.divide(self.random_first_number, 0),
52              'brmph?! I cannot divide by 0. Try again...'
53          )
54
55
56# Exceptions seen

the terminal shows ZeroDivisionError

ZeroDivisionError: float division by zero

GREEN: make it pass


  • I add ZeroDivisionError to the list of Exceptions seen in test_calculator.py

    58# Exceptions seen
    59# AssertionError
    60# NameError
    61# AttributeError
    62# TypeError
    63# ZeroDivisionError
    
  • I open calculator.py from the src folder in the editor

  • I add an exception handler to the divide function

     9def divide(first_input, second_input):
    10    try:
    11        return first_input / second_input
    12    except ZeroDivisionError:
    13        return 'brmph?! I cannot divide by 0. Try again...'
    

    the test passes.


REFACTOR: make it better


There is a problem, the test uses random numbers, which means at some point random_second_number will have a value of 0 and the first assertion of test_division will raise ZeroDivisionError

  • I add a return statement to the a_random_number function in test_calculator.py to make it happen

    6def a_random_number():
    7    return 0
    8    return random.triangular(-1000.0, 1000.0)
    

    the terminal shows ZeroDivisionError

        def test_division(self):
            self.assertEqual(
                src.calculator.divide(
                    self.random_first_number,
                    self.random_second_number
                ),
    >           self.random_first_number/self.random_second_number
            )
    E       ZeroDivisionError: division by zero
    

    the expectated calculation in test_division divides by 0 when random_second_number is 0 but the result should be 'brmph?! I cannot divide by 0. Try again...'

  • I add an exception handler to the test

    43  def test_division(self):
    44      try:
    45          self.assertEqual(
    46              src.calculator.divide(
    47                  self.random_first_number,
    48                  self.random_second_number
    49              ),
    50              self.random_first_number/self.random_second_number
    51          )
    52      except ZeroDivisionError:
    53          self.assertEqual(
    54              src.calculator.divide(self.random_first_number, 0),
    55              'brmph?! I cannot divide by 0. Try again...'
    56          )
    

    the test passes

  • I remove the return statement from a_random_number to go back to testing with a range of random numbers

     1import random
     2import src.calculator
     3import unittest
     4
     5
     6def a_random_number():
     7    return random.triangular(-1000.0, 1000.0)
     8
     9
    10class TestCalculator(unittest.TestCase):
    

    the test is still green


close the project

  • I close test_calculator.py and calculator.py in the editor

  • I click in the terminal, then use q on the keyboard to leave the tests. The terminal goes back to the command line

  • I change directory to the parent of calculator

    cd ..
    

    the terminal shows

    ...\pumping_python
    

    I am back in the pumping_python directory


review

I ran tests to show that

code from the chapter

Do you want to see all the CODE I typed in this chapter?


what is next?

you know

Would you like to test TypeError?


rate pumping python

If this has been a 7 star experience for you, please CLICK HERE to leave a 5 star review of pumping python. It helps other people get into the book too