Danger
DANGER WILL ROBINSON! Though the code works, this chapter is still UNDER CONSTRUCTION it may look completely different when I am done
dictionaries¶
A dictionary also known as a Mapping is a way to keep key-value pairs, the values can be any Python object. I add tests for the keys to see which of the Python basic data types I can use.
I think this is the most important data structure to know because they can hold all the other data structures. In programming I have had to work with JSON which I can read and write as dictionaries
preview¶
Here are the tests I have by the end of the chapter
1import unittest
2
3
4class TestDictionaries(unittest.TestCase):
5
6 def test_making_a_dictionary(self):
7 self.assertEqual(dict(), {})
8 self.assertEqual(dict(key='value'), {'key': 'value'})
9
10 def test_making_a_dictionary_w_none_as_a_key(self):
11 self.assertEqual({None: 'boom'}, {None: 'boom'})
12
13 def test_making_a_dictionary_w_a_boolean_as_a_key(self):
14 self.assertEqual(
15 {False: 'boom', True: 'bap'},
16 {False: 'boom', True: 'bap'}
17 )
18
19 def test_making_a_dictionary_w_a_number_as_a_key(self):
20 self.assertEqual(
21 {0: 'boom', 0.1: 'bap'},
22 {0: 'boom', 0.1: 'bap'}
23 )
24
25 def test_making_a_dictionary_w_a_tuple_as_a_key(self):
26 self.assertEqual(
27 {(0, 1): 'boom'},
28 {(0, 1): 'boom'}
29 )
30
31 def test_making_a_dictionary_w_a_list_as_a_key(self):
32 with self.assertRaises(TypeError):
33 {[3, 2, 1]: 'BOOM!!!'}
34
35 def test_making_a_dictionary_w_a_set_as_a_key(self):
36 with self.assertRaises(TypeError):
37 {{3, 2, 1}: 'BOOM!!!'}
38
39 def test_making_a_dictionary_w_a_dictionary_as_a_key(self):
40 a_dictionary = {'key': 'value'}
41 with self.assertRaises(TypeError):
42 {a_dictionary: 'BOOM!!!'}
43
44 def test_attributes_and_methods_of_dictionaries(self):
45 self.maxDiff = None
46 self.assertEqual(
47 dir(dict),
48 [
49 '__class__',
50 '__class_getitem__',
51 '__contains__',
52 '__delattr__',
53 '__delitem__',
54 '__dir__',
55 '__doc__',
56 '__eq__',
57 '__format__',
58 '__ge__',
59 '__getattribute__',
60 '__getitem__',
61 '__getstate__',
62 '__gt__',
63 '__hash__',
64 '__init__',
65 '__init_subclass__',
66 '__ior__',
67 '__iter__',
68 '__le__',
69 '__len__',
70 '__lt__',
71 '__ne__',
72 '__new__',
73 '__or__',
74 '__reduce__',
75 '__reduce_ex__',
76 '__repr__',
77 '__reversed__',
78 '__ror__',
79 '__setattr__',
80 '__setitem__',
81 '__sizeof__',
82 '__str__',
83 '__subclasshook__',
84 'clear',
85 'copy',
86 'fromkeys',
87 'get',
88 'items',
89 'keys',
90 'pop',
91 'popitem',
92 'setdefault',
93 'update',
94 'values'
95 ]
96 )
97
98 def test_clear_empties_a_dictionary(self):
99 a_dictionary = {'key': 'value'}
100 self.assertIsNone(a_dictionary.clear())
101 self.assertEqual(a_dictionary, {})
102
103 def test_copy_a_dictionary(self):
104 a_dictionary = {'key': 'value'}
105 self.assertEqual(
106 a_dictionary.copy(),
107 {'key': 'value'}
108 )
109
110 def test_fromkeys_makes_a_dictionary_from_an_iterable(self):
111 self.assertEqual(
112 dict.fromkeys((0, 1), 'default'),
113 {0: 'default', 1: 'default'}
114 )
115
116 def test_get_value_of_a_key_in_a_dictionary(self):
117 a_dictionary = {'key': 'value'}
118 self.assertEqual(
119 a_dictionary.get('not_in_dictionary', 'default'),
120 'default'
121 )
122 self.assertEqual(
123 a_dictionary.get('key', 'default'),
124 'value'
125 )
126
127 def test_items_returns_iterable_of_key_value_pairs_of_a_dictionary(self):
128 a_dictionary = {
129 'key1': 'value1',
130 'keyN': [0, 1, 2, 'n'],
131 }
132 self.assertEqual(
133 list(a_dictionary.items()),
134 [
135 ('key1', 'value1'),
136 ('keyN', [0, 1, 2, 'n']),
137 ]
138 )
139
140 def test_keys_of_a_dictionary(self):
141 a_dictionary = {
142 'key1': 'value1',
143 'keyN': [0, 1, 2, 'n'],
144 }
145 self.assertEqual(
146 list(a_dictionary.keys()),
147 ['key1', 'keyN']
148 )
149
150 def test_pop_removes_given_key_from_a_dictionary_and_returns_its_value(self):
151 a_dictionary = {'key': 'value'}
152
153 with self.assertRaises(KeyError):
154 a_dictionary.pop('not_in_dictionary')
155 self.assertEqual(
156 a_dictionary.pop('not_in_dictionary', 'default'),
157 'default'
158 )
159 self.assertEqual(
160 a_dictionary.pop('key', 'default'),
161 'value'
162 )
163 self.assertEqual(a_dictionary, {})
164
165 def test_popitem_removes_and_returns_last_key_value_pair_from_a_dictionary(self):
166 a_dictionary = {
167 'key1': 'value1',
168 'keyN': [0, 1, 2, 'n'],
169 }
170 self.assertEqual(
171 a_dictionary.popitem(),
172 ('keyN', [0, 1, 2, 'n'])
173 )
174 self.assertEqual(a_dictionary, {'key1': 'value1'})
175
176 def test_setdefault_adds_given_key_to_a_dictionary(self):
177 a_dictionary = {'key': 'value'}
178 self.assertEqual(
179 a_dictionary.setdefault('new_key', 'default'),
180 'default'
181 )
182 self.assertEqual(
183 a_dictionary.setdefault('key', 'default'),
184 'value'
185 )
186 self.assertEqual(
187 a_dictionary,
188 {
189 'key': 'value',
190 'new_key': 'default',
191 }
192 )
193
194 def test_update_a_dictionary(self):
195 a_dictionary = {'key': 'value'}
196 self.assertIsNone(a_dictionary.update(new_key=[0, 1, 2, 'n']))
197 self.assertIsNone(a_dictionary.update(key='updated value'))
198 self.assertIsNone(a_dictionary.update({'another_key': {0, 1, 2, 'n'}}))
199 self.assertEqual(
200 a_dictionary,
201 {
202 'key': 'updated value',
203 'new_key': [0, 1, 2, 'n'],
204 'another_key': {0, 1, 2, 'n'},
205 }
206 )
207
208 def test_values_of_a_dictionary(self):
209 a_dictionary = {
210 'key1': 'value1',
211 'keyN': [0, 1, 2, 'n'],
212 }
213 self.assertEqual(
214 list(a_dictionary.values()),
215 [
216 'value1',
217 [0, 1, 2, 'n'],
218 ]
219 )
220
221 def test_key_error(self):
222 a_dictionary = {'key': 'value'}
223 self.assertEqual(a_dictionary['key'], 'value')
224
225 with self.assertRaises(KeyError):
226 a_dictionary['not_in_dictionary']
227 self.assertEqual(
228 a_dictionary.get('not_in_dictionary', 'default'),
229 'default'
230 )
231
232 with self.assertRaises(KeyError):
233 a_dictionary.pop('not_in_dictionary')
234 self.assertEqual(
235 a_dictionary.pop('not_in_dictionary', 'default'),
236 'default'
237 )
238
239 with self.assertRaises(KeyError):
240 {}.popitem()
241
242
243# Exceptions Encountered
244# AssertionError
245# TypeError
246# KeyError
requirements¶
I open a terminal to run makePythonTdd.sh with
dictionariesas the name of the project./makePythonTdd.sh dictionarieson Windows without Windows Subsystem for Linux use makePythonTdd.ps1 instead of makePythonTdd.sh
./makePythonTdd.ps1 dictionaries
it makes the folders and files that are needed, installs packages, runs the first test, and the terminal shows AssertionError
E AssertionError: True is not false tests/test_dictionaries.py:7: AssertionError
I hold
ctrl(Windows/Linux) oroption or command(MacOS) on the keyboard and use the mouse to click ontests/test_dictionaries.py:7to open it in the editorthen I change True to False to make the test pass
7 self.assertFalse(False)I change the name of the class to match the CapWords format to follow Python convention
4class TestDictionaries(unittest.TestCase):
test_making_a_dictionary¶
RED: make it fail¶
I change test_failure to test_making_a_dictionary then add an assertion
1import unittest
2
3
4class TestDictionaries(unittest.TestCase):
5
6 def test_making_a_dictionary(self):
7 self.assertEqual(dict(), None)
the terminal shows AssertionError
AssertionError: {} != None
GREEN: make it pass¶
I change the expectation to match
6 def test_making_a_dictionary(self):
7 self.assertEqual(dict(), {})
the test passes. These are two ways to make an empty dictionary one
with the constructor -
dict()and withcurly braces -
{}
REFACTOR: make it better¶
I add another assertion, this time with input
6 def test_making_a_dictionary(self): 7 self.assertEqual(dict(), {}) 8 self.assertEqual(dict(0), {})
TypeError: 'int' object is not iterable
I add the error to the list of Exceptions encountered in
test_dictionaries.py11# Exceptions Encountered 12# AssertionError 13# TypeError
I change the value to a tuple since it is an iterable
7 self.assertEqual(dict(), {}) 8 self.assertEqual(dict((0, 1)), {})
TypeError: cannot convert dictionary update sequence element #0 to a sequence
I try a keyword argument
7 self.assertEqual(dict(), {}) 8 self.assertEqual(dict(key='value'), {})
the terminal shows AssertionError
AssertionError: {'key': 'value'} != {}
I change the expectation to match the values in the terminal
self.assertEqual(dict(key='value'), {'key': 'value'})
the test passes.
I can make a dictionary with the dict constructor or curly braces({}) and I used a string as a key in this test. Next I test the Python basic data types to see which ones I can use as keys
test_making_a_dictionary_w_none_as_a_key¶
RED: make it fail¶
I add a test to see if I can use None as a key in a dictionary
8 self.assertEqual(dict(key='value'), {'key': 'value'})
9
10 def test_making_a_dictionary_w_none_as_a_key(self):
11 self.assertEqual({None: 'boom'}, {None: 'bap'})
12
13
14# Exceptions Encountered
the terminal shows AssertionError
AssertionError: {None: 'boom'} != {None: 'bap'}
GREEN: make it pass¶
I change 'bap' to 'boom'
11 self.assertEqual({None: 'boom'}, {None: 'boom'})
the test passes. I can use None and strings as keys in a dictionary
test_making_a_dictionary_w_a_boolean_as_a_key¶
RED: make it fail¶
I add a test to see if I can use a boolean as a key in a dictionary
10 def test_making_a_dictionary_w_none_as_a_key(self):
11 self.assertEqual({None: 'boom'}, {None: 'boom'})
12
13 def test_making_a_dictionary_w_a_boolean_as_a_key(self):
14 self.assertEqual({False: 'boom'}, {False: 'bap'})
15
16
17# Exceptions Encountered
the terminal shows AssertionError
AssertionError: {False: 'boom'} != {False: 'bap'}
GREEN: make it pass¶
I change 'bap' to 'boom'
14 self.assertEqual({False: 'boom'}, {False: 'boom'})
the tests passes. I can use False as a key in a dictionary
REFACTOR: make it better¶
I add an assertion for the other boolean
13 def test_making_a_dictionary_w_a_boolean_as_a_key(self):
14 self.assertEqual(
15 {False: 'boom', True: 'bap'},
16 {False: 'boom'}
17 )
the terminal shows AssertionError
AssertionError: {False: 'boom', True: 'bap'} != {False: 'boom'}
I add the new key-value pair to the expectation
14 self.assertEqual(
15 {False: 'boom', True: 'bap'},
16 {False: 'boom', True: 'bap'}
17 )
the test passes. I can use booleans, None and strings as keys in a dictionary
test_making_a_dictionary_w_a_number_as_a_key¶
RED: make it fail¶
I add a failing test to see if I can use a number as a key in a dictionary
16 {False: 'boom', True: 'bap'}
17 )
18
19 def test_making_a_dictionary_w_a_number_as_a_key(self):
20 self.assertEqual(
21 {0: 'boom'},
22 {0: 'bap'}
23 )
24
25
26# Exceptions Encountered
the terminal shows AssertionError
AssertionError: {0: 'boom'} != {0: 'bap'}
GREEN: make it pass¶
I change 'bap' to 'boom'
20 self.assertEqual(
21 {0: 'boom'},
22 {0: 'boom'}
23 )
the test passes. I can use an integer as a key in a dictionary
REFACTOR: make it better¶
I want to see if I can use a float as a key in a dictionary
def test_making_a_dictionary_w_a_number_as_a_key(self):
self.assertEqual(
{0: 'boom', 0.1: 'bap'},
{0: 'boom'}
)
the terminal shows AssertionError
AssertionError: {0: 'boom', 0.1: 'bap'} != {0: 'boom'}
I add the new key-value pair to the expectation
20 self.assertEqual(
21 {0: 'boom', 0.1: 'bap'},
22 {0: 'boom', 0.1: 'bap'}
23 )
the test passes. I can use numbers (floats and integers), booleans, None and strings as keys in a dictionary
test_making_a_dictionary_w_a_tuple_as_a_key¶
RED: make it fail¶
I add a test to see if I can use a tuple (anything in parentheses (())) as a key in a dictionary
22 {0: 'boom', 0.1: 'bap'}
23 )
24
25 def test_making_a_dictionary_w_a_tuple_as_a_key(self):
26 self.assertEqual(
27 {(0, 1): 'boom'},
28 {(0, 1): 'bap'}
29 )
30
31
32# Exceptions Encountered
the terminal shows AssertionError
AssertionError: {(0, 1): 'boom'} != {(0, 1): 'bap'}
GREEN: make it pass¶
I change 'bap' to 'boom'
26 self.assertEqual(
27 {(0, 1): 'boom'},
28 {(0, 1): 'boom'}
29 )
the test passes. I can use tuples, numbers (floats and integers), booleans, None and strings as keys in a dictionary
test_making_a_dictionary_w_a_list_as_a_key¶
RED: make it fail¶
I add a test for lists (anything in square brackets ([]))
28 {(0, 1): 'boom'}
29 )
30
31 def test_making_a_dictionary_w_a_list_as_a_key(self):
32 self.assertEqual(
33 {[0, 1]: 'boom'},
34 )
35
36
37# Exceptions Encountered
TypeError: unhashable type: 'list'
GREEN: make it pass¶
I remove the things around the new dictionary then change the key and value for fun
31 def test_making_a_dictionary_w_a_list_as_a_key(self):
32
33 {[3, 2, 1]: 'BOOM!!!'}
the terminal still shows TypeError. I add assertRaises
31 def test_making_a_dictionary_w_a_list_as_a_key(self):
32 with self.assertRaises(TypeError):
33 {[3, 2, 1]: 'BOOM!!!'}
the test passes. I cannot use a list as a key in a dictionary
test_making_a_dictionary_w_a_set_as_a_key¶
RED: make it fail¶
I add another test with a set (single items in a curly braces ({})) as a key in a dictionary
33 {[3, 2, 1]: 'BOOM!!!'}
34
35 def test_making_a_dictionary_w_a_set_as_a_key(self):
36 {{3, 2, 1}: 'BOOM!!!'}
37
38
39# Exceptions Encountered
TypeError: unhashable type: 'set'
GREEN: make it pass¶
I add assertRaises to handle the Exception
35 def test_making_a_dictionary_w_a_set_as_a_key(self):
36 with self.assertRaises(TypeError):
37 {{3, 2, 1}: 'BOOM!!!'}
the test is green again. I cannot use lists or sets as keys in a dictionary
test_making_a_dictionary_w_a_dictionary_as_a_key¶
RED: make it fail¶
I add another test, this time for a dictionary
37 {{3, 2, 1}: 'BOOM!!!'}
38
39 def test_making_a_dictionary_w_a_dictionary_as_a_key(self):
40 a_dictionary = {'key': 'value'}
41 {a_dictionary: 'BOOM!!!'}
42
43
44# Exceptions Encountered
TypeError: unhashable type: 'dict'
GREEN: make it pass¶
I add assertRaises
39 def test_making_a_dictionary_w_a_dictionary_as_a_key(self):
40 a_dictionary = {'key': 'value'}
41 with self.assertRaises(TypeError):
42 {a_dictionary: 'BOOM!!!'}
43
44
45# Exceptions Encountered
the test passes. I cannot use dictionaries, sets or lists as keys in a dictionary. They are not hashable, which means they can change in their lifetime
test_attributes_and_methods_of_dictionaries¶
RED: make it fail¶
I add a new test with the dir function to see the attributes and methods of dictionaries
42 {a_dictionary: 'BOOM!!!'}
43
44 def test_attributes_and_methods_of_dictionaries(self):
45 self.assertEqual(
46 dir(dict),
47 []
48 )
49
50
51# Exceptions Encountered
the terminal shows AssertionError
AssertionError: Lists differ: ['__class__', '__class_getitem__', '__cont[530 chars]ues'] != []
It also gives me a message about how to show the full difference between the two lists
Diff is 720 characters long. Set self.maxDiff to None to see it.
maxDiff is a class attribute that is used to set the maximum length of differences between 2 items that the terminal shows
GREEN: make it pass¶
I move the terminal to right side of the screen
I add maxDiff to the test
44 def test_attributes_and_methods_of_dictionaries(self): 45 self.maxDiff = None 46 self.assertEqual( 47 dir(dict), 48 [] 49 )
the terminal shows the full difference between the two lists. I copy and paste the expected values from the terminal then use find and replace to remove the extra characters
Note
results can be different because of the Python version.
44 def test_attributes_and_methods_of_dictionaries(self): 45 self.maxDiff = None 46 self.assertEqual( 47 dir(dict), 48 [ 49 '__class__', 50 '__class_getitem__', 51 '__contains__', 52 '__delattr__', 53 '__delitem__', 54 '__dir__', 55 '__doc__', 56 '__eq__', 57 '__format__', 58 '__ge__', 59 '__getattribute__', 60 '__getitem__', 61 '__getstate__', 62 '__gt__', 63 '__hash__', 64 '__init__', 65 '__init_subclass__', 66 '__ior__', 67 '__iter__', 68 '__le__', 69 '__len__', 70 '__lt__', 71 '__ne__', 72 '__new__', 73 '__or__', 74 '__reduce__', 75 '__reduce_ex__', 76 '__repr__', 77 '__reversed__', 78 '__ror__', 79 '__setattr__', 80 '__setitem__', 81 '__sizeof__', 82 '__str__', 83 '__subclasshook__', 84 'clear', 85 'copy', 86 'fromkeys', 87 'get', 88 'items', 89 'keys', 90 'pop', 91 'popitem', 92 'setdefault', 93 'update', 94 'values' 95 ] 96 )
the test passes
I copy the names that do NOT have double underscores (__) and paste them below the test to make a TODO list that I use to test what I can do with dictionaries
93 'update', 94 'values' 95 ] 96 ) 97 98 99'clear', 100'copy', 101'fromkeys', 102'get', 103'items', 104'keys', 105'pop', 106'popitem', 107'setdefault', 108'update', 109'values' 110 111 112# Exceptions Encountered
the terminal still shows green
I move the terminal back to the bottom of the screen
test_clear_empties_a_dictionary¶
RED: make it fail¶
I add a test for the first method
93 'update', 94 'values' 95 ] 96 ) 97 98 def test_clear(self): 99 a_dictionary = {'key': 'value'} 100 self.assertIsNone(a_dictionary.clear()) 101 102 103'clear', 104'copy',
I add an assertion to see what clear did to the dictionary
98 def test_clear(self): 99 a_dictionary = {'key': 'value'} 100 self.assertIsNone(a_dictionary.clear()) 101 self.assertEqual(a_dictionary, {'key': 'value'})
the terminal shows AssertionError
AssertionError: {} != {'key': 'value'}
the clear method emptied the dictionary, same as it does with lists
GREEN: make it pass¶
I change the values to match
98 def test_clear(self):
99 a_dictionary = {'key': 'value'}
100 self.assertIsNone(a_dictionary.clear())
101 self.assertEqual(a_dictionary, {})
the test passes
REFACTOR: make it better¶
I change the name of the test
98 def test_clear_empties_a_dictionary(self): 99 a_dictionary = {'key': 'value'} 100 self.assertIsNone(a_dictionary.clear()) 101 self.assertEqual(a_dictionary, {}) 102 103 104'clear', 105'copy',
I remove clear from the TODO list
104'copy', 105'fromkeys', 106'get', 107'items', 108'keys', 109'pop', 110'popitem', 111'setdefault', 112'update', 113'values'
test_copy_a_dictionary¶
RED: make it fail¶
I add a test for the next method
101 self.assertEqual(a_dictionary, {})
102
103 def test_copy(self):
104 a_dictionary = {'key': 'value'}
105 self.assertIsNone(a_dictionary.copy())
106
107
108'copy',
109'fromkeys',
the terminal shows AssertionError
AssertionError: {'key': 'value'} is not None
this method returns a copy of the dictionary, same as with lists
GREEN: make it pass¶
I add the value to the assertion
103 def test_copy(self):
104 a_dictionary = {'key': 'value'}
105 self.assertIsNone(
106 a_dictionary.copy(),
107 {'key': 'value'}
108 )
the terminal shows AssertionError
AssertionError: {'key': 'value'} is not None : {'key': 'value'}
I change assertIsNone to assertEqual
103 def test_copy(self):
104 a_dictionary = {'key': 'value'}
105 self.assertEqual(
106 a_dictionary.copy(),
107 {'key': 'value'}
108 )
the test passes
REFACTOR: make it better¶
I change the name of the test
103 def test_copy_a_dictionary(self): 104 a_dictionary = {'key': 'value'} 105 self.assertEqual( 106 a_dictionary.copy(), 107 {'key': 'value'} 108 ) 109 110 111'copy', 112'fromkeys',
I remove copy from the TODO list
111'fromkeys', 112'get', 113'items', 114'keys', 115'pop', 116'popitem', 117'setdefault', 118'update', 119'values'
test_fromkeys_makes_a_dictionary_from_an_iterable¶
RED: make it fail¶
I add a test for the next method from the TODO list
107 {'key': 'value'}
108 )
109
110 def test_fromkeys(self):
111 a_dictionary = {'key': 'value'}
112 self.assertIsNone(a_dictionary.fromkeys())
113
114
115'fromkeys',
TypeError: fromkeys expected at least 1 argument, got 0
GREEN: make it pass¶
I pass a value to the call
110 def test_fromkeys(self): 111 a_dictionary = {'key': 'value'} 112 self.assertIsNone(a_dictionary.fromkeys(0))
TypeError: 'int' object is not iterable
I change the value to a tuple
112 self.assertIsNone(a_dictionary.fromkeys((0, 1)))the terminal shows AssertionError
AssertionError: {0: None, 1: None} is not None
the fromkeys method returns a dictionary that uses the values in the iterable as keys with default values of None
I add the dictionary as an expectation
110 def test_fromkeys(self): 111 a_dictionary = {'key': 'value'} 112 self.assertIsNone( 113 a_dictionary.fromkeys((0, 1)), 114 {0: None, 1: None} 115 )
the terminal shows AssertionError
AssertionError: {0: None, 1: None} is not None : {0: None, 1: None}
I change assertIsNone to assertEqual
112 self.assertEqual( 113 a_dictionary.fromkeys((0, 1)), 114 {0: None, 1: None} 115 )
the test passes
REFACTOR: make it better¶
I add another assert method to see what happens to the first dictionary in the test
110 def test_fromkeys(self): 111 a_dictionary = {'key': 'value'} 112 self.assertEqual( 113 a_dictionary.fromkeys((0, 1)), 114 {0: None, 1: None} 115 ) 116 self.assertEqual(a_dictionary, {})
the terminal shows AssertionError
AssertionError: {'key': 'value'} != {}
the dictionary did not change
I remove the last line I added
I change the call fromkeys to use the dict class instead
110 def test_fromkeys(self): 111 a_dictionary = {'key': 'value'} 112 self.assertEqual( 113 dict.fromkeys((0, 1)), 114 {0: None, 1: None} 115 ) 116 117 118'fromkeys',
the test is still green
I remove
a_dictionarysince it is not used110 def test_fromkeys(self): 111 self.assertEqual( 112 dict.fromkeys((0, 1)), 113 {0: None, 1: None} 114 ) 115 116 117'fromkeys',
still green
the dictionary made with the fromkeys method has None as the default values. When I called the method without inputs the terminal showed TypeError
TypeError: fromkeys expected at least 1 argument, got 0
I add a second input to the call to see what happens
111 self.assertEqual( 112 dict.fromkeys((0, 1), None), 113 {0: None, 1: None} 114 )
the terminal still shows green
I change the second input expecting a failure
111 self.assertEqual( 112 dict.fromkeys((0, 1), 'default'), 113 {0: None, 1: None} 114 )
the terminal shows AssertionError
AssertionError: {0: 'default', 1: 'default'} != {0: None, 1: None}
I change the values to match
111 self.assertEqual( 112 dict.fromkeys((0, 1), 'default'), 113 {0: 'default', 1: 'default'} 114 )
the test is green again. This is like a dict comprehension because it made a dictionary using the items from the iterable as keys
I change the name of the test
110 def test_fromkeys_makes_a_dictionary_from_an_iterable(self): 111 self.assertEqual( 112 dict.fromkeys((0, 1), 'default'), 113 {0: 'default', 1: 'default'} 114 ) 115 116 117'fromkeys', 118'get',
I remove fromkeys from the TODO list
117'get', 118'items', 119'keys', 120'pop', 121'popitem', 122'setdefault', 123'update', 124'values'
test_get_value_of_a_key_in_a_dictionary¶
RED: make it fail¶
I add a test for the get method
107 {0: 'default', 1: 'default'}
108 )
109
110 def test_get(self):
111 a_dictionary = {'key': 'value'}
112 self.assertIsNone(a_dictionary.get())
113
114
115'get',
TypeError: get expected at least 1 argument, got 0
GREEN: make it pass¶
I add a value to the call
118 self.assertIsNone(a_dictionary.get(0))
the test passes
REFACTOR: make it better¶
the get method also expected at least 1 argument, I add None to the call
118 self.assertIsNone(a_dictionary.get(0, None))the terminal still shows green
I change the second argument expecting a failure
118 self.assertIsNone(a_dictionary.get(0, 'default'))the terminal shows AssertionError
AssertionError: 'default' is not None
I add the expectation
118 def test_get(self): 119 a_dictionary = {'key': 'value'} 120 self.assertIsNone( 121 a_dictionary.get(0, 'default'), 122 'default' 123 )
the terminal shows AssertionError
AssertionError: 'default' is not None : default
I change assertIsNone to assertEqual
118 self.assertEqual( 119 a_dictionary.get(0, 'default'), 120 'default' 121 )
the test passes
I change
0in the call to get to be more descriptive118 self.assertEqual( 119 a_dictionary.get('not_in_dictionary', 'default'), 120 'default' 121 )
the test is still green
I want to see what happens when I use the get method with a key that is in the dictionary, I add another assertion
118 self.assertEqual( 119 a_dictionary.get('not_in_dictionary', 'default'), 120 'default' 121 ) 122 self.assertEqual( 123 a_dictionary.get('key', 'default'), 124 'default' 125 ) 126 127 128'get',
the terminal shows AssertionError
AssertionError: 'value' != 'default'
I get
'value'back. I change the expectation to match122 self.assertEqual( 123 a_dictionary.get('key', 'default'), 124 'value' 125 )
the test passes.
The get method has a condition
When the key is NOT in the dictionary, it returns the default argument
When the key is in the dictionary, it returns its value.
I change the name of the test
116 def test_get_value_of_a_key_in_a_dictionary(self): 117 a_dictionary = {'key': 'value'} 118 self.assertEqual( 119 a_dictionary.get('not_in_dictionary', 'default'), 120 'default' 121 ) 122 self.assertEqual( 123 a_dictionary.get('key', 'default'), 124 'value' 125 ) 126 127 128'get',
the test is still green
I remove get from the TODO list
128'items', 129'keys', 130'pop', 131'popitem', 132'setdefault', 133'update', 134'values'
test_items_returns_iterable_of_key_value_pairs_of_a_dictionary¶
RED: make it fail¶
I add the next test from the TODO list
124 'value'
125 )
126
127 def test_items(self):
128 a_dictionary = {'key': 'value'}
129 self.assertIsNone(a_dictionary.items())
130
131
132'items',
the terminal shows AssertionError
AssertionError: dict_items([('key', 'value')]) is not None
GREEN: make it pass¶
I copy the
dict_itemsobject from the terminal and paste it as the expectation129 self.assertIsNone( 130 a_dictionary.items(), 131 dict_items([('key', 'value')]) 132 )
NameError: name 'dict_items' is not defined
this new object has a list and I know how to work with lists
I remove the stuff around the list
129 self.assertIsNone( 130 a_dictionary.items(), 131 [('key', 'value')] 132 )
the terminal shows AssertionError
AssertionError: dict_items([('key', 'value')]) is not None : [('key', 'value')]
I pass the call to the items method to the list constructor to see if it is iterable
129 self.assertIsNone( 130 list(a_dictionary.items()), 131 [('key', 'value')] 132 )
the terminal shows AssertionError
AssertionError: [('key', 'value')] is not None : [('key', 'value')]
the values are the same
I change assertIsNone to assertEqual
129 self.assertEqual( 130 list(a_dictionary.items()), 131 [('key', 'value')] 132 )
the test passes.
This works because the items method returns an iterable of the key-value pairs of the dictionary. The
dict_itemsobject is iterable
REFACTOR: make it better¶
I add another key-value pair to the dictionary to see what the method does when there is more than one
127 def test_items(self): 128 a_dictionary = { 129 'key1': 'value1', 130 'keyN': [0, 1, 2, 'n'], 131 } 132 self.assertEqual( 133 list(a_dictionary.items()), 134 [('key', 'value')] 135 ) 136 137 138'items',
the terminal shows AssertionError
AssertionError: Lists differ: [('key1', 'value1'), ('keyN', [0, 1, 2, 'n'])] != [('key', 'value')]
I change the expectation to match
132 self.assertEqual( 133 list(a_dictionary.items()), 134 [ 135 ('key1', 'value1'), 136 ('keyN', [0, 1, 2, 'n']), 137 ] 138 )
the test passes
I change the name of the test
127 def test_items_returns_iterable_of_key_value_pairs_of_a_dictionary(self): 128 a_dictionary = { 129 'key1': 'value1', 130 'keyN': [0, 1, 2, 'n'], 131 } 132 self.assertEqual( 133 list(a_dictionary.items()), 134 [ 135 ('key1', 'value1'), 136 ('keyN', [0, 1, 2, 'n']), 137 ] 138 ) 139 140 141'items',
I remove items from the TODO list
141'keys', 142'pop', 143'popitem', 144'setdefault', 145'update', 146'values'
all tests are still passing
test_keys_of_a_dictionary¶
RED: make it fail¶
I add a new test
136 ('keyN', [0, 1, 2, 'n']),
137 ]
138 )
139
140 def test_keys(self):
141 a_dictionary = {'key': 'value'}
142 self.assertIsNone(a_dictionary.keys())
143
144
145'keys',
the terminal shows AssertionError
AssertionError: dict_keys(['key']) is not None
this looks like the error in test_items_returns_iterable_of_key_value_pairs_of_a_dictionary
GREEN: make it pass¶
I copy the
dict_keysobject from the terminal and paste it as the expectation140 def test_keys(self): 141 a_dictionary = {'key': 'value'} 142 self.assertIsNone( 143 a_dictionary.keys(), 144 dict_keys(['key']) 145 )
NameError: name 'dict_keys' is not defined
I use the list in the
dict_keysobject as the expectation instead142 def test_keys(self): 143 a_dictionary = {'key': 'value'} 144 self.assertIsNone( 145 a_dictionary.keys(), 146 ['key'] 147 )
the terminal shows AssertionError
AssertionError: dict_keys(['key']) is not None : ['key']
I pass the call to the keys method to the list constructor to see if
dict_keysis iterable142 self.assertIsNone( 143 list(a_dictionary.keys()), 144 ['key'] 145 )
the terminal shows AssertionError
AssertionError: ['key'] is not None : ['key']
I change assertIsNone to assertEqual
142 self.assertEqual( 143 list(a_dictionary.keys()), 144 ['key'] 145 )
the test passes
REFACTOR: make it better¶
I add another key-value pair to the dictionary to see what the keys method returns when there are multiple
140 def test_keys(self): 141 a_dictionary = { 142 'key1': 'value1', 143 'keyN': [0, 1, 2, 'n'], 144 } 145 self.assertEqual( 146 list(a_dictionary.keys()), 147 ['key'] 148 )
the terminal shows AssertionError
AssertionError: Lists differ: ['key1', 'keyN'] != ['key']
I change the expectation to match
145 self.assertEqual( 146 list(a_dictionary.keys()), 147 ['key1', 'keyN'] 148 )
the test passes
I change the name of the test
140 def test_keys_of_a_dictionary(self): 141 a_dictionary = { 142 'key1': 'value1', 143 'keyN': [0, 1, 2, 'n'], 144 } 145 self.assertEqual( 146 list(a_dictionary.keys()), 147 ['key1', 'keyN'] 148 ) 149 150 151'keys',
I remove keys from the TODO list
151'pop', 152'popitem', 153'setdefault', 154'update', 155'values'
test_pop_removes_given_key_from_a_dictionary_and_returns_its_value¶
RED: make it fail¶
I wonder if the next method behaves the same way as it did in test_pop_removes_and_returns_last_item_from_a_list, I add a test for it
147 ['key1', 'keyN']
148 )
149
150 def test_pop(self):
151 a_dictionary = {'key': 'value'}
152 self.assertIsNone(a_dictionary.pop())
153
154
155'pop',
TypeError: pop expected at least 1 argument, got 0
GREEN: make it pass¶
I pass a value to the call
152 self.assertIsNone(a_dictionary.pop(0))KeyError: 0
I add it to the list of Exceptions encountered
162# Exceptions Encountered 163# AssertionError 164# TypeError 165# KeyError
I remove the things around the call in the test and change the value given to be more descriptive
150 def test_pop(self): 151 a_dictionary = {'key': 'value'} 152 a_dictionary.pop('not_in_dictionary')
KeyError: 'not in dictionary'
I add assertRaises
150 def test_pop(self): 151 a_dictionary = {'key': 'value'} 152 153 with self.assertRaises(KeyError): 154 a_dictionary.pop('not_in_dictionary')
the test passes. When I call the pop method with a key that is not in the dictionary it raises KeyError
REFACTOR: make it better¶
When I called the pop method without input, the terminal showed TypeError
TypeError: pop expected at least 1 argument, got 0
I add another assertion to see what happens when I call it with 2 arguments
153 with self.assertRaises(KeyError): 154 a_dictionary.pop('not_in_dictionary') 155 self.assertIsNone(a_dictionary.pop('not_in_dictionary', None))
the test is still green
I change the second argument, expecting a failure
155 self.assertIsNone(a_dictionary.pop('not_in_dictionary', 'default'))the terminal shows AssertionError
AssertionError: 'default' is not None
I add the expectation
155 self.assertIsNone( 156 a_dictionary.pop('not_in_dictionary', 'default'), 157 'default' 158 )
the terminal shows AssertionError
AssertionError: 'default' is not None : default
I change assertIsNone to assertEqual
155 self.assertEqual( 156 a_dictionary.pop('not_in_dictionary', 'default'), 157 'default' 158 )
the test passes
I add another assertion to see what happens when I call the pop method with a key that is in the dictionary
155 self.assertEqual( 156 a_dictionary.pop('not_in_dictionary', 'default'), 157 'default' 158 ) 159 self.assertEqual( 160 a_dictionary.pop('key', 'default'), 161 'default' 162 )
the terminal shows AssertionError
AssertionError: 'value' != 'default'
I get
'value'back. The pop method returns the value of the given key from the dictionaryI change the expectation to match
159 self.assertEqual( 160 a_dictionary.pop('key', 'default'), 161 'value' 162 )
the test passes
I add another assertion to see what the pop method did to the dictionary
159 self.assertEqual( 160 a_dictionary.pop('key', 'default'), 161 'value' 162 ) 163 self.assertEqual(a_dictionary, {'key': 'value'})
the terminal shows AssertionError
AssertionError: {} != {'key': 'value'}
the pop method removes the key-value pair and returns the value of the given key from the dictionary
I change the expectation to match
163self.assertEqual(a_dictionary, {})the test passes
I change the name of the test
150 def test_pop_removes_given_key_from_a_dictionary_and_returns_its_value(self): 151 a_dictionary = {'key': 'value'} 152 153 with self.assertRaises(KeyError): 154 a_dictionary.pop('not_in_dictionary') 155 self.assertEqual( 156 a_dictionary.pop('not_in_dictionary', 'default'), 157 'default' 158 ) 159 self.assertEqual( 160 a_dictionary.pop('key', 'default'), 161 'value' 162 ) 163 self.assertEqual(a_dictionary, {}) 164 165 166'pop',
I remove pop from the TODO list
166'popitem', 167'setdefault', 168'update', 169'values'
test_popitem_removes_and_returns_last_key_value_pair_from_a_dictionary¶
RED: make it fail¶
I add a failing test for the next item in the TODO list
163 self.assertEqual(a_dictionary, {})
164
165 def test_popitem(self):
166 a_dictionary = {'key': 'value'}
167 self.assertIsNone(a_dictionary.popitem())
168
169
170'popitem',
the terminal shows AssertionError
AssertionError: ('key', 'value') is not None
the popitem method returns the key-value pair in the dictionary as a tuple
GREEN: make it pass¶
I add the value from the terminal as the expectation
166 a_dictionary = {'key': 'value'}
167 self.assertIsNone(
168 a_dictionary.popitem(),
169 ('key', 'value')
170 )
the terminal shows AssertionError
AssertionError: ('key', 'value') is not None : ('key', 'value')
I change assertIsNone to assertEqual
167 self.assertEqual(
168 a_dictionary.popitem(),
169 ('key', 'value')
170 )
the test passes
REFACTOR: make it better¶
I want to know what the popitem method did to the dictionary. I add another assertion
167 self.assertEqual( 168 a_dictionary.popitem(), 169 ('key', 'value') 170 ) 171 self.assertEqual(a_dictionary, {'key': 'value'})
the terminal shows AssertionError
AssertionError: {} != {'key': 'value'}
popitem removes and returns the key-value pair from the dictionary
I change the value to match
171 self.assertEqual(a_dictionary, {})the test passes
this operation does not take input, I change the dictionary to see what happens
165 def test_popitem(self): 166 a_dictionary = { 167 'key1': 'value1', 168 'keyN': [0, 1, 2, 'n'], 169 } 170 self.assertEqual( 171 a_dictionary.popitem(), 172 ('key', 'value') 173 ) 174 self.assertEqual(a_dictionary, {})
the terminal shows AssertionError
AssertionError: Tuples differ: ('keyN', [0, 1, 2, 'n']) != ('key', 'value')
I change the expectation in the first assertEqual to match
170 self.assertEqual( 171 a_dictionary.popitem(), 172 ('keyN', [0, 1, 2, 'n']) 173 )
the terminal shows AssertionError
AssertionError: {'key1': 'value1'} != {'key': 'value'}
I change the value in the second assertEqual to match
self.assertEqual(a_dictionary, {'key1': 'value1'})
the test passes. popitem removes and returns the last key-value pair from a dictionary
I change the name of the test
165 def test_popitem_removes_and_returns_last_key_value_pair_from_a_dictionary(self): 166 a_dictionary = { 167 'key1': 'value1', 168 'keyN': [0, 1, 2, 'n'], 169 } 170 self.assertEqual( 171 a_dictionary.popitem(), 172 ('keyN', [0, 1, 2, 'n']) 173 ) 174 self.assertEqual(a_dictionary, {'key1': 'value1'}) 175 176 177'popitem',
I remove popitem from the TODO list
177'setdefault', 178'update', 179'values'
test_setdefault_adds_given_key_to_a_dictionary¶
RED: make it fail¶
I add a test for the next method
174 self.assertEqual(a_dictionary, {'key1': 'value1'})
175
176 def test_setdefault(self):
177 a_dictionary = {'key': 'value'}
178 self.assertIsNone(a_dictionary.setdefault())
179
180
181'setdefault',
TypeError: setdefault expected at least 1 argument, got 0
GREEN: make it pass¶
I pass a value in the call
178 self.assertIsNone(a_dictionary.setdefault(0))
the test passes
REFACTOR: make it better¶
The error message showed that the method expects at least 1 argument, I add a second argument
178 self.assertIsNone(a_dictionary.setdefault(0, None))the test is still green
I change the second argument expecting a failure
178 self.assertIsNone(a_dictionary.setdefault(0, 'default'))the terminal shows AssertionError
AssertionError: 'default' is not None
I add the expectation
177 a_dictionary = {'key': 'value'} 178 self.assertIsNone( 179 a_dictionary.setdefault(0, 'default'), 180 'default' 181 )
the terminal shows AssertionError
AssertionError: 'default' is not None : default
I change assertIsNone to assertEqual
178 self.assertEqual( 179 a_dictionary.setdefault(0, 'default'), 180 'default' 181 )
the test passes
I add an assertion to see what setdefault did to the dictionary
178 self.assertEqual( 179 a_dictionary.setdefault(0, 'default'), 180 'default' 181 ) 182 self.assertEqual(a_dictionary, {'key': 'value'})
the terminal shows AssertionError
AssertionError: {'key': 'value', 0: 'default'} != {'key': 'value'}
setdefault adds the given key to the dictionary with the default value and returns the default value
I change the expectation to match
176 def test_setdefault(self): 177 a_dictionary = {'key': 'value'} 178 self.assertEqual( 179 a_dictionary.setdefault(0, 'default'), 180 'default' 181 ) 182 self.assertEqual( 183 a_dictionary, 184 { 185 'key': 'value', 186 0: None, 187 } 188 )
the test passes
I change the
0given to the call to be more descriptive178 self.assertEqual( 179 a_dictionary.setdefault('new_key', 'default'), 180 'default' 181 )
the terminal shows AssertionError
AssertionError: {'key': 'value', 'new_key': 'default'} != {'key': 'value', 0: 'default'}
I change the expectation to match
182 self.assertEqual( 183 a_dictionary, 184 { 185 'key': 'value', 186 'new_key': 'default', 187 } 188 )
the test is green again
I add an assertion to see what happens when I use setdefault with a key that is already in the dictionary
178 def test_setdefault(self): 179 a_dictionary = {'key': 'value'} 180 self.assertEqual( 181 a_dictionary.setdefault('new_key', 'default'), 182 'default' 183 ) 184 self.assertEqual( 185 a_dictionary.setdefault('key', 'default'), 186 'default' 187 ) 188 self.assertEqual( 189 a_dictionary, 190 { 191 'key': 'value', 192 'new_key': 'default', 193 } 194 )
the terminal shows AssertionError
AssertionError: 'value' != 'default'
I get
'value'back. setdefault returns the value for a key in a dictionary when the key is in the dictionaryI change the expectation to match
182 self.assertEqual( 183 a_dictionary.setdefault('key', 'default'), 184 'value' 185 )
the test passes
setdefault has a condition
when the key is NOT in the dictionary it adds it with a default value of None and returns None
when the key is NOT in the dictionary and I call setdefault with a second argument, it adds the key to the dictionary with the second argument as the value and returns the second argument
when the key is in the dictionary it returns value from the dictionary
I change the name of the test
176 def test_setdefault_adds_given_key_to_a_dictionary(self): 177 a_dictionary = {'key': 'value'} 178 self.assertEqual( 179 a_dictionary.setdefault('new_key', 'default'), 180 'default' 181 ) 182 self.assertEqual( 183 a_dictionary.setdefault('key', 'default'), 184 'value' 185 ) 186 self.assertEqual( 187 a_dictionary, 188 { 189 'key': 'value', 190 'new_key': 'default', 191 } 192 ) 193 194 195'setdefault',
I remove setdefault from the TODO list
195'update', 196'values'
test_update_a_dictionary¶
RED: make it fail¶
I add a test for the next method from the TODO list
190 'new_key': 'default', 191 } 192 ) 193 194 def test_update(self): 195 a_dictionary = {'key': 'value'} 196 self.assertIsNone(a_dictionary.update()) 197 198 199'update',
I add an assertion to see what it did to the dictionary
194 def test_update(self): 195 a_dictionary = {'key': 'value'} 196 self.assertIsNone(a_dictionary.update()) 197 self.assertEqual(a_dictionary, {})
the terminal shows AssertionError
AssertionError: {'key': 'value'} != {}
the dictionary did not change
GREEN: make it pass¶
I change the values in the expectation to match the terminal
197 self.assertEqual(a_dictionary, {'key': 'value'})
the test passes
REFACTOR: make it better¶
I add a value to the call to the update method to see what happens
194 def test_update(self): 195 a_dictionary = {'key': 'value'} 196 self.assertIsNone(a_dictionary.update(0)) 197 self.assertEqual(a_dictionary, {'key': 'value'})
TypeError: 'int' object is not iterable
I change the value to a tuple
196 self.assertIsNone(a_dictionary.update((0, 1)))TypeError: cannot convert dictionary update sequence element #0 to a sequence
I had the same error message when I tried to make a dictionary with things in it
I try a keyword argument
196 self.assertIsNone(a_dictionary.update(new_key=[0, 1, 2, 'n']))the terminal shows AssertionError
AssertionError: {'key': 'value', 'new_key': [0, 1, 2, 'n']} != {'key': 'value'}
I add the new key-value pair to the expectation
196 self.assertIsNone(a_dictionary.update(new_key=[0, 1, 2, 'n'])) 197 self.assertEqual( 198 a_dictionary, 199 { 200 'key': 'value', 201 'new_key': [0, 1, 2, 'n'], 202 } 203 )
the test passes
I add an assertion to see what happens when I give a key that is already in the dictionary
194 def test_update(self): 195 a_dictionary = {'key': 'value'} 196 self.assertIsNone(a_dictionary.update(new_key=[0, 1, 2, 'n'])) 197 self.assertIsNone(a_dictionary.update(key='updated value')) 198 self.assertEqual(
the terminal shows AssertionError
AssertionError: {'key': 'updated value', 'new_key': [0, 1, 2, 'n']} != {'key': 'value', 'new_key': [0, 1, 2, 'n']}
the update method changes the value for a key that is already in a dictionary
I change the expectation to match
198 self.assertEqual( 199 a_dictionary, 200 { 201 'key': 'updated value', 202 'new_key': [0, 1, 2, 'n'], 203 } 204 )
the test passes
since the update method takes keyword arguments, I can give it a dictionary as input. I add another assertion
194 def test_update(self): 195 a_dictionary = {'key': 'value'} 196 self.assertIsNone(a_dictionary.update(new_key=[0, 1, 2, 'n'])) 197 self.assertIsNone(a_dictionary.update(key='updated value')) 198 self.assertIsNone(a_dictionary.update({'another_key': {0, 1, 2, 'n'}})) 199 self.assertEqual(
the terminal shows AssertionError
AssertionError: {'key[14 chars]lue', 'new_key': [0, 1, 2, 'n'], 'another_key': {0, 1, 2, 'n'}} != {'key[14 chars]lue', 'new_key': [0, 1, 2, 'n']}
I can use the update method to add key-value pairs from one dictionary to another
I change the expectation to match
199 self.assertEqual( 200 a_dictionary, 201 { 202 'key': 'updated value', 203 'new_key': [0, 1, 2, 'n'], 204 'another_key': {0, 1, 2, 'n'}, 205 } 206 )
the test passes
I change the name of the test
194 def test_update_a_dictionary(self): 195 a_dictionary = {'key': 'value'} 196 self.assertIsNone(a_dictionary.update(new_key=[0, 1, 2, 'n'])) 197 self.assertIsNone(a_dictionary.update(key='updated value')) 198 self.assertIsNone(a_dictionary.update({'another_key': {0, 1, 2, 'n'}})) 199 self.assertEqual( 200 a_dictionary, 201 { 202 'key': 'updated value', 203 'new_key': [0, 1, 2, 'n'], 204 'another_key': {0, 1, 2, 'n'}, 205 } 206 ) 207 208 209'update',
the test is still green
I remove update from the TODO list
209'values'
test_values_of_a_dictionary¶
RED: make it fail¶
I add a test for the last method
204 'another_key': {0, 1, 2, 'n'},
205 }
206 )
207
208 def test_values(self):
209 a_dictionary = {'key': 'value'}
210 self.assertIsNone(a_dictionary.values())
211
212
213'values'
the terminal shows AssertionError
AssertionError: dict_values(['value']) is not None
this is like test_items_returns_iterable_of_key_value_pairs_of_a_dictionary and test_keys_of_a_dictionary
GREEN: make it pass¶
I add the expected value
208 def test_values(self): 209 a_dictionary = {'key': 'value'} 210 self.assertIsNone( 211 a_dictionary.values, 212 dict_values(['value']) 213 )
NameError: name 'dict_values' is not defined
I remove the things around the list in the
dict_valuesobject210 self.assertIsNone( 211 a_dictionary.values(), 212 ['value'] 213 )
the terminal shows AssertionError
I use the list constructor to see if
dict_valuesis iterable210 self.assertIsNone( 211 list(a_dictionary.values()), 212 ['value'] 213 )
the terminal shows AssertionError
AssertionError: ['value'] is not None : ['value']
I change assertIsNone to assertEqual
210 self.assertEqual( 211 list(a_dictionary.values()), 212 ['value'] 213 )
the test passes
REFACTOR: make it better¶
I change the dictionary to see what happens when it has more than one key-value pair
208 def test_values(self): 209 a_dictionary = { 210 'key1': 'value1', 211 'keyN': [0, 1, 2, 'n'], 212 } 213 self.assertEqual( 214 list(a_dictionary.values()), 215 ['value'] 216 )
the terminal shows AssertionError
AssertionError: Lists differ: ['value1', [0, 1, 2, 'n']] != ['value']
I change the values in the expectation
213 self.assertEqual( 214 list(a_dictionary.values()), 215 [ 216 'value1', 217 [0, 1, 2, 'n'], 218 ] 219 )
the test passes
I change the name of the test
208 def test_values_of_a_dictionary(self): 209 a_dictionary = { 210 'key1': 'value1', 211 'keyN': [0, 1, 2, 'n'], 212 } 213 self.assertEqual( 214 list(a_dictionary.values()), 215 [ 216 'value1', 217 [0, 1, 2, 'n'], 218 ] 219 ) 220 221 222'values'
I remove values from the TODO list
test_key_error¶
The KeyError is an important Exception to know when working with a dictionary. It happened earlier in test_pop_removes_given_key_from_a_dictionary_and_returns_its_value
RED: make it fail¶
I add a test for getting the value of a key that is in a dictionary
217 [0, 1, 2, 'n'],
218 ]
219 )
220
221 def test_key_error(self):
222 a_dictionary = {'key': 'value'}
223 self.assertEqual(a_dictionary['key'], '')
224
225
226# Exceptions Encountered
the terminal shows AssertionError
AssertionError: 'value' != ''
I get 'value' back. I can get the value for a key in a dictionary by giving the key in [], just like viewing items in a list by giving the index
GREEN: make it pass¶
I change the value in the expectation to match the terminal
223 self.assertEqual(a_dictionary['key'], 'value')
the test passes
REFACTOR: make it better¶
I add another assertion, this time for a key that is not in the dictionary
224 self.assertEqual(a_dictionary['key'], 'value') 225 self.assertEqual(a_dictionary['not_in_dictionary'])
KeyError: 'not_in_dictionary'
I change the assertEqual to assertRaises
223 self.assertEqual(a_dictionary['key'], 'value') 224 225 with self.assertRaises(KeyError): 226 a_dictionary['not_in_dictionary']
the test passes
I can use the get method if I do not want to get KeyError with a key that is not in a dictionary
225 with self.assertRaises(KeyError): 226 a_dictionary['not_in_dictionary'] 227 self.assertEqual( 228 a_dictionary.get('not_in_dictionary', 'default'), 229 '' 230 )
the terminal shows AssertionError
AssertionError: 'default' != ''
I change the expectation
227 self.assertEqual( 228 a_dictionary.get('not_in_dictionary', 'default'), 229 'default' 230 )
the test passes. This is a repetition of test_get_value_of_a_key_in_a_dictionary, here is another repetition
Earlier on in test_pop_removes_given_key_from_a_dictionary_and_returns_its_value the pop method raised KeyError when I gave it a key that was not in the dictionary, I add another assertion for it
227 self.assertEqual( 228 a_dictionary.get('not_in_dictionary', 'default'), 229 'default' 230 ) 231 a_dictionary.pop('not_in_dictionary')
KeyError: 'not_in_dictionary'
I add assertRaises
227 self.assertEqual( 228 a_dictionary.get('not_in_dictionary', 'default'), 229 'default' 230 ) 231 232 with self.assertRaises(KeyError): 233 a_dictionary.pop('not_in_dictionary')
the test passes
I can give a second argument if I do not want the pop method to raise KeyError when the key is not in the dictionary. I add an assertion
232 with self.assertRaises(KeyError): 233 a_dictionary.pop('not_in_dictionary') 234 self.assertEqual( 235 a_dictionary.pop('not_in_dictionary', 'default'), 236 '' 237 )
the terminal shows AssertionError
AssertionError: 'default' != ''
I change the expectation to match
234 self.assertEqual( 235 a_dictionary.pop('not_in_dictionary', 'default'), 236 'default' 237 )
the test passes
The popitem method also raises KeyError when called on an empty dictionary
234 self.assertEqual( 235 a_dictionary.pop('not_in_dictionary', 'default'), 236 'default' 237 ) 238 {}.popitem()
KeyError: 'popitem(): dictionary is empty'
I add assertRaises
221 def test_key_error(self): 222 a_dictionary = {'key': 'value'} 223 self.assertEqual(a_dictionary['key'], 'value') 224 225 with self.assertRaises(KeyError): 226 a_dictionary['not_in_dictionary'] 227 self.assertEqual( 228 a_dictionary.get('not_in_dictionary', 'default'), 229 'default' 230 ) 231 232 with self.assertRaises(KeyError): 233 a_dictionary.pop('not_in_dictionary') 234 self.assertEqual( 235 a_dictionary.pop('not_in_dictionary', 'default'), 236 'default' 237 ) 238 239 with self.assertRaises(KeyError): 240 {}.popitem() 241 242 243# Exceptions Encountered 244# AssertionError 245# TypeError 246# KeyError
the test passes
review¶
I ran tests for dictionaries
they contain key-value pairs
any object can be used as values
strings, booleans, integers, floats and tuples can be used as keys
they can be represented with
{}they can be made with the dict constructor
Would you like to test How to make a Person?
Click Here for the code from this chapter
you know
Would you like to put it all together in Classes?