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
I have these tests by the end of the chapter
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):
11
12 random_first_number = a_random_number()
13 random_second_number = a_random_number()
14
15 def test_addition(self):
16 self.assertEqual(
17 src.calculator.add(
18 self.random_first_number,
19 self.random_second_number
20 ),
21 self.random_first_number+self.random_second_number
22 )
23
24 def test_subtraction(self):
25 self.assertEqual(
26 src.calculator.subtract(
27 self.random_first_number,
28 self.random_second_number
29 ),
30 self.random_first_number-self.random_second_number
31 )
32
33 def test_multiplication(self):
34 self.assertEqual(
35 src.calculator.multiply(
36 self.random_first_number,
37 self.random_second_number
38 ),
39 self.random_first_number*self.random_second_number
40 )
41
42 def test_division(self):
43 try:
44 self.assertEqual(
45 src.calculator.divide(
46 self.random_first_number,
47 self.random_second_number
48 ),
49 self.random_first_number/self.random_second_number
50 )
51 except ZeroDivisionError:
52 self.assertEqual(
53 src.calculator.divide(self.random_first_number, 0),
54 'brmph?! I cannot divide by 0. Try again...'
55 )
56
57
58# Exceptions seen
59# AssertionError
60# NameError
61# AttributeError
62# TypeError
open the project
I change directory to the
calculatorfoldercd calculatorthe terminal shows I am in the
calculatorfolder.../pumping_python/calculatorI use
pytest-watcherto run the testsuv run pytest-watcher . --nowthe terminal is my friend, and 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.pyto 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 is my friend, and shows ZeroDivisionError
ZeroDivisionError: float division by zero
GREEN: make it pass
I add ZeroDivisionError to the list of Exceptions seen in
test_calculator.py58# Exceptions seen 59# AssertionError 60# NameError 61# AttributeError 62# TypeError 63# ZeroDivisionErrorI use the Explorer to open
calculator.pyfrom thesrcfolder in the editorI add an exception handler to the
dividefunction9def 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_numberfunction intest_calculator.pyto make it happen6def a_random_number(): 7 return 0 8 return random.triangular(-1000.0, 1000.0)the terminal is my friend, and 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 zerothe expectation in test_division when
random_second_numberis0should 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_numberto go back to testing with a range of random numbers1import 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.pyandcalculator.pyin the editorI click in the terminal where the tests are running, 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
calculatorcd ..the terminal is my friend, and shows
...\pumping_pythonI am back in the
pumping_pythondirectory
review
I ran tests to show that
I can use the assertRaises method to catch Exceptions in tests and tested these
I can use assertRaisesRegex to catch Exceptions with messages
I can use try..except…else to make programs that can choose what to do when Exceptions are raised
code from the chapter
what is next?
you know
how to make a Python test driven development environment manually
how to make a Python Test Driven Development environment automatically
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.