how to make a calculator 7
I want to test the calculator with a dictionary
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 shows
rootdir: .../pumping_python/calculator configfile: pyproject.toml collected 7 items tests/test_calculator.py ....... [100%] ======================== 7 passed in X.YZs =========================I hold ctrl on the keyboard, then click on
tests/test_calculator.pyto open it in the editor
test_calculator_w_dictionary_items
RED: make it fail
I add a new test
58 def test_calculator_w_list_items(self):
59 two_numbers = [
60 self.random_first_number,
61 self.random_second_number
62 ]
63
64 self.assertEqual(
65 src.calculator.add(
66 two_numbers[0],
67 two_numbers[1]
68 ),
69 self.random_first_number+self.random_second_number
70 )
71 self.assertEqual(
72 src.calculator.divide(
73 two_numbers[-2],
74 two_numbers[-1]
75 ),
76 self.random_first_number/self.random_second_number
77 )
78 self.assertEqual(
79 src.calculator.multiply(
80 two_numbers[1],
81 two_numbers[-1]
82 ),
83 self.random_second_number*self.random_second_number
84 )
85 self.assertEqual(
86 src.calculator.subtract(
87 two_numbers[-2],
88 two_numbers[0]
89 ),
90 self.random_first_number-self.random_first_number
91 )
92 self.assertEqual(
93 src.calculator.add(*two_numbers),
94 self.random_first_number+self.random_second_number
95 )
96 self.assertEqual(
97 src.calculator.divide(*two_numbers),
98 self.random_first_number/self.random_second_number
99 )
100 self.assertEqual(
101 src.calculator.multiply(*two_numbers),
102 self.random_first_number*self.random_second_number
103 )
104 self.assertEqual(
105 src.calculator.subtract(*two_numbers),
106 self.random_first_number-self.random_second_number
107 )
108
109 def test_calculator_w_dictionary_items(self):
110 two_numbers = {
111 'x': self.random_first_number,
112 'y': self.random_second_number,
113 }
114
115 self.assertEqual(
116 src.calculator.add(
117 two_numbers['x'],
118 two_numbers['y']
119 ),
120 self.random_first_number+self.random_first_number
121 )
122
123 def test_calculator_raises_type_error_when_given_more_than_two_inputs(self):
the terminal shows AssertionError
AssertionError: ABC.DEFGHIJKLMNOPQ != RST.UVWXYZABCDEFG
GREEN: make it pass
I change the expectation to the right calculation
115 self.assertEqual(
116 src.calculator.add(
117 two_numbers['x'],
118 two_numbers['y']
119 ),
120 self.random_first_number+self.random_second_number
121 )
the test passes. two_numbers is a dictionary with two key-value pairs
'x': self.random_first_number'y': self.random_second_number
this means
two_numbers['x']isself.random_first_numbertwo_numbers['y']isself.random_second_number
REFACTOR: make it better
I add an assertion for the divide function
115 self.assertEqual( 116 src.calculator.add( 117 two_numbers['x'], 118 two_numbers['y'] 119 ), 120 self.random_first_number+self.random_second_number 121 ) 122 self.assertEqual( 123 src.calculator.divide( 124 two_numbers['x'], 125 two_numbers['y'] 126 ), 127 self.random_first_number*self.random_second_number 128 )the terminal shows AssertionError
AssertionError: D.EFGHIJKLMNOPQRST != UVWXY.ZABCDEFGHIJI change the calculation to division
122 self.assertEqual( 123 src.calculator.divide( 124 two_numbers['x'], 125 two_numbers['y'] 126 ), 127 self.random_first_number/self.random_second_number 128 )the test passes
I add an assertion for the multiply function
122 self.assertEqual( 123 src.calculator.divide( 124 two_numbers['x'], 125 two_numbers['y'] 126 ), 127 self.random_first_number/self.random_second_number 128 ) 129 self.assertEqual( 130 src.calculator.multiply( 131 two_numbers['y'], 132 two_numbers['y'] 133 ), 134 self.random_first_number*self.random_second_number 135 )the terminal shows AssertionError
AssertionError: EFGHIJ.KLMNOPQRSTU != VWXYZ.ABCDEFGHIJKLI change the expectation to use the correct variables
129 self.assertEqual( 130 src.calculator.multiply( 131 two_numbers['y'], 132 two_numbers['y'] 133 ), 134 self.random_second_number*self.random_second_number 135 )the test passes
I add an assertion for the subtract function
129 self.assertEqual( 130 src.calculator.multiply( 131 two_numbers['y'], 132 two_numbers['y'] 133 ), 134 self.random_second_number*self.random_second_number 135 ) 136 self.assertEqual( 137 src.calculator.subtract( 138 two_numbers['x'], 139 two_numbers['x'], 140 ), 141 self.random_first_number-self.random_second_number 142 )the terminal shows AssertionError
AssertionError: 0.0 != FGH.IJKLMNOPQRSTUI change the expectation to match
109 def test_calculator_w_dictionary_items(self): 110 two_numbers = { 111 'first_input': self.random_first_number, 112 'second_input': self.random_second_number, 113 } 114 115 self.assertEqual( 116 src.calculator.add( 117 two_numbers['x'], 118 two_numbers['y'] 119 ), 120 self.random_first_number+self.random_second_number 121 ) 122 self.assertEqual( 123 src.calculator.divide( 124 two_numbers['x'], 125 two_numbers['y'] 126 ), 127 self.random_first_number/self.random_second_number 128 ) 129 self.assertEqual( 130 src.calculator.multiply( 131 two_numbers['y'], 132 two_numbers['y'] 133 ), 134 self.random_second_number*self.random_second_number 135 ) 136 self.assertEqual( 137 src.calculator.subtract( 138 two_numbers['x'], 139 two_numbers['x'], 140 ), 141 self.random_first_number-self.random_first_number 142 ) 143 144 def test_calculator_raises_type_error_when_given_more_than_two_inputs(self):the test passes
test calculator with ** expression
RED: make it fail
I use ** like I did for the keyword arguments in test_functions_w_unknown_arguments
136 self.assertEqual(
137 src.calculator.subtract(
138 two_numbers['x'],
139 two_numbers['x'],
140 ),
141 self.random_first_number-self.random_first_number
142 )
143 self.assertEqual(
144 src.calculator.add(**two_numbers),
145 self.random_first_number-self.random_second_number
146 )
TypeError: numbers_only.<locals>.wrapper() got an unexpected keyword argument 'x'
the names of the keys in the two_numbers dictionary must be the same as the names of the arguments the calculator functions receive - first_input and second_input not x and y
GREEN: make it pass
I change
xandytofirst_inputandsecond_inputin the dictionary109 def test_calculator_w_dictionary_items(self): 110 two_numbers = { 111 # 'x': self.random_first_number, 112 'first_input': self.random_first_number, 113 # 'y': self.random_second_number, 114 'second_input': self.random_second_number, 115 }KeyError: 'x'I add KeyError to the list of Exceptions seen
214# Exceptions seen 215# AssertionError 216# NameError 217# AttributeError 218# TypeError 219# KeyErrorI remove the comments to put
xandyback as keys in the dictionary109 def test_calculator_w_dictionary_items(self): 110 two_numbers = { 111 'x': self.random_first_number, 112 'first_input': self.random_first_number, 113 'y': self.random_second_number, 114 'second_input': self.random_second_number, 115 } 116 117 self.assertEqual( 118 src.calculator.add( 119 two_numbers['x'], 120 two_numbers['y'] 121 ), 122 self.random_first_number+self.random_second_number 123 )TypeError: numbers_only.<locals>.decorator() got an unexpected keyword argument 'x'the same Exception I had before I added the keys to the dictionary
I change
two_numbers['x']totwo_numbers['first_input']to use the new keys in the assertions for addition117 self.assertEqual( 118 src.calculator.add( 119 # two_numbers['x'], 120 two_numbers['first_input'], 121 two_numbers['y'] 122 ), 123 self.random_first_number+self.random_second_number 124 )TypeError: numbers_only.<locals>.decorator() got an unexpected keyword argument 'x'the same Exception I had before I added the keys to the dictionary
I comment out the assertion with
**two_numbers139 self.assertEqual( 140 src.calculator.subtract( 141 two_numbers['x'], 142 two_numbers['x'], 143 ), 144 self.random_first_number-self.random_first_number 145 ) 146 # self.assertEqual( 147 # src.calculator.add(**two_numbers), 148 # self.random_first_number-self.random_second_number 149 # ) 150 151 def test_calculator_raises_type_error_when_given_more_than_two_inputs(self):the test is green again
I use
two_numbers['second_input']fortwo_numbers['y']117 self.assertEqual( 118 src.calculator.add( 119 # two_numbers['x'], 120 two_numbers['first_input'], 121 # two_numbers['y'] 122 two_numbers['second_input'] 123 ), 124 self.random_first_number+self.random_second_number 125 )the test is still green
I remove the commented lines then make the same change for division
117 self.assertEqual( 118 src.calculator.add( 119 two_numbers['first_input'], 120 two_numbers['second_input'] 121 ), 122 self.random_first_number+self.random_second_number 123 ) 124 self.assertEqual( 125 src.calculator.divide( 126 # two_numbers['x'], 127 two_numbers['first_input'], 128 # two_numbers['y'] 129 two_numbers['second_input'] 130 ), 131 self.random_first_number/self.random_second_number 132 )still green
I do the same thing for the multiply function
124 self.assertEqual( 125 src.calculator.divide( 126 two_numbers['first_input'], 127 two_numbers['second_input'] 128 ), 129 self.random_first_number/self.random_second_number 130 ) 131 self.assertEqual( 132 src.calculator.multiply( 133 # two_numbers['y'], 134 two_numbers['second_input'], 135 # two_numbers['y'] 136 two_numbers['second_input'] 137 ), 138 self.random_second_number*self.random_second_number 139 )green
I do it in the assertions for the subtract function
131 self.assertEqual( 132 src.calculator.multiply( 133 two_numbers['second_input'], 134 two_numbers['second_input'] 135 ), 136 self.random_second_number*self.random_second_number 137 ) 138 self.assertEqual( 139 src.calculator.subtract( 140 # two_numbers['x'], 141 two_numbers['first_input'], 142 # two_numbers['x'], 143 two_numbers['first_input'] 144 ), 145 self.random_first_number-self.random_first_number 146 )still green
I remove the
xandykeys from the dictionary109 def test_calculator_w_dictionary_items(self): 110 two_numbers = { 111 'first_input': self.random_first_number, 112 'second_input': self.random_second_number, 113 } 114 115 self.assertEqual( 116 src.calculator.add( 117 two_numbers['first_input'], 118 two_numbers['second_input'] 119 ), 120 self.random_first_number+self.random_second_number 121 ) 122 self.assertEqual( 123 src.calculator.divide( 124 two_numbers['first_input'], 125 two_numbers['second_input'] 126 ), 127 self.random_first_number/self.random_second_number 128 ) 129 self.assertEqual( 130 src.calculator.multiply( 131 two_numbers['second_input'], 132 two_numbers['second_input'] 133 ), 134 self.random_second_number*self.random_second_number 135 ) 136 self.assertEqual( 137 src.calculator.subtract( 138 two_numbers['first_input'], 139 two_numbers['first_input'] 140 ), 141 self.random_first_number-self.random_first_number 142 ) 143 # self.assertEqual( 144 # src.calculator.add(**two_numbers), 145 # self.random_first_number-self.random_second_number 146 # )the tests are still green
I remove the comments from the assertion with
**two_numbers143 self.assertEqual( 144 src.calculator.add(**two_numbers), 145 self.random_first_number-self.random_second_number 146 )the terminal shows AssertionError
AssertionError: VWX.YZABCDEFGHIJK != LMN.OPQRSTUVWXYZABCI change the calculation in the assertion to addition
143 self.assertEqual( 144 src.calculator.add(**two_numbers), 145 self.random_first_number+self.random_second_number 146 )the test passes
REFACTOR: make it better
I add an assertion for the divide function
143 self.assertEqual( 144 src.calculator.add(**two_numbers), 145 self.random_first_number+self.random_second_number 146 ) 147 self.assertEqual( 148 src.calculator.divide(**two_numbers), 149 self.random_first_number*self.random_second_number 150 )the terminal shows AssertionError
AssertionError: H.IJKLMNOPQRSTUVWX != YZABCD.EFGHIJKLMNOI change the calculation to use division
147 self.assertEqual( 148 src.calculator.divide(**two_numbers), 149 self.random_first_number/self.random_second_number 150 )the test passes
I add an assertion for the multiply function
147 self.assertEqual( 148 src.calculator.divide(**two_numbers), 149 self.random_first_number/self.random_second_number 150 ) 151 self.assertEqual( 152 src.calculator.multiply(**two_numbers), 153 self.random_first_number/self.random_second_number 154 )the terminal shows AssertionError
AssertionError: IJKLMN.OPQRSTUVWX != Y.ZABCDEFGHIJKLMNOPI change the calculation to multiplication
151 self.assertEqual( 152 src.calculator.multiply(**two_numbers), 153 self.random_first_number*self.random_second_number 154 )the test passes
I add the next assertion
151 self.assertEqual( 152 src.calculator.multiply(**two_numbers), 153 self.random_first_number*self.random_second_number 154 ) 155 self.assertEqual( 156 src.calculator.subtract(**two_numbers), 157 self.random_first_number+self.random_second_number 158 )the terminal shows AssertionError
AssertionError: JKL.MNOPQRSTUVWXYZ != ABC.DEFGHIJKLMNOPI change the expectation
109 def test_calculator_w_dictionary_items(self): 110 two_numbers = { 111 'first_input': self.random_first_number, 112 'second_input': self.random_second_number, 113 } 114 115 self.assertEqual( 116 src.calculator.add( 117 two_numbers['first_input'], 118 two_numbers['second_input'] 119 ), 120 self.random_first_number+self.random_second_number 121 ) 122 self.assertEqual( 123 src.calculator.divide( 124 two_numbers['first_input'], 125 two_numbers['second_input'] 126 ), 127 self.random_first_number/self.random_second_number 128 ) 129 self.assertEqual( 130 src.calculator.multiply( 131 two_numbers['second_input'], 132 two_numbers['second_input'] 133 ), 134 self.random_second_number*self.random_second_number 135 ) 136 self.assertEqual( 137 src.calculator.subtract( 138 two_numbers['first_input'], 139 two_numbers['first_input'] 140 ), 141 self.random_first_number-self.random_first_number 142 ) 143 self.assertEqual( 144 src.calculator.add(**two_numbers), 145 self.random_first_number+self.random_second_number 146 ) 147 self.assertEqual( 148 src.calculator.divide(**two_numbers), 149 self.random_first_number/self.random_second_number 150 ) 151 self.assertEqual( 152 src.calculator.multiply(**two_numbers), 153 self.random_first_number*self.random_second_number 154 ) 155 self.assertEqual( 156 src.calculator.subtract(**two_numbers), 157 self.random_first_number-self.random_second_number 158 ) 159 160 def test_calculator_raises_type_error_when_given_more_than_two_inputs(self):the test passes
test calculator with dictionary values
RED: make it fail
I can use the values method of dictionaries to make a list to test the calculator in test_calculator_w_list_items
58 def test_calculator_w_list_items(self):
59 # two_numbers = [
60 # self.random_first_number,
61 # self.random_second_number
62 # ]
63 a_dictionary = {
64 'x': self.random_first_number,
65 'y': self.random_second_number
66 }
67
68 self.assertEqual(
69 src.calculator.add(
70 two_numbers[0],
71 two_numbers[1]
72 ),
73 self.random_first_number+self.random_second_number
74 )
NameError: name 'two_numbers' is not defined
GREEN: make it pass
I add a new variable and make a list from the values of the dictionary
58 def test_calculator_w_list_items(self):
59 # two_numbers = [
60 # self.random_first_number,
61 # self.random_second_number
62 # ]
63 a_dictionary = {
64 'x': self.random_first_number,
65 'y': self.random_second_number
66 }
67 two_numbers = list(a_dictionary.values())
68
69 self.assertEqual(
70 src.calculator.add(
71 two_numbers[0],
72 two_numbers[1]
73 ),
74 self.random_first_number+self.random_second_number
75 )
76 self.assertEqual(
77 src.calculator.divide(
78 two_numbers[-2],
79 two_numbers[-1]
80 ),
81 self.random_first_number/self.random_second_number
82 )
83 self.assertEqual(
84 src.calculator.multiply(
85 two_numbers[1],
86 two_numbers[-1]
87 ),
88 self.random_second_number*self.random_second_number
89 )
90 self.assertEqual(
91 src.calculator.subtract(
92 two_numbers[-2],
93 two_numbers[0]
94 ),
95 self.random_first_number-self.random_first_number
96 )
97 self.assertEqual(
98 src.calculator.add(*two_numbers),
99 self.random_first_number+self.random_second_number
100 )
101 self.assertEqual(
102 src.calculator.divide(*two_numbers),
103 self.random_first_number/self.random_second_number
104 )
105 self.assertEqual(
106 src.calculator.multiply(*two_numbers),
107 self.random_first_number*self.random_second_number
108 )
109 self.assertEqual(
110 src.calculator.subtract(*two_numbers),
111 self.random_first_number-self.random_second_number
112 )
113
114 def test_calculator_w_dictionary_items(self):
the test is green again
test_calculator_w_for_loops_and_dictionaries
I can use a dictionary with a for loop in test_calculator_sends_message_when_input_is_not_a_number
RED: make it fail
I add a new test with a dictionary
177 def test_calculator_sends_message_when_input_is_not_a_number(self): 178 error_message = 'brmph?! Numbers only. Try again...' 179 180 [ 181 self.assertEqual( 182 src.calculator.add(data_type, a_random_number()), 183 error_message 184 ) for data_type in ( 185 None, 186 True, False, 187 str(), 'text', 188 tuple(), (0, 1, 2, 'n'), 189 list(), [0, 1, 2, 'n'], 190 set(), {0, 1, 2, 'n'}, 191 dict(), {'key': 'value'}, 192 ) 193 ] 194 195 for data_type in ( 196 None, 197 True, False, 198 str(), 'text', 199 tuple(), (0, 1, 2, 'n'), 200 list(), [0, 1, 2, 'n'], 201 set(), {0, 1, 2, 'n'}, 202 dict(), {'key': 'value'}, 203 ): 204 with self.subTest(data_type=data_type): 205 self.assertEqual( 206 src.calculator.add( 207 data_type, a_random_number() 208 ), 209 error_message 210 ) 211 self.assertEqual( 212 src.calculator.divide( 213 data_type, a_random_number() 214 ), 215 error_message 216 ) 217 self.assertEqual( 218 src.calculator.multiply( 219 data_type, a_random_number() 220 ), 221 error_message 222 ) 223 self.assertEqual( 224 src.calculator.subtract( 225 data_type, a_random_number() 226 ), 227 error_message 228 ) 229 230 def test_calculator_w_for_loops_and_dictionaries(self): 231 arithmetic = { 232 'addition': src.calculator.add, 233 'subtraction': src.calculator.subtract, 234 'multiplication': src.calculator.multiply, 235 'division': src.calculator.divide, 236 } 237 238 239# Exceptions seenarithmeticis a dictionary with the names of the Arithmetic operations as keys, this meansarithmetic['addition'] is src.calculator.add arithmetic['subtract'] is src.calculator.subtract arithmetic['multiplication'] is src.calculator.multiply arithmetic['division'] is src.calculator.divideit also means that
arithmetic['addition'](x, y) is src.calculator.add(x, y) arithmetic['subtract'](x, y) is src.calculator.subtract(x, y) arithmetic['multiplication'](x, y) is src.calculator.multiply(x, y) arithmetic['division'](x, y) is src.calculator.divide(x, y)I add for loops with the subTest method
230 def test_calculator_w_for_loops_and_dictionaries(self): 231 arithmetic = { 232 'addition': src.calculator.add, 233 'subtraction': src.calculator.subtract, 234 'multiplication': src.calculator.multiply, 235 'division': src.calculator.divide, 236 } 237 238 for bad_input in ( 239 None, 240 True, False, 241 str(), 'text', 242 tuple(), (0, 1, 2, 'n'), 243 list(), [0, 1, 2, 'n'], 244 set(), {0, 1, 2, 'n'}, 245 dict(), {'key': 'value'}, 246 ): 247 for operation in arithmetic: 248 with self.subTest( 249 operation=operation, 250 bad_input=bad_input, 251 ): 252 self.assertEqual( 253 arithmetic[operation]( 254 bad_input, a_random_number() 255 ), 256 'BOOM!!!' 257 ) 258 259 260# Exceptions seenthe terminal shows AssertionError
SUBFAILED(operation='addition', bad_input=None) ... - AssertionError: 'brmph?! Numbers only. Try again...' != 'BOOM!!!' SUBFAILED(operation='subtraction', bad_input=None) ... - AssertionError: 'brmph?! Numbers only. Try again...' != 'BOOM!!!' SUBFAILED(operation='multiplication', bad_input=None) ... - AssertionError: 'brmph?! Numbers only. Try again...' != 'BOOM!!!' SUBFAILED(operation='division', bad_input=None) ... - AssertionError: 'brmph?! Numbers only. Try again...' != 'BOOM!!!' ... SUBFAILED(operation='addition', bad_input={'key': 'value'}) ... - AssertionError: 'brmph?! Numbers only. Try again...' != 'BOOM!!!' SUBFAILED(operation='subtraction', bad_input={'key': 'value'}) ... - AssertionError: 'brmph?! Numbers only. Try again...' != 'BOOM!!!' SUBFAILED(operation='multiplication', bad_input={'key': 'value'}) ... - AssertionError: 'brmph?! Numbers only. Try again...' != 'BOOM!!!' SUBFAILED(operation='division', bad_input={'key': 'value'}) ... - AssertionError: 'brmph?! Numbers only. Try again...' != 'BOOM!!!' =================== 52 failed, 9 passed in R.STs ===================The second for loop goes over the keys of the dictionary and runs 4 tests for every bad input in the
bad_inputstuple. The two for loops together go every combination of operations and bad inputs(addition, None) (subtraction, None) (multiplication, None) (division, None) ... (addition, tuple()) (subtraction, tuple()) (multiplication, tuple()) (division, tuple()) ... (addition, {'key': 'value'}) (subtraction, {'key': 'value'}) (multiplication, {'key': 'value'}) (division, {'key': 'value'})this means I do not have to write 52 tests
GREEN: make it pass
I change the expectation to the error message
252 self.assertEqual(
253 arithmetic[operation](
254 bad_input, a_random_number()
255 ),
256 'brmph?! Numbers only. Try again...'
257 )
the test passes
REFACTOR: make it better
I remove test_calculator_sends_message_when_input_is_not_a_number because test_calculator_sends_message_when_input_is_not_a_number covers all its assertions
165 def test_calculator_raises_type_error_when_given_more_than_two_inputs(self): 166 not_two_numbers = [0, 1, 2] 167 168 with self.assertRaises(TypeError): 169 src.calculator.add(*not_two_numbers) 170 with self.assertRaises(TypeError): 171 src.calculator.divide(*not_two_numbers) 172 with self.assertRaises(TypeError): 173 src.calculator.multiply(*not_two_numbers) 174 with self.assertRaises(TypeError): 175 src.calculator.subtract(*not_two_numbers) 176 177 def test_calculator_w_for_loops_and_dictionaries(self):I change the name of test_calculator_w_for_loops_and_dictionaries to test_calculator_sends_message_when_input_is_not_a_number to say what it does
177 def test_calculator_sends_message_when_input_is_not_a_number(self): 178 arithmetic = { 179 'addition': src.calculator.add, 180 'subtraction': src.calculator.subtract, 181 'multiplication': src.calculator.multiply, 182 'division': src.calculator.divide, 183 } 184 185 for bad_input in ( 186 None, 187 True, False, 188 str(), 'text', 189 tuple(), (0, 1, 2, 'n'), 190 list(), [0, 1, 2, 'n'], 191 set(), {0, 1, 2, 'n'}, 192 dict(), {'key': 'value'}, 193 ): 194 for operation in arithmetic: 195 with self.subTest( 196 operation=operation, 197 bad_input=bad_input, 198 ): 199 self.assertEqual( 200 arithmetic[operation]( 201 bad_input, a_random_number() 202 ), 203 'brmph?! Numbers only. Try again...' 204 ) 205 206 207# Exceptions seenthis solution is not as easy to read as what was there before. Is there a better way?
test_calculator_functions
I want to use a dictionary to write one test that covers all the 4 arithmetic functions: addition, subtraction, division and multiplication and check their results are correct
RED: make it pass
I add a new test
177 def test_calculator_sends_message_when_input_is_not_a_number(self): 178 arithmetic = { 179 'addition': src.calculator.add, 180 'subtraction': src.calculator.subtract, 181 'multiplication': src.calculator.multiply, 182 'division': src.calculator.divide, 183 } 184 185 for bad_input in ( 186 None, 187 True, False, 188 str(), 'text', 189 tuple(), (0, 1, 2, 'n'), 190 list(), [0, 1, 2, 'n'], 191 set(), {0, 1, 2, 'n'}, 192 dict(), {'key': 'value'}, 193 ): 194 for operation in arithmetic: 195 with self.subTest( 196 operation=operation, 197 bad_input=bad_input, 198 ): 199 self.assertEqual( 200 arithmetic[operation]( 201 bad_input, a_random_number() 202 ), 203 'brmph?! Numbers only. Try again...' 204 ) 205 206 def test_calculator_functions(self): 207 arithmetic = { 208 'addition': src.calculator.add, 209 'subtraction': src.calculator.subtract, 210 'division': src.calculator.divide, 211 'multiplication': src.calculator.multiply, 212 } 213 214 for operation in arithmetic: 215 with self.subTest(operation=operation): 216 self.assertEqual( 217 arithmetic[operation]( 218 self.random_first_number, 219 self.random_second_number 220 ), 221 'BOOM!!!' 222 ) 223 224 225# Exceptions seenthe terminal shows AssertionError for the 4 arithmetic operations
SUBFAILED(operation='addition') ... - AssertionError: QRS.TUVWXYZABCDEF != 'BOOM!!!' SUBFAILED(operation='subtraction') ... - AssertionError: GHI.JKLMNOPQRSTUVWX != 'BOOM!!!' SUBFAILED(operation='division') ... - AssertionError: Y.ABCDEFGHIJKLMNOP != 'BOOM!!!' SUBFAILED(operation='multiplication') ... - AssertionError: QRSTUV.WXYZABCDEFG != 'BOOM!!!'how do I add the results?
GREEN: make it pass
I add a dictionary for the calculations of each operation
206 def test_calculator_functions(self): 207 arithmetic = { 208 'addition': src.calculator.add, 209 'subtraction': src.calculator.subtract, 210 'division': src.calculator.divide, 211 'multiplication': src.calculator.multiply, 212 } 213 214 expectations = { 215 'addition': ( 216 self.random_first_number+self.random_second_number 217 ), 218 'subtraction': ( 219 self.random_first_number-self.random_second_number 220 ), 221 'division': ( 222 self.random_first_number/self.random_second_number 223 ), 224 'multiplication': ( 225 self.random_first_number*self.random_second_number 226 ) 227 } 228 229 for operation in arithmetic:I use the new dictionary for the calculation in the assertion
229 for operation in arithmetic: 230 with self.subTest(operation=operation): 231 self.assertEqual( 232 arithmetic[operation]( 233 self.random_first_number, 234 self.random_second_number 235 ), 236 expectations[operation] 237 )the test passes.
This test goes through every operation in the arithmetic dictionary then calls the function that is its value with self.random_first_number and self.random_second_number as input, and checks if the result is the value for the operation key in the expectations dictionary. I think of it as
self.assertEqual(
arithmetic[operation](x, y),
expectations[operation]
)
operationcan beaddition,subtraction,multiplicationordivisionin this case
xisself.first_random_numberin this case
yisself.second_random_number
this means all these statements are the same
for addition
arithmetic['addition'](x, y) src.calculator.add(x, y) expectations['addition'] x + yfor subtraction
arithmetic['subtraction'](x, y) src.calculator.add(x, y) expectations['subtraction'] x - yfor multiplication
arithmetic['multiplication'](x, y) src.calculator.add(x, y) expectations['multiplication'] x * yfor division
arithmetic['division'](x, y) src.calculator.add(x, y) expectations['division'] x / y
REFACTOR: make it better
I can put the two dictionaries in this test together because they have the same keys
214 expectations = { 215 'addition': ( 216 self.random_first_number+self.random_second_number 217 ), 218 'subtraction': ( 219 self.random_first_number-self.random_second_number 220 ), 221 'division': ( 222 self.random_first_number/self.random_second_number 223 ), 224 'multiplication': ( 225 self.random_first_number*self.random_second_number 226 ) 227 } 228 229 x = self.random_first_number 230 y = self.random_second_number 231 arithmetic_tests = { 232 'addition': { 233 'function': src.calculator.add, 234 'expectation': x+y, 235 }, 236 'subtraction': { 237 'function': src.calculator.subtract, 238 'expectation': x-y, 239 }, 240 'division': { 241 'function': src.calculator.divide, 242 'expectation': x/y, 243 }, 244 'multiplication': { 245 'function': src.calculator.multiply, 246 'expectation': x*y, 247 }, 248 } 249 250 for operation in arithmetic:I add a new assertion in a for loop with the subTest method
250 for operation in arithmetic: 251 with self.subTest(operation=operation): 252 self.assertEqual( 253 arithmetic[operation]( 254 self.random_first_number, 255 self.random_second_number 256 ), 257 expectations[operation] 258 ) 259 260 for operation in arithmetic_tests: 261 with self.subTest(operation=operation): 262 self.assertEqual( 263 arithmetic_tests[operation]['function'](x, y), 264 'BOOM!!!' 265 ) 266 267 268# Exceptions seen 269 270 def test_calculator_sends_message_when_input_is_not_a_number(self):the terminal shows AssertionError:
SUBFAILED(operation='addition') ... - AssertionError: HIJ.KLMNOPQRSTUVW != 'BOOM!!!' SUBFAILED(operation='subtraction') ... - AssertionError: XYZA.BCDEFGHIJKLMN != 'BOOM!!!' SUBFAILED(operation='division') ... - AssertionError: NO.PQRSTUVWXYZABCDE != 'BOOM!!!' SUBFAILED(operation='multiplication') ... - AssertionError: FGHIJKLM.NOPQRSTUVW != 'BOOM!!!'I change the expectation
260 for operation in arithmetic_tests: 261 with self.subTest(operation=operation): 262 self.assertEqual( 263 arithmetic_tests[operation]['function'](x, y), 264 arithmetic_tests[operation]['expectation'] 265 )the test passes
I remove the other dictionaries and for loop
206 def test_calculator_functions(self): 207 x = self.random_first_number 208 y = self.random_second_number 209 arithmetic_tests = { 210 'addition': { 211 'function': src.calculator.add, 212 'expectation': x+y, 213 }, 214 'subtraction': { 215 'function': src.calculator.subtract, 216 'expectation': x-y, 217 }, 218 'division': { 219 'function': src.calculator.divide, 220 'expectation': x/y, 221 }, 222 'multiplication': { 223 'function': src.calculator.multiply, 224 'expectation': x*y, 225 }, 226 } 227 228 for operation in arithmetic_tests: 229 with self.subTest(operation=operation): 230 self.assertEqual( 231 arithmetic_tests[operation]['function'](x, y), 232 arithmetic_tests[operation]['expectation'] 233 ) 234 235 236# Exceptions seenmuch better
I remove test_addition, test_subtraction and test_multiplication
10class TestCalculator(unittest.TestCase): 11 12 def setUp(self): 13 self.random_first_number = a_random_number() 14 self.random_second_number = a_random_number() 15 16 def test_division(self):I have to handle ZeroDivisionError in test_calculator_functions before I can remove test_division
I change
yto0in test_calculator_functions179 def test_calculator_functions(self): 180 x = self.random_first_number 181 # y = self.random_second_number 182 y = 0 183 184 arithmetic_tests = {the terminal shows ZeroDivisionError
ZeroDivisionError: float division by zerogood
I add an exception handler to make a variable for the result of division
179 def test_calculator_functions(self): 180 x = self.random_first_number 181 # y = self.random_second_number 182 y = 0 183 184 try: 185 division_result = x / y 186 except ZeroDivisionError: 187 division_result = 'BOOM!!!' 188 189 arithmetic_tests = {here is what the exception handler does
try: division_result = x / ytry to point
division_resultto the result of dividingxbyyexcept ZeroDivisionError: division_result = 'BOOM!!!'if ZeroDivisionError is raised when trying to divide
xbyy, pointdivision_resultto'BOOM!!!'I use
division_resultin thearithmetic_testsdictionary189 arithmetic_tests = { 190 'addition': { 191 'function': src.calculator.add, 192 'expectation': x+y, 193 }, 194 'subtraction': { 195 'function': src.calculator.subtract, 196 'expectation': x-y, 197 }, 198 'division': { 199 'function': src.calculator.divide, 200 # 'expectation': x/y, 201 'expectation': division_result, 202 }, 203 'multiplication': { 204 'function': src.calculator.multiply, 205 'expectation': x*y, 206 }, 207 }the terminal shows AssertionError
AssertionError: 'brmph?! I cannot divide by 0. Try again...' != 'BOOM!!!'I change
'BOOM!!!'to the error message184 try: 185 division_result = x / y 186 except ZeroDivisionError: 187 division_result = 'brmph?! I cannot divide by 0. Try again...'the test passes. Progress
I change
yback toself.random_second_number179 def test_calculator_functions(self): 180 x = self.random_first_number 181 y = self.random_second_number 182 183 try: 184 division_result = x / y 185 except ZeroDivisionError: 186 division_result = 'brmph?! I cannot divide by 0. Try again...' 187 188 arithmetic_tests = { 189 'addition': { 190 'function': src.calculator.add, 191 'expectation': x+y, 192 }, 193 'subtraction': { 194 'function': src.calculator.subtract, 195 'expectation': x-y, 196 }, 197 'division': { 198 'function': src.calculator.divide, 199 'expectation': division_result, 200 }, 201 'multiplication': { 202 'function': src.calculator.multiply, 203 'expectation': x*y, 204 }, 205 } 206 207 for operation in arithmetic_tests: 208 with self.subTest(operation=operation): 209 self.assertEqual( 210 arithmetic_tests[operation]['function'](x, y), 211 arithmetic_tests[operation]['expectation'] 212 ) 213 214 215# Exceptions seenthe test is still green
I can put the arithmetic_tests dictionary from test_calculator_functions and the arithmetic dictionary from test_calculator_sends_message_when_input_is_not_a_number together because they have the same keys.
I add the variables from test_calculator_functions to the setUp method
12 def setUp(self): 13 self.random_first_number = a_random_number() 14 self.random_second_number = a_random_number() 15 16 x = self.random_first_number 17 y = self.random_second_number 18 19 try: 20 division_result = x / y 21 except ZeroDivisionError: 22 division_result = 'brmph?! I cannot divide by 0. Try again...' 23 24 self.arithmetic_tests = { 25 'addition': { 26 'function': src.calculator.add, 27 'expectation': x+y, 28 }, 29 'subtraction': { 30 'function': src.calculator.subtract, 31 'expectation': x-y, 32 }, 33 'division': { 34 'function': src.calculator.divide, 35 'expectation': division_result, 36 }, 37 'multiplication': { 38 'function': src.calculator.multiply, 39 'expectation': x*y, 40 } 41 }I use the new class attribute in the for loop in test_calculator_functions
219 # for operation in arithmetic_tests: 220 for operation in self.arithmetic_tests: 221 with self.subTest(operation=operation): 222 self.assertEqual( 223 arithmetic_tests[operation]['function'](x, y), 224 arithmetic_tests[operation]['expectation'] 225 )the test is still green
I use it in the assertion
222 self.assertEqual( 223 # arithmetic_tests[operation]['function'](x, y), 224 self.arithmetic_tests[operation]['function']( 225 x, y 226 ), 227 arithmetic_tests[operation]['expectation'] 228 )still green
I use it for the expectation
222 self.assertEqual( 223 # arithmetic_tests[operation]['function'](x, y), 224 self.arithmetic_tests[operation]['function']( 225 x, y 226 ), 227 # arithmetic_tests[operation]['expectation'] 228 self.arithmetic_tests[operation]['expectation'] 229 )the test is still green
I comment out the
arithmetic_testsdictionary in test_calculator_functions195 try: 196 division_result = x / y 197 except ZeroDivisionError: 198 division_result = 'brmph?! I cannot divide by 0. Try again...' 199 200 # arithmetic_tests = { 201 # 'addition': { 202 # 'function': src.calculator.add, 203 # 'expectation': x+y, 204 # }, 205 # 'subtraction': { 206 # 'function': src.calculator.subtract, 207 # 'expectation': x-y, 208 # }, 209 # 'division': { 210 # 'function': src.calculator.divide, 211 # 'expectation': division_result, 212 # }, 213 # 'multiplication': { 214 # 'function': src.calculator.multiply, 215 # 'expectation': x*y, 216 # }, 217 # } 218 219 # for operation in arithmetic_tests:still green
I comment out the exception handler
191 def test_calculator_functions(self): 192 x = self.random_first_number 193 y = self.random_second_number 194 195 # try: 196 # division_result = x / y 197 # except ZeroDivisionError: 198 # division_result = 'brmph?! I cannot divide by 0. Try again...'green
I comment out the
xandyvariables191 def test_calculator_functions(self): 192 # x = self.random_first_number 193 # y = self.random_second_numberSUBFAILED(operation='addition') ... - NameError: name 'x' is not defined SUBFAILED(operation='subtraction') ... - NameError: name 'x' is not defined SUBFAILED(operation='division') ... - NameError: name 'x' is not defined SUBFAILED(operation='multiplication') ... - NameError: name 'x' is not definedI undo the change
191 def test_calculator_functions(self): 192 x = self.random_first_number 193 y = self.random_second_numberthe test is green again
I change the inputs in the assertion
222 self.assertEqual( 223 # arithmetic_tests[operation]['function'](x, y), 224 self.arithmetic_tests[operation]['function']( 225 # x, y 226 self.random_first_number, 227 self.random_second_number 228 ), 229 # arithmetic_tests[operation]['expectation'] 230 self.arithmetic_tests[operation]['expectation'] 231 )the test is still green
I comment out
xandyagain191 def test_calculator_functions(self): 192 # x = self.random_first_number 193 # y = self.random_second_numbergreen
I remove the commented lines
191 def test_calculator_functions(self): 192 for operation in self.arithmetic_tests: 193 with self.subTest(operation=operation): 194 self.assertEqual( 195 self.arithmetic_tests[operation]['function']( 196 self.random_first_number, 197 self.random_second_number 198 ), 199 self.arithmetic_tests[operation]['expectation'] 200 ) 201 202 203# Exceptions seenthe test is still green
I use the new class attribute in the for loop in test_calculator_sends_message_when_input_is_not_a_number
162 def test_calculator_sends_message_when_input_is_not_a_number(self): 163 arithmetic = { 164 'addition': src.calculator.add, 165 'subtraction': src.calculator.subtract, 166 'multiplication': src.calculator.multiply, 167 'division': src.calculator.divide, 168 } 169 170 for bad_input in ( 171 None, 172 True, False, 173 str(), 'text', 174 tuple(), (0, 1, 2, 'n'), 175 list(), [0, 1, 2, 'n'], 176 set(), {0, 1, 2, 'n'}, 177 dict(), {'key': 'value'}, 178 ): 179 # for operation in arithmetic: 180 for operation in self.arithmetic_tests: 181 with self.subTest( 182 operation=operation, 183 bad_input=bad_input, 184 ): 185 self.assertEqual( 186 arithmetic[operation]( 187 bad_input, a_random_number() 188 ), 189 'brmph?! Numbers only. Try again...' 190 ) 191 192 def test_calculator_functions(self):still green
I use it in the assertion
185 self.assertEqual( 186 # arithmetic[operation]( 187 self.arithmetic_tests[operation]['function']( 188 bad_input, a_random_number() 189 ), 190 'brmph?! Numbers only. Try again...' 191 )green
I remove the commented lines and the
arithmeticvariable because it is no longer used162 def test_calculator_sends_message_when_input_is_not_a_number(self): 163 for bad_input in ( 164 None, 165 True, False, 166 str(), 'text', 167 tuple(), (0, 1, 2, 'n'), 168 list(), [0, 1, 2, 'n'], 169 set(), {0, 1, 2, 'n'}, 170 dict(), {'key': 'value'}, 171 ): 172 for operation in self.arithmetic_tests: 173 with self.subTest( 174 operation=operation, 175 bad_input=bad_input, 176 ): 177 self.assertEqual( 178 self.arithmetic_tests[operation]['function']( 179 bad_input, a_random_number() 180 ), 181 'brmph?! Numbers only. Try again...' 182 ) 183 184 def test_calculator_functions(self):green around the roses
I add a for loop to use the
self.arithmetic_testsdictionary in test_calculator_raises_type_error_when_given_more_than_two_inputs150 def test_calculator_raises_type_error_when_given_more_than_two_inputs(self): 151 not_two_numbers = [0, 1, 2] 152 153 for operation in self.arithmetic_tests: 154 with self.subTest(operation=operation): 155 self.arithmetic_tests[operation]['function']( 156 **not_two_numbers 157 ) 158 159 with self.assertRaises(TypeError): 160 src.calculator.add(*not_two_numbers) 161 with self.assertRaises(TypeError): 162 src.calculator.divide(*not_two_numbers) 163 with self.assertRaises(TypeError): 164 src.calculator.multiply(*not_two_numbers) 165 with self.assertRaises(TypeError): 166 src.calculator.subtract(*not_two_numbers)the terminal shows TypeError for all 4 cases
SUBFAILED(operation='addition') ... - TypeError: src.calculator.numbers_only.<locals>.decorator() argument after ** must be a m... SUBFAILED(operation='subtraction') ... - TypeError: src.calculator.numbers_only.<locals>.decorator() argument after ** must be a m... SUBFAILED(operation='division') ... - TypeError: src.calculator.numbers_only.<locals>.decorator() argument after ** must be a m... SUBFAILED(operation='multiplication') ... - TypeError: src.calculator.numbers_only.<locals>.decorator() argument after ** must be a m...lovely! The test works
I add the assertRaises method
153 for operation in self.arithmetic_tests: 154 with self.subTest(operation=operation): 155 with self.assertRaises(TypeError): 156 self.arithmetic_tests[operation]['function']( 157 **not_two_numbers 158 )the test passes
I remove the other assertions
171 def test_calculator_raises_type_error_when_given_more_than_two_inputs(self): 172 not_two_numbers = [0, 1, 2] 173 174 for operation in self.arithmetic_tests: 175 with self.subTest(operation=operation): 176 with self.assertRaises(TypeError): 177 self.arithmetic_tests[operation]['function']( 178 **not_two_numbers 179 ) 180 181 def test_calculator_sends_message_when_input_is_not_a_number(self):the test is still green
I use the list for the variable in the assertion
156 self.arithmetic_tests[operation]['function']( 157 # **not_two_numbers 158 [0, 1, 2] 159 )still green
I put the two with statements together
153 for operation in self.arithmetic_tests: 154 # with self.subTest(operation=operation): 155 # with self.assertRaises(TypeError): 156 with ( 157 self.subTest(operation=operation), 158 self.assertRaises(TypeError), 159 ): 160 self.arithmetic_tests[operation]['function']( 161 # **not_two_numbers 162 [0, 1, 2] 163 )green
I remove the commented lines and
not_two_numbersvariable150 def test_calculator_raises_type_error_when_given_more_than_two_inputs(self): 151 for operation in self.arithmetic_tests: 152 with ( 153 self.subTest(operation=operation), 154 self.assertRaises(TypeError), 155 ): 156 self.arithmetic_tests[operation]['function']( 157 [0, 1, 2] 158 ) 159 160 def test_calculator_sends_message_when_input_is_not_a_number(self):still green
I add a for loop to use the
self.arithmetic_testsdictionary in test_calculator_w_dictionary_items99 def test_calculator_w_dictionary_items(self): 100 two_numbers = { 101 'first_input': self.random_first_number, 102 'second_input': self.random_second_number, 103 } 104 105 for operation in self.arithmetic_tests: 106 with self.subTest(operation=operation): 107 self.assertEqual( 108 self.arithmetic_tests[operation]['function']( 109 **two_numbers 110 ), 111 'BOOM!!!' 112 ) 113 114 self.assertEqual( 115 src.calculator.add( 116 two_numbers['first_input'], 117 two_numbers['second_input'] 118 ), 119 self.random_first_number+self.random_second_number 120 ) 121 self.assertEqual( 122 src.calculator.divide( 123 two_numbers['first_input'], 124 two_numbers['second_input'] 125 ), 126 self.random_first_number/self.random_second_number 127 ) 128 self.assertEqual( 129 src.calculator.multiply( 130 two_numbers['second_input'], 131 two_numbers['second_input'] 132 ), 133 self.random_second_number*self.random_second_number 134 ) 135 self.assertEqual( 136 src.calculator.subtract( 137 two_numbers['first_input'], 138 two_numbers['first_input'] 139 ), 140 self.random_first_number-self.random_first_number 141 ) 142 self.assertEqual( 143 src.calculator.add(**two_numbers), 144 self.random_first_number+self.random_second_number 145 ) 146 self.assertEqual( 147 src.calculator.divide(**two_numbers), 148 self.random_first_number/self.random_second_number 149 ) 150 self.assertEqual( 151 src.calculator.multiply(**two_numbers), 152 self.random_first_number*self.random_second_number 153 ) 154 self.assertEqual( 155 src.calculator.subtract(**two_numbers), 156 self.random_first_number-self.random_second_number 157 ) 158 159 def test_calculator_raises_type_error_when_given_more_than_two_inputs(self):the terminal shows AssertionError for the 4 operations
SUBFAILED(operation='addition') ... - AssertionError: XYZ.ABCDEFGHIJKLM != 'BOOM!!!' SUBFAILED(operation='subtraction') ... - AssertionError: NOP.QRSTUVWXYZABC != 'BOOM!!!' SUBFAILED(operation='division') ... - AssertionError: D.EFGHIJKLMNOPQRS != 'BOOM!!!' SUBFAILED(operation='multiplication') ... - AssertionError: TUVWX.YZABCDEFGHI != 'BOOM!!!'I change the expectation
107 self.assertEqual( 108 self.arithmetic_tests[operation]['function']( 109 **two_numbers 110 ), 111 self.arithmetic_tests[operation]['expectation'] 112 )the test passes
I remove all the assertions that have
**two_numbers99 def test_calculator_w_dictionary_items(self): 100 two_numbers = { 101 'first_input': self.random_first_number, 102 'second_input': self.random_second_number, 103 } 104 105 for operation in self.arithmetic_tests: 106 with self.subTest(operation=operation): 107 self.assertEqual( 108 self.arithmetic_tests[operation]['function']( 109 **two_numbers 110 ), 111 self.arithmetic_tests[operation]['expectation'] 112 ) 113 114 self.assertEqual( 115 src.calculator.add( 116 two_numbers['first_input'], 117 two_numbers['second_input'] 118 ), 119 self.random_first_number+self.random_second_number 120 ) 121 self.assertEqual( 122 src.calculator.divide( 123 two_numbers['first_input'], 124 two_numbers['second_input'] 125 ), 126 self.random_first_number/self.random_second_number 127 ) 128 self.assertEqual( 129 src.calculator.multiply( 130 two_numbers['second_input'], 131 two_numbers['second_input'] 132 ), 133 self.random_second_number*self.random_second_number 134 ) 135 self.assertEqual( 136 src.calculator.subtract( 137 two_numbers['first_input'], 138 two_numbers['first_input'] 139 ), 140 self.random_first_number-self.random_first_number 141 ) 142 143 def test_calculator_raises_type_error_when_given_more_than_two_inputs(self):the test is still green
I add a for loop to use the
self.arithmetic_testsdictionary in test_calculator_w_list_items43 def test_calculator_w_list_items(self): 44 # two_numbers = [ 45 # self.random_first_number, 46 # self.random_second_number 47 # ] 48 a_dictionary = { 49 'x': self.random_first_number, 50 'y': self.random_second_number 51 } 52 two_numbers = list(a_dictionary.values()) 53 54 for operation in self.arithmetic_tests: 55 with self.subTest(operation=operation): 56 self.assertEqual( 57 self.arithmetic_tests[operation]['function']( 58 *two_numbers 59 ), 60 'BOOM!!!' 61 ) 62 63 self.assertEqual( 64 src.calculator.add( 65 two_numbers[0], 66 two_numbers[1] 67 ), 68 self.random_first_number+self.random_second_number 69 ) 70 self.assertEqual( 71 src.calculator.divide( 72 two_numbers[-2], 73 two_numbers[-1] 74 ), 75 self.random_first_number/self.random_second_number 76 ) 77 self.assertEqual( 78 src.calculator.multiply( 79 two_numbers[1], 80 two_numbers[-1] 81 ), 82 self.random_second_number*self.random_second_number 83 ) 84 self.assertEqual( 85 src.calculator.subtract( 86 two_numbers[-2], 87 two_numbers[0] 88 ), 89 self.random_first_number-self.random_first_number 90 ) 91 self.assertEqual( 92 src.calculator.add(*two_numbers), 93 self.random_first_number+self.random_second_number 94 ) 95 self.assertEqual( 96 src.calculator.divide(*two_numbers), 97 self.random_first_number/self.random_second_number 98 ) 99 self.assertEqual( 100 src.calculator.multiply(*two_numbers), 101 self.random_first_number*self.random_second_number 102 ) 103 self.assertEqual( 104 src.calculator.subtract(*two_numbers), 105 self.random_first_number-self.random_second_number 106 ) 107 108 def test_calculator_w_dictionary_items(self):the terminal shows AssertionError for the 4 operations
SUBFAILED(operation='addition') ... - AssertionError: JK.LMNOPQRSTUVWXYZ != 'BOOM!!!' SUBFAILED(operation='subtraction') ... - AssertionError: ABCD.EFGHIJKLMNOPQ != 'BOOM!!!' SUBFAILED(operation='division') ... - AssertionError: R.STUVWXYZABCDEFGH != 'BOOM!!!' SUBFAILED(operation='multiplication') ... - AssertionError: IJKLMN.OPQRSTUVWXY != 'BOOM!!!'I change the expectation
56 self.assertEqual( 57 self.arithmetic_tests[operation]['function']( 58 *two_numbers 59 ), 60 self.arithmetic_tests[operation]['expectation'] 61 )the test passes
I remove all the other assertions that have
*two_numbers43 def test_calculator_w_list_items(self): 44 # two_numbers = [ 45 # self.random_first_number, 46 # self.random_second_number 47 # ] 48 a_dictionary = { 49 'x': self.random_first_number, 50 'y': self.random_second_number 51 } 52 two_numbers = list(a_dictionary.values()) 53 54 for operation in self.arithmetic_tests: 55 with self.subTest(operation=operation): 56 self.assertEqual( 57 self.arithmetic_tests[operation]['function']( 58 *two_numbers 59 ), 60 self.arithmetic_tests[operation]['expectation'] 61 ) 62 63 self.assertEqual( 64 src.calculator.add( 65 two_numbers[0], 66 two_numbers[1] 67 ), 68 self.random_first_number+self.random_second_number 69 ) 70 self.assertEqual( 71 src.calculator.divide( 72 two_numbers[-2], 73 two_numbers[-1] 74 ), 75 self.random_first_number/self.random_second_number 76 ) 77 self.assertEqual( 78 src.calculator.multiply( 79 two_numbers[1], 80 two_numbers[-1] 81 ), 82 self.random_second_number*self.random_second_number 83 ) 84 self.assertEqual( 85 src.calculator.subtract( 86 two_numbers[-2], 87 two_numbers[0] 88 ), 89 self.random_first_number-self.random_first_number 90 ) 91 92 def test_calculator_w_dictionary_items(self):the test is still green
I think it is time to take nap. That was a lot.
close the project
I close
test_calculator.pyin the editorI click in the terminal, then use q on the keyboard to leave the tests. The terminal goes back to the command line, the terminal shows
(.venv) .../pumping_python/calculatorI deactivate the virtual environment
deactivatethe terminal goes back to the command line,
(.venv)is no longer on the left side.../pumping_python/calculatorI change directory to the parent of
calculatorcd ..the terminal shows
.../pumping_pythonI am back in the
pumping_pythondirectory
review
I added these tests for the calculator program with dictionaries which made testing the program easier
code from the chapter
what is next?
you know
I edited makePythonTdd.sh or makePythonTdd.ps1 for the last few projects. I want to automate the process so that I can call the program and it does all the steps for me when I give it the name of the project.
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