lists
preview
Here are the tests I have by the end of the chapter
1import unittest
2
3
4class TestLists(unittest.TestCase):
5
6 def test_making_a_list(self):
7 self.assertEqual(list(), [])
8 self.assertEqual(list((0, 1, 2, 'n')), [0, 1, 2, 'n'])
9
10 def test_attributes_and_methods_of_lists(self):
11 self.maxDiff = None
12 self.assertEqual(
13 dir(list),
14 [
15 '__add__',
16 '__class__',
17 '__class_getitem__',
18 '__contains__',
19 '__delattr__',
20 '__delitem__',
21 '__dir__',
22 '__doc__',
23 '__eq__',
24 '__format__',
25 '__ge__',
26 '__getattribute__',
27 '__getitem__',
28 '__getstate__',
29 '__gt__',
30 '__hash__',
31 '__iadd__',
32 '__imul__',
33 '__init__',
34 '__init_subclass__',
35 '__iter__',
36 '__le__',
37 '__len__',
38 '__lt__',
39 '__mul__',
40 '__ne__',
41 '__new__',
42 '__reduce__',
43 '__reduce_ex__',
44 '__repr__',
45 '__reversed__',
46 '__rmul__',
47 '__setattr__',
48 '__setitem__',
49 '__sizeof__',
50 '__str__',
51 '__subclasshook__',
52 'append',
53 'clear',
54 'copy',
55 'count',
56 'extend',
57 'index',
58 'insert',
59 'pop',
60 'remove',
61 'reverse',
62 'sort',
63 ]
64 )
65
66 def test_append_adds_item_to_end_of_a_list(self):
67 a_list = [0, 1, 2, 'n']
68 self.assertIsNone(a_list.append('n+1'))
69 self.assertEqual(a_list, [0, 1, 2, 'n', 'n+1'])
70
71 def test_clear_empties_a_list(self):
72 a_list = [0, 1, 2, 'n']
73 self.assertIsNone(a_list.clear())
74 self.assertEqual(a_list, [])
75
76 def test_copy_a_list(self):
77 a_list = [0, 1, 2, 'n']
78 self.assertEqual(a_list.copy(), [0, 1, 2, 'n'])
79
80 def test_count_number_of_times_item_is_in_a_list(self):
81 a_list = [0, 1, 2, 1, 'n', 1]
82 self.assertEqual(a_list.count(0), 1)
83 self.assertEqual(a_list.count(1), 3)
84 self.assertEqual(a_list.count('not in list'), 0)
85
86 def test_extend_adds_items_from_an_iterable_to_end_of_a_list(self):
87 a_list = [0, 1, 2, 'n']
88 self.assertIsNone(a_list.extend((2, 1, 0)))
89 self.assertEqual(a_list, [0, 1, 2, 'n', 2, 1, 0])
90
91 def test_index_returns_first_position_of_item_in_a_list(self):
92 a_list = ['1st', '2nd', '3rd', '...last', '1st']
93 self.assertEqual(a_list.index('1st', 0), 0)
94 self.assertEqual(a_list.index('3rd', 0), 2)
95 self.assertEqual(a_list.index('2nd', 0), 1)
96 self.assertEqual(a_list.index('...last', 0), 3)
97 self.assertEqual(a_list.index('1st', 1), 4)
98
99 with self.assertRaises(ValueError):
100 a_list.index('not in list')
101
102 def test_insert_item_at_position_in_a_list(self):
103 a_list = [0, 1, 2, 'n']
104 self.assertIsNone(a_list.insert(0, -1))
105 self.assertEqual(a_list, [-1, 0, 1, 2, 'n'])
106 self.assertIsNone(a_list.insert(3, 1.5))
107 self.assertEqual(a_list, [-1, 0, 1, 1.5, 2, 'n'])
108
109 def test_pop_removes_and_returns_last_item_from_a_list(self):
110 a_list = [0, 1, 2, 'n']
111 self.assertEqual(a_list.pop(), 'n')
112 self.assertEqual(a_list, [0, 1, 2])
113 self.assertEqual(a_list.pop(), 2)
114 self.assertEqual(a_list, [0, 1])
115
116 def test_remove_first_time_item_is_in_a_list(self):
117 a_list = [0, 1, 0, 2, 0, 'n']
118 self.assertIsNone(a_list.remove(0))
119 self.assertEqual(a_list, [1, 0, 2, 0, 'n'])
120
121 with self.assertRaises(ValueError):
122 a_list.remove('not in list')
123
124 def test_reverse_a_list(self):
125 a_list = [0, 1, 2, 'n']
126 self.assertIsNone(a_list.reverse())
127 self.assertEqual(a_list, ['n', 2, 1, 0])
128
129 def test_sort_a_list(self):
130 with self.assertRaises(TypeError):
131 [0, 1, 2, 'n'].sort()
132
133 a_list = [0, 1, -1, 2, -2, 3, -3]
134 self.assertIsNone(a_list.sort())
135 self.assertEqual(a_list, [-3, -2, -1, 0, 1, 2, 3])
136
137 def test_getting_items_of_a_list(self):
138 a_list = ['1st', '2nd', '3rd', '...last']
139 self.assertEqual(a_list[0], '1st')
140 self.assertEqual(a_list[a_list.index('1st')], '1st')
141 self.assertEqual(a_list[-4], '1st')
142 self.assertEqual(a_list[2], '3rd')
143 self.assertEqual(a_list[-2], '3rd')
144 self.assertEqual(a_list[1], '2nd')
145 self.assertEqual(a_list[-3], '2nd')
146 self.assertEqual(a_list[3], '...last')
147 self.assertEqual(a_list[-1], '...last')
148
149 def test_setting_items_in_a_list(self):
150 a_list = ['1st', '2nd', '3rd', '...last']
151 a_list[-1] = '4th'
152 self.assertEqual(a_list, ['1st', '2nd', '3rd', '4th'])
153
154 def test_looking_at_parts_of_a_list_aka_slicing(self):
155 a_list = ['a', 'b', 'c', 'd']
156 self.assertEqual(a_list[0:2], ['a', 'b'])
157 self.assertEqual(a_list[:2], ['a', 'b'])
158 self.assertEqual(a_list[1:4], ['b', 'c', 'd'])
159 self.assertEqual(a_list[1:], ['b', 'c', 'd'])
160 self.assertEqual(a_list[0:3], ['a', 'b', 'c'])
161 self.assertEqual(a_list[1:3], ['b', 'c'])
162 self.assertEqual(a_list[:], a_list.copy())
163
164 def test_index_error(self):
165 a_list = ['a', 'b', 'c', 'd']
166
167 with self.assertRaises(IndexError):
168 a_list[4]
169 with self.assertRaises(IndexError):
170 a_list[-5]
171 with self.assertRaises(IndexError):
172 [].pop()
173 with self.assertRaises(IndexError):
174 [][-1]
175
176
177# Exceptions seen
178# AssertionError
179# TypeError
180# ValueError
181# IndexError
questions about lists
Here are questions you can answer after going through this chapter
start the project
I name this project
listsI open
makePythonTdd.shormakePythonTdd.ps1in the editorTip
Here is a quick way to open
makePythonTdd.shormakePythonTdd.ps1if you are using Visual Studio Codecode makePythonTdd.shon Windows without Windows Subsystem for Linux use
code makePythonTdd.ps1I change everywhere I have
type_errorto the name of this project1#!/bin/bash 2mkdir lists 3cd lists 4mkdir src 5touch src/lists.py 6mkdir tests 7touch tests/__init__.py 8 9echo "import unittest 10 11 12class TestLists(unittest.TestCase): 13 14 def test_failure(self): 15 self.assertFalse(True) 16 17 18# Exceptions seen 19# AssertionError 20" > tests/test_lists.pyAttention
on Windows without Windows Subsystem for Linux use
makePythonTdd.ps1NOTmakePythonTdd.sh1mkdir lists 2cd lists 3mkdir src 4New-Item src/lists.py 5mkdir tests 6New-Item tests/__init__.py 7 8"import unittest 9 10 11class TestLists(unittest.TestCase): 12 13 def test_failure(self): 14 self.assertFalse(True) 15 16# Exceptions seen 17# AssertionError 18" | Out-File tests/test_lists.pyI run the program in the terminal
./makePythonTdd.shAttention
on Windows without Windows Subsystem for Linux use
makePythonTdd.ps1NOTmakePythonTdd.sh./makePythonTdd.ps1the terminal shows AssertionError
================================= FAILURES ================================= ________________________________ TestLists.test_failure ________________________________ self = <tests.test_lists.TestLists testMethod=test_failure> def test_failure(self): > self.assertFalse(True) E AssertionError: True is not false tests/test_lists.py:7: AssertionError ================================ short test summary info ================================= FAILED tests/test_lists.py::TestLists::test_failure - AssertionError: True is not false ============================ 1 failed in X.YZs =============================I hold ctrl (Windows/Linux) or option or command (MacOS) on the keyboard and use the mouse to click on
tests/test_lists.py:7to open it in the editor-
7 self.assertFalse(False)the test passes
test_making_a_list
RED: make it fail
I change test_failure to test_making_a_list
4class TestLists(unittest.TestCase):
5
6 def test_making_a_list(self):
7 self.assertEqual(list(), None)
the terminal shows AssertionError
AssertionError: [] != None
GREEN: make it pass
I change the expectation
7 self.assertEqual(list(), [])
the test passes. I can make an empty list with list() or []
REFACTOR: make it better
I add another assertion, this time with input to
list(), I want to make a list that has things in it7 self.assertEqual(list(), []) 8 self.assertEqual(list(0), [])TypeError: 'int' object is not iterableI add TypeError to the list of Exceptions seen
11# Exceptions seen 12# AssertionError 13# TypeError
what is an iterable?
An iterable is an object that can return what it has, one at a time. In order words, I can loop over it. strings, tuples, lists, sets and dictionaries are iterable
I change the input to a tuple (anything in parentheses (
()), separated by a comma)7 self.assertEqual(list(), []) 8 self.assertEqual(list((0, 1, 2, 'n')), [])the terminal shows AssertionError
AssertionError: Lists differ: [0, 1, 2, 'n'] != []I change the expectation to match
8 self.assertEqual(list((0, 1, 2, 'n')), [0, 1, 2, 'n'])the test passes.
I can make a list with list(), or with square brackets([]) which uses less characters
test_attributes_and_methods_of_lists
how to see the attributes and methods of an object
I want to test the things I can do with lists. I can use the dir function to see the attributes and methods of objects, it is part of Python’s Built-in Functions
RED: make it fail
I add a failing test
8 self.assertEqual(list(0, 1, 2, 'n'), [0, 1, 2, 'n'])
9
10 def test_attributes_and_methods_of_lists(self):
11 self.assertEqual(
12 dir(list),
13 []
14 )
the terminal shows AssertionError
AssertionError: Lists differ: ['__add__', '__class__', '__class_getitem_[552 chars]ort'] != []
there is also a note on how to see the full difference between dir(list) and my empty list
Diff is 748 characters long. Set self.maxDiff to None to see it
maxDiff is an attribute of the unittest.TestCase class that sets the maximum number of characters to show when comparing 2 objects in the terminal, when it is set to None it shows the full difference
GREEN: make it pass
I add
self.maxDiffto the test then move the terminal to the right10 def test_attributes_and_methods_of_lists(self): 11 self.maxDiff = None 12 self.assertEqual( 13 dir(list), 14 [] 15 )the terminal shows a long list of items. I copy (ctrl/command+c) and paste (ctrl/command+v) them from the terminal then use find and replace to remove the extra characters
Eand-Note
results can be different because of the Python version
10 def test_attributes_and_methods_of_lists(self): 11 self.maxDiff = None 12 self.assertEqual( 13 dir(list), 14 [ 15 '__add__', 16 '__class__', 17 '__class_getitem__', 18 '__contains__', 19 '__delattr__', 20 '__delitem__', 21 '__dir__', 22 '__doc__', 23 '__eq__', 24 '__format__', 25 '__ge__', 26 '__getattribute__', 27 '__getitem__', 28 '__getstate__', 29 '__gt__', 30 '__hash__', 31 '__iadd__', 32 '__imul__', 33 '__init__', 34 '__init_subclass__', 35 '__iter__', 36 '__le__', 37 '__len__', 38 '__lt__', 39 '__mul__', 40 '__ne__', 41 '__new__', 42 '__reduce__', 43 '__reduce_ex__', 44 '__repr__', 45 '__reversed__', 46 '__rmul__', 47 '__setattr__', 48 '__setitem__', 49 '__sizeof__', 50 '__str__', 51 '__subclasshook__', 52 'append', 53 'clear', 54 'copy', 55 'count', 56 'extend', 57 'index', 58 'insert', 59 'pop', 60 'remove', 61 'reverse', 62 'sort' 63 ] 64 )the test passes and I move the terminal back to the bottom
I copy (ctrl/command+c) and paste (ctrl/command+v) the names that do NOT have double underscores (__) to use as a TODO list
67'append', 68'clear', 69'copy', 70'count', 71'extend', 72'index', 73'insert', 74'pop', 75'remove', 76'reverse', 77'sort' 78 79 80# Exceptions seen 81# AssertionError 82# TypeError
test_append_adds_item_to_end_of_a_list
RED: make it fail
I add a test for the append method
62 'sort'
63 ]
64 )
65
66 def test_append(self):
67 a_list = [0, 1, 2, 'n']
68 self.assertIsNone(a_list.append())
69
70
71 'append',
TypeError: list.append() takes exactly one argument (0 given)
GREEN: make it pass
I add 0 as input
68 self.assertIsNone(a_list.append(0))
the terminal shows green, the append method returns None when called
REFACTOR: make it better
I add another assertion to see what append did to the list
68 self.assertIsNone(a_list.append(0)) 69 self.assertEqual(a_list, [0, 1, 2, 'n'])the terminal shows AssertionError
AssertionError: Lists differ: [0, 1, 2, 'n', 0] != [0, 1, 2, 'n']the append method added a value at the end of the list
I change the expectation to match the values in the terminal
69 self.assertEqual(a_list, [0, 1, 2, 'n', 0])the test passes
I change the value given to append
68 self.assertIsNone(a_list.append('n+1'))the terminal shows AssertionError
AssertionError: Lists differ: [0, 1, 2, 'n', 'n+1'] != [0, 1, 2, 'n', 0]I change the expectation to match
69 self.assertEqual(a_list, [0, 1, 2, 'n', 'n+1'])the test passes
I change the name of the test
66 def test_append_adds_item_to_end_of_a_list(self): 67 a_list = [0, 1, 2, 'n'] 68 self.assertIsNone(a_list.append('n+1')) 69 self.assertEqual(a_list, [0, 1, 2, 'n', 'n+1'])I remove append from the TODO list
69 self.assertEqual(a_list, [0, 1, 2, 'n', 'n+1']) 70 71 72'clear', 73'copy', 74'count', 75'extend', 76'index', 77'insert', 78'pop', 79'remove', 80'reverse', 81'sort'
test_clear_empties_a_list
I add a test for the clear method
69 self.assertEqual(a_list, [0, 1, 2, 'n', 'n+1'])
70
71 def test_clear(self):
72 a_list = [0, 1, 2, 'n']
73 self.assertIsNone(a_list.clear())
74
75
76'clear',
the terminal shows green. The clear method returns None when called
RED: make it fail
I add an assertion to see what clear did to the list
73 self.assertIsNone(a_list.clear())
74 self.assertEqual(a_list, [0, 1, 2, 'n'])
the terminal shows AssertionError
AssertionError: Lists differ: [] != [0, 1, 2, 'n']
the list is now empty
GREEN: make it pass
I change the values to match
74 self.assertEqual(a_list, [])
the test passes
REFACTOR: make it better
I change the name of the test to make it “clearer”
71 def test_clear_empties_a_list(self): 72 a_list = [0, 1, 2, 'n'] 73 self.assertIsNone(a_list.clear()) 74 self.assertEqual(a_list, [])I remove clear from the TODO list
74 self.assertEqual(a_list, []) 75 76 77'copy', 78'count', 79'extend', 80'index', 81'insert', 82'pop', 83'remove', 84'reverse', 85'sort'
test_copy_a_list
RED: make it fail
I add another test
74 self.assertEqual(a_list, [])
75
76 def test_copy(self):
77 a_list = [0, 1, 2, 'n']
78 self.assertIsNone(a_list.copy())
79
80
81'copy',
the terminal shows AssertionError
AssertionError: [0, 1, 2, 'n'] is not None
GREEN: make it pass
I add the list to the assertion
77 a_list = [0, 1, 2, 'n'] 78 self.assertIsNone(a_list.copy(), [0, 1, 2, 'n'])the terminal shows AssertionError
AssertionError: [0, 1, 2, 'n'] is not None : [0, 1, 2, 'n']the values are the same, the problem is assertIsNone only takes 1 input and I gave it 2
I change assertIsNone to assertEqual
77 a_list = [0, 1, 2, 'n'] 78 self.assertEqual(a_list.copy(), [0, 1, 2, 'n'])the test passes
REFACTOR: make it better
I change the name of the test
76 def test_copy_a_list(self): 77 a_list = [0, 1, 2, 'n'] 78 self.assertEqual(a_list.copy(), [0, 1, 2, 'n'])I remove copy from the TODO list
78 self.assertIsNone(a_list.copy(), [0, 1, 2, 'n']) 79 80 81'count', 82'extend', 83'index', 84'insert', 85'pop', 86'remove', 87'reverse', 88'sort'
test_count_number_of_times_item_is_in_a_list
RED: make it fail
I add a test for the next method
78 self.assertEqual(a_list.copy(), [0, 1, 2, 'n'])
79
80 def test_count(self):
81 a_list = [0, 1, 2, 'n']
82 self.assertIsNone(a_list.count())
83
84
85'count',
TypeError: list.count() takes exactly one argument (0 given)
I add a value to the call
80 def test_count(self):
81 a_list = [0, 1, 2, 'n']
82 self.assertIsNone(a_list.count(0))
the terminal shows AssertionError
AssertionError: 1 is not None
GREEN: make it pass
I add the value
82 self.assertIsNone(a_list.count(0), 1)
the terminal shows AssertionError
AssertionError: 1 is not None : 1
I change assertIsNone to assertEqual
82 self.assertEqual(a_list.count(0), 1)
the test passes
REFACTOR: make it better
0is in this list 1 time, I add1to the list 2 more times then add an assertion for it80 def test_count(self): 81 a_list = [0, 1, 2, 1, 'n', 1] 82 self.assertEqual(a_list.count(0), 1) 83 self.assertEqual(a_list.count(1), 1)the terminal shows AssertionError
AssertionError: 3 != 1I change the value to match
83 self.assertEqual(a_list.count(1), 3)the test passes
I want to see what happens when I try to count something that is not in the list
83 self.assertEqual(a_list.count(1), 3) 84 self.assertEqual(a_list.count('not in list'), 3)the terminal shows AssertionError
AssertionError: 0 != 3The count method returns
0when the item is not in the listI change the value to match
84 self.assertEqual(a_list.count('not in list'), 0)the test passes
I change the name of the test
80 def test_count_number_of_times_item_is_in_a_list(self): 81 a_list = [0, 1, 2, 1, 'n', 1] 82 self.assertEqual(a_list.count(0), 1) 83 self.assertEqual(a_list.count(1), 3) 84 self.assertEqual(a_list.count('not in list'), 0)I remove count from the TODO list
84 self.assertEqual(a_list.count('not in list'), 0) 85 86 87'extend', 88'index', 89'insert', 90'pop', 91'remove', 92'reverse', 93'sort'
test_extend_adds_items_from_an_iterable_to_end_of_a_list
RED: make it fail
time for another test
84 self.assertEqual(a_list.count('not in list'), 0)
85
86 def test_extend(self):
87 a_list = [0, 1, 2, 'n']
88 self.assertIsNone(a_list.extend())
89
90
91'extend',
TypeError: list.extend() takes exactly one argument (0 given)
GREEN: make it pass
I pass a value to the call
88 self.assertIsNone(a_list.extend(0))
TypeError: 'int' object is not iterable
I change the value to an iterable
88 self.assertIsNone(a_list.extend((0, 1)))
the test passes. The extend method returns None when called
REFACTOR: make it better
I add another assertion to see what it did to the list
88 self.assertIsNone(a_list.extend((0, 1))) 89 self.assertEqual(a_list, [0, 1, 2, 'n'])the terminal shows AssertionError
AssertionError: Lists differ: [0, 1, 2, 'n', 0, 1] != [0, 1, 2, 'n']I change the expectation to match
89 self.assertEqual(a_list, [0, 1, 2, 'n', 0, 1])the test passes
I change the values given to the extend method
86 def test_extend(self): 87 a_list = [0, 1, 2, 'n'] 88 self.assertIsNone(a_list.extend((2, 1, 0))) 89 self.assertEqual(a_list, [0, 1, 2, 'n', 0, 1])the terminal shows AssertionError
AssertionError: Lists differ: [0, 1, 2, 'n', 2, 1, 0] != [0, 1, 2, 'n', 0, 1]I change the values to match
89 self.assertEqual(a_list, [0, 1, 2, 'n', 2, 1, 0])the test is green again, it looks like extend calls append for each item in the iterable
I change the name of the test
86 def test_extend_adds_items_from_an_iterable_to_end_of_a_list(self): 87 a_list = [0, 1, 2, 'n'] 88 self.assertIsNone(a_list.extend((2, 1, 0))) 89 self.assertEqual(a_list, [0, 1, 2, 'n', 2, 1, 0])I remove extend from the TODO list
89 self.assertEqual(a_list, [0, 1, 2, 'n', 2, 1, 0]) 90 91 92'index', 93'insert', 94'pop', 95'remove', 96'reverse', 97'sort'
test_index_returns_first_position_of_item_in_a_list
RED: make it fail
I add a test for the index method
89 self.assertEqual(a_list, [0, 1, 2, 'n', 2, 1, 0])
90
91 def test_index(self):
92 a_list = [0, 1, 2, 'n']
93 self.assertIsNone(a_list.index())
94
95
96'index',
TypeError: index expected at least 1 argument, got 0
GREEN: make it pass
I add a value to the call
91 def test_index(self):
92 a_list = [0, 1, 2, 'n']
93 self.assertIsNone(a_list.index(0))
the terminal shows AssertionError
AssertionError: 0 is not None
I add the expectation
93 self.assertIsNone(a_list.index(0), 0)
the terminal shows AssertionError
AssertionError: 0 is not None : 0
I change assertIsNone to assertEqual
91 def test_index(self):
92 a_list = [0, 1, 2, 'n']
93 self.assertEqual(a_list.index(0), 0)
the test passes
REFACTOR: make it better
maybe the method returned the same value I gave, I change the list to find out
91 def test_index(self): 92 a_list = ['1st', '2nd', '3rd', '...last'] 93 self.assertEqual(a_list.index(0), 0)the terminal shows ValueError
ValueError: 0 is not in listthe index method raises ValueError when the item is not in the list
I add ValueError to the list of Exceptions seen
104# Exceptions seen 105# AssertionError 106# TypeError 107# ValueErrorI remove the things around the call and change the value to be clearer
91 def test_index(self): 92 a_list = ['1st', '2nd', '3rd', '...last'] 93 a_list.index('not in list')the terminal shows ValueError
ValueError: 'not in list' is not in listI add assertRaises to handle the Exception
91 def test_index(self): 92 a_list = ['1st', '2nd', '3rd', '...last'] 93 94 with self.assertRaises(ValueError): 95 a_list.index('not in list')the test is green again
I add a new assertion
91 def test_index(self): 92 a_list = ['1st', '2nd', '3rd', '...last'] 93 self.assertEqual(a_list.index('1st'), '1st') 94 95 with self.assertRaises(ValueError): 96 a_list.index('not in list')the terminal shows AssertionError
AssertionError: 0 != '1st'I change the expectation
93 self.assertEqual(a_list.index('1st'), 0)the test passes. The index method does not just return the value I give it
I add another assertion
91 def test_index(self): 92 a_list = ['1st', '2nd', '3rd', '...last'] 93 self.assertEqual(a_list.index('1st'), 0) 94 self.assertEqual(a_list.index('3rd'), 0)the terminal shows AssertionError
AssertionError: 2 != 0I change the value in the test
94 self.assertEqual(a_list.index('3rd'), 2)the test passes
I add another assertion
94 self.assertEqual(a_list.index('3rd'), 2) 95 self.assertEqual(a_list.index('2nd'), 2) 96 97 with self.assertRaises(ValueError): 98 a_list.index('not in list')the terminal shows AssertionError
AssertionError: 1 != 2I change the value to match
95 self.assertEqual(a_list.index('2nd'), 1)the test is green again
I add another assertion
95 self.assertEqual(a_list.index('2nd'), 1) 96 self.assertEqual(a_list.index('...last'), 1)the terminal shows AssertionError
AssertionError: 3 != 1I change the value to match the terminal
96 self.assertEqual(a_list.index('...last'), 3)the test passes. The index method returns numbers for the position of the item in the list. Python uses zero-based indexing which means the first item has an index of
0and the last item has an index of the length of the list minus1I want to know what happens when I have the same item in the list more than once, so I add something in the list again
91 def test_index(self): 92 a_list = ['1st', '2nd', '3rd', '...last', '1st']the terminal still shows green
I add an assertion
96 self.assertEqual(a_list.index('...last'), 3) 97 self.assertEqual(a_list.index('1st'), 4)the terminal shows AssertionError
AssertionError: 0 != 4when I first called the index method, the terminal showed TypeError
TypeError: index expected at least 1 argument, got 0which means I should be able to send more than one argument
I add a second argument
97 self.assertEqual(a_list.index('1st', 0), 4)the terminal still shows AssertionError
AssertionError: 0 != 4I change the argument
97self.assertEqual(a_list.index('1st', 1), 4)the test passes, the second input is the position I want the method to start from
I try the same thing with the other assertions
91 def test_index(self): 92 a_list = ['1st', '2nd', '3rd', '...last', '1st'] 93 self.assertEqual(a_list.index('1st', 0), 0) 94 self.assertEqual(a_list.index('3rd', 0), 2) 95 self.assertEqual(a_list.index('2nd', 0), 1) 96 self.assertEqual(a_list.index('...last', 0), 3) 97 self.assertEqual(a_list.index('1st', 1), 4) 98 99 with self.assertRaises(ValueError): 100 a_list.index('not in list')the test is still green
I change the name of the test
91 def test_index_returns_first_position_of_item_in_a_list(self): 92 a_list = ['1st', '2nd', '3rd', '...last', '1st']I also remove index from the TODO list
99 with self.assertRaises(ValueError): 100 a_list.index('not in list') 101 102 103'insert', 104'pop', 105'remove', 106'reverse', 107'sort'
test_insert_item_at_position_in_a_list
RED: make it fail
I add a test for the next method
99 with self.assertRaises(ValueError):
100 a_list.index('not in list')
101
102 def test_insert(self):
103 a_list = [0, 1, 2, 'n']
104 self.assertIsNone(a_list.insert())
105
106
107'insert',
TypeError: insert expected 2 arguments, got 0
GREEN: make it pass
I add two values to the call
102 def test_insert(self):
103 a_list = [0, 1, 2, 'n']
104 self.assertIsNone(a_list.insert(0, 1))
the test passes. What did the insert method do to the list?
REFACTOR: make it better
I add an assertion to find out
104 self.assertIsNone(a_list.insert(0, 1)) 105 self.assertEqual(a_list, [0, 1, 2, 'n'])the terminal shows AssertionError
AssertionError: Lists differ: [1, 0, 1, 2, 'n'] != [0, 1, 2, 'n']there is an extra value at the beginning of the list
I add the new value to the expectation
105 self.assertEqual(a_list, [1, 0, 1, 2, 'n'])the test passes.
The insert method
I change the second input in the call
102 def test_insert(self): 103 a_list = [0, 1, 2, 'n'] 104 self.assertIsNone(a_list.insert(0, -1)) 105 self.assertEqual(a_list, [0, 1, 2, 'n'])the terminal shows AssertionError
AssertionError: Lists differ: [-1, 0, 1, 2, 'n'] != [0, 1, 2, 'n']I change the expectation to match
105 self.assertEqual(a_list, [-1, 0, 1, 2, 'n'])the test is green again
I add another assertion to see what happens when I insert an item in the middle of the list
105 self.assertEqual(a_list, [-1, 0, 1, 2, 'n']) 106 self.assertIsNone(a_list.insert(3, 1.5))the terminal shows green
I add an assertion to see what it did to the list
106 self.assertIsNone(a_list.insert(3, 1.5)) 107 self.assertEqual(a_list, [-1, 0, 1, 2, 'n'])the terminal shows AssertionError
AssertionError: Lists differ: [-1, 0, 1, 1.5, 2, 'n'] != [-1, 0, 1, 2, 'n']I add the value to the expectation
107 self.assertEqual(a_list, [-1, 0, 1, 1.5, 2, 'n'])the test passes, it moved everything in the list from the index I gave and after, to the right
I change the name of the test
102 def test_insert_item_at_position_in_a_list(self): 103 a_list = [0, 1, 2, 'n'] 104 self.assertIsNone(a_list.insert(0, -1)) 105 self.assertEqual(a_list, [-1, 0, 1, 2, 'n']) 106 self.assertIsNone(a_list.insert(3, 1.5)) 107 self.assertEqual(a_list, [-1, 0, 1, 1.5, 2, 'n']) 108 109 110'insert',I remove insert from the TODO list
107 self.assertEqual(a_list, [-1, 0, 1, 1.5, 2, 'n']) 108 109 110'pop', 111'remove', 112'reverse', 113'sort'
test_pop_removes_and_returns_last_item_from_a_list
RED: make it fail
I add a new test
107 self.assertEqual(a_list, [-1, 0, 1, 1.5, 2, 'n'])
108
109 def test_pop(self):
110 a_list = [0, 1, 2, 'n']
111 self.assertIsNone(a_list.pop())
112
113
114'pop',
the terminal shows AssertionError
AssertionError: 'n' is not None
The pop method returns the last item in the list
GREEN: make it pass
I add the expectation
111 self.assertIsNone(a_list.pop(), 'n')
the terminal shows AssertionError
AssertionError: 'n' is not None : n
I change assertIsNone to assertEqual
109 def test_pop(self):
110 a_list = [0, 1, 2, 'n']
111 self.assertEqual(a_list.pop(), 'n')
the test passes
REFACTOR: make it better
I add another assertion to see what happened to the list
111 self.assertEqual(a_list.pop(), 'n') 112 self.assertEqual(a_list, [0, 1, 2, 'n'])the terminal shows AssertionError
AssertionError: Lists differ: [0, 1, 2] != [0, 1, 2, 'n']I change the values in the test to match
112 self.assertEqual(a_list, [0, 1, 2])the test passes
I add another assertion with the pop method
112 self.assertEqual(a_list, [0, 1, 2]) 113 self.assertEqual(a_list.pop(), 'n')the terminal shows AssertionError
AssertionError: 2 != 'n'I change the value in the expectation
113 self.assertEqual(a_list.pop(), 2)the test passes
I add another assertion to see what changed in the list
113 self.assertEqual(a_list.pop(), 2) 114 self.assertEqual(a_list, [0, 1, 2])the terminal shows AssertionError
AssertionError: Lists differ: [0, 1] != [0, 1, 2]I change the values in the test to match
114 self.assertEqual(a_list, [0, 1])the test passes
I change the name of the test
def test_pop_removes_and_returns_last_item_from_a_list(self): a_list = [0, 1, 2, 'n'] self.assertEqual(a_list.pop(), 'n') self.assertEqual(a_list, [0, 1, 2]) self.assertEqual(a_list.pop(), 2) self.assertEqual(a_list, [0, 1]) 'pop',I take out pop from the TODO list
114 self.assertEqual(a_list, [0, 1]) 115 116 117'remove', 118'reverse', 119'sort'
test_remove_first_time_item_is_in_a_list
RED: make it fail
time for the next method
114 self.assertEqual(a_list, [0, 1])
115
116 def test_remove(self):
117 a_list = [0, 1, 2, 'n']
118 self.assertIsNone(a_list.remove())
119
120
121'remove',
TypeError: list.remove() takes exactly one argument (0 given)
GREEN: make it pass
I add a value to the call
118 self.assertIsNone(a_list.remove(0))
the terminal shows green. The remove method returns None
REFACTOR: make it better
I add an assertion to see what it did to the list
118 self.assertIsNone(a_list.remove(0)) 119 self.assertEqual(a_list, [0, 1, 2, 'n'])the terminal shows AssertionError
AssertionError: Lists differ: [1, 2, 'n'] != [0, 1, 2, 'n']I change the expectation
119 self.assertEqual(a_list, [1, 2, 'n'])the test passes
I change the values in the list to see what happens when an item is in there more than one time
116 def test_remove(self): 117 a_list = [0, 1, 0, 2, 0, 'n'] 118 self.assertIsNone(a_list.remove(0)) 119 self.assertEqual(a_list, [1, 2, 'n'])the terminal shows AssertionError
AssertionError: Lists differ: [1, 0, 2, 0, 'n'] != [1, 2, 'n']I change the values to match
119 self.assertEqual(a_list, [1, 0, 2, 0, 'n'])the test passes. The remove method only removes the first time something shows up in the list
I want to see what happens when I try to remove something that is not in the list
119 self.assertEqual(a_list, [1, 0, 2, 0, 'n']) 120 self.assertIsNone(a_list.remove('not in list'))the terminal shows ValueError
ValueError: list.remove(x): x not in listI remove the things around the call then add assertRaises
119 self.assertEqual(a_list, [1, 0, 2, 0, 'n']) 120 121 with self.assertRaises(ValueError): 122 a_list.remove('not in list') 123 124 125'remove',the test passes
I change the name of the test
116 def test_remove_first_time_item_is_in_a_list(self): 117 a_list = [0, 1, 0, 2, 0, 'n'] 118 self.assertIsNone(a_list.remove(0)) 119 self.assertEqual(a_list, [1, 0, 2, 0, 'n']) 120 121 with self.assertRaises(ValueError): 122 a_list.remove('not in list') 123 124 125'remove'I take out remove from the TODO list
121 with self.assertRaises(ValueError): 122 a_list.remove('not in list') 123 124 125'reverse', 126'sort'
test_reverse_a_list
RED: make it fail
I add the next test
121 with self.assertRaises(ValueError): 122 a_list.remove('not in list') 123 124 def test_reverse(self): 125 a_list = [0, 1, 2, 'n'] 126 self.assertIsNone(a_list.reverse()) 127 128 129'reverse',the terminal shows green. The reverse method returns None.
I add an assertion to see what it did to the list
126 self.assertIsNone(a_list.reverse()) 127 self.assertEqual(a_list, [0, 1, 2, 'n'])the terminal shows AssertionError
AssertionError: Lists differ: ['n', 2, 1, 0] != [0, 1, 2, 'n']it reversed the order of the items in the list
GREEN: make it pass
I change the expectation
127 self.assertEqual(a_list, ['n', 2, 1, 0])
the test passes
REFACTOR: make it better
I change the name of the test
124 def test_reverse_a_list(self): 125 a_list = [0, 1, 2, 'n'] 126 self.assertIsNone(a_list.reverse()) 127 self.assertEqual(a_list, ['n', 2, 1, 0]) 128 129 130'reverse',I remove the name from the TODO list
127 self.assertEqual(a_list, ['n', 2, 1, 0]) 128 129 130'sort' 131 132 133# Exceptions seen
test_sort_a_list
RED: make it fail
I add a test for the last method in the TODO list
127 self.assertEqual(a_list, ['n', 2, 1, 0])
128
129 def test_sort(self):
130 a_list = [0, 1, 2, 'n']
131 self.assertIsNone(a_list.sort())
132
133
134'sort'
TypeError: '<' not supported between instances of 'str' and 'int'
I have to change 'n' to a number or change the other numbers to strings
GREEN: make it pass
I remove the things around the call then add assertRaises
129 def test_sort(self):
130 a_list = [0, 1, 2, 'n']
131 with self.assertRaises(TypeError):
132 a_list.sort()
the test passes
REFACTOR: make it better
I can use the list directly in the call
129 def test_sort(self): 130 a_list = [0, 1, 2, 'n'] 131 with self.assertRaises(TypeError): 132 [0, 1, 2, 'n'].sort()the test is still green
I remove the variable because it is no longer used
129 def test_sort(self): 130 with self.assertRaises(TypeError): 131 [0, 1, 2, 'n'].sort()still green
I add a new list where all the items are numbers and another assertion
129 def test_sort(self): 130 with self.assertRaises(TypeError): 131 [0, 1, 2, 'n'].sort() 132 133 a_list = [0, 1, 2, 3] 134 self.assertIsNone(a_list.sort())the terminal still shows green, sort returns None when called
I add another assertion to see what it did to the list
133 a_list = [0, 1, 2, 3] 134 self.assertIsNone(a_list.sort()) 135 self.assertEqual(a_list, [])the terminal shows AssertionError
AssertionError: Lists differ: [0, 1, 2, 3] != []the list stayed the same
I change the expectation to match
135 self.assertEqual(a_list, [0, 1, 2, 3])the test passes. The name of the method is sort and I gave it a list that is sorted
I change the list to see what happens when it is NOT sorted
133 a_list = [0, 1, -1, 2, -2, 3, -3] 134 self.assertIsNone(a_list.sort()) 135 self.assertEqual(a_list, [0, 1, 2, 3])the terminal shows AssertionError
AssertionError: Lists differ: [-3, -2, -1, 0, 1, 2, 3] != [0, 1, 2, 3]the sort method changed the order of the list from smallest to biggest number
I change the values to match
135 self.assertEqual(a_list, [-3, -2, -1, 0, 1, 2, 3])the test passes
I change the name of the test
129 def test_sort_a_list(self): 130 with self.assertRaises(TypeError): 131 [0, 1, 2, 'n'].sort() 132 133 a_list = [0, 1, -1, 2, -2, 3, -3] 134 self.assertIsNone(a_list.sort()) 135 self.assertEqual(a_list, [-3, -2, -1, 0, 1, 2, 3]) 136 137 138'sort'I remove sort from the TODO list
135 self.assertEqual(a_list, [-3, -2, -1, 0, 1, 2, 3]) 136 137 138# Exceptions seen 139# AssertionError 140# TypeError 141# ValueError
test_getting_items_of_a_list
When I want an item that is in a list, I can give its index in square brackets([]) to get it
RED: make it fail
I add a failing test
135 self.assertEqual(a_list, [-3, -2, -1, 0, 1, 2, 3])
136
137 def test_getting_items_of_a_list(self):
138 a_list = ['1st', '2nd', '3rd', '...last']
139 self.assertEqual(a_list[0], '')
140
141
142# Exceptions seen
the terminal shows AssertionError
AssertionError: '1st' != ''
the first item has an index of 0
GREEN: make it pass
I change the value in the test
139 self.assertEqual(a_list[0], '1st')
the test passes
REFACTOR: make it better
this is the opposite of the index method which takes in the item and returns its position, in this case I provide the index (position) and it returns the item, which means I can write this
139 self.assertEqual(a_list[0], '1st') 140 self.assertEqual(a_list[a_list.index('1st')], '')the terminal shows AssertionError
AssertionError: '1st' != ''I change the value to match
140 self.assertEqual(a_list[a_list.index('1st')], '1st')the test passes because
a_list.index('1st')returns0a_list[0]returns1st
I can also use negative numbers. The last item has an index of
-1and the first item has an index of negative the length of the list140 self.assertEqual(a_list[a_list.index('1st')], '1st') 141 self.assertEqual(a_list[-4], '')the terminal shows AssertionError
AssertionError: '1st' != ''I change the value to match
141 self.assertEqual(a_list[-4], '1st')the test passes
I add another assertion
141 self.assertEqual(a_list[-4], '1st') 142 self.assertEqual(a_list[2], '')the terminal shows AssertionError
AssertionError: '3rd' != ''I change the expectation to match
142 self.assertEqual(a_list[2], '3rd')the terminal shows green again
I add another assertion
142 self.assertEqual(a_list[2], '3rd') 143 self.assertEqual(a_list[-2], '')the terminal shows AssertionError
AssertionError: '3rd' != ''I change the expectation
143 self.assertEqual(a_list[-2], '3rd')the test passes
I add another line
143 self.assertEqual(a_list[-2], '3rd') 144 self.assertEqual(a_list[1], '')the terminal shows AssertionError
AssertionError: '2nd' != ''I change the expectation
144 self.assertEqual(a_list[1], '2nd')I add another
144 self.assertEqual(a_list[1], '2nd') 145 self.assertEqual(a_list[-3], '')the terminal shows AssertionError
AssertionError: '2nd' != ''I change the value
145 self.assertEqual(a_list[-3], '2nd')the test passes
I add another assertion
145 self.assertEqual(a_list[-3], '2nd') 146 self.assertEqual(a_list[3], '')the terminal shows AssertionError
AssertionError: '...last' != ''I change the value
146 self.assertEqual(a_list[3], '...last')the test passes
I add another assertion
146 self.assertEqual(a_list[3], '...last') 147 self.assertEqual(a_list[-1], '')the terminal shows AssertionError
AssertionError: '...last' != ''I make the values match
137 def test_getting_items_of_a_list(self): 138 a_list = ['1st', '2nd', '3rd', '...last'] 139 self.assertEqual(a_list[0], '1st') 140 self.assertEqual(a_list[a_list.index('1st')], '1st') 141 self.assertEqual(a_list[-4], '1st') 142 self.assertEqual(a_list[2], '3rd') 143 self.assertEqual(a_list[-2], '3rd') 144 self.assertEqual(a_list[1], '2nd') 145 self.assertEqual(a_list[-3], '2nd') 146 self.assertEqual(a_list[3], '...last') 147 self.assertEqual(a_list[-1], '...last') 148 149 150# Exceptions seenthe test passes
test_setting_items_in_a_list
I can also use the index of an item in a list to change the item
RED: make it fail
I add an assertion
147 self.assertEqual(a_list[-1], '...last')
148
149 def test_setting_items_in_a_list(self):
150 a_list = ['1st', '2nd', '3rd', '...last']
151 a_list[-1] = '4th'
152 self.assertEqual(a_list, ['1st', '2nd', '3rd', '...last'])
153
154
155# Exceptions seen
the terminal shows AssertionError
AssertionError: Lists differ: ['1st', '2nd', '3rd', '4th'] != ['1st', '2nd', '3rd', '...last']
I can use the index of an item to change its value in a list, the way I point a name to a value when I make a variable
GREEN: make it pass
I change the expectation to match the values in the terminal
152 self.assertEqual(a_list, ['1st', '2nd', '3rd', '4th'])
the test passes. I know how to change the value of an item in a list
test_looking_at_parts_of_a_list_aka_slicing
I can use indices to look at parts of a list, this is called slicing
RED: make it fail
I add another test
152 self.assertEqual(a_list, ['1st', '2nd', '3rd', '4th'])
153
154 def test_looking_at_parts_of_a_list(self):
155 a_list = ['a', 'b', 'c', 'd']
156 self.assertEqual(a_list[0:2], [])
157
158
159 # Exceptions seen
the terminal shows AssertionError
AssertionError: Lists differ: ['a', 'b'] != []
GREEN: make it pass
I change the values to match
156 self.assertEqual(a_list[0:2], ['a', 'b'])
the test passes.
I give two values in square brackets([]), separated by a :, the first value is the index of the item I want to start from, and the second value is the index of the item I want to stop at plus 1
REFACTOR: make it better
I can skip the first number when the starting index is
0155 self.assertEqual(a_list[0:2], ['a', 'b']) 156 self.assertEqual(a_list[:2], [])the terminal shows AssertionError
AssertionError: Lists differ: ['a', 'b'] != []I change the values to match
157 self.assertEqual(a_list[:2], ['a', 'b'])the terminal shows green again.
[0:2]and[:2]are the sameI add another assertion
157 self.assertEqual(a_list[:2], ['a', 'b']) 158 self.assertEqual(a_list[1:4], [])the terminal shows AssertionError
AssertionError: Lists differ: ['b', 'c', 'd'] != []I add the missing values
158 self.assertEqual(a_list[1:4], ['b', 'c', 'd'])the test passes
I can skip the second number when it is bigger than or the same as the number of things in the list
158 self.assertEqual(a_list[1:4], ['b', 'c', 'd']) 159 self.assertEqual(a_list[1:], [])the terminal shows AssertionError
AssertionError: Lists differ: ['b', 'c', 'd'] != []I add the missing values
159 self.assertEqual(a_list[1:], ['b', 'c', 'd'])the test passes.
[1:4]and[1:]are the same because this list has 4 thingsI add another line
159 self.assertEqual(a_list[1:], ['b', 'c', 'd']) 160 self.assertEqual(a_list[0:3], [])the terminal shows AssertionError
AssertionError: Lists differ: ['a', 'b', 'c'] != []I change the expectation
160 self.assertEqual(a_list[0:3], ['a', 'b', 'c'])the test passes
I add another
160 self.assertEqual(a_list[0:3], ['a', 'b', 'c']) 161 self.assertEqual(a_list[1:3], [])the terminal shows AssertionError
AssertionError: Lists differ: ['b', 'c'] != []I change the expectation
161 self.assertEqual(a_list[1:3], ['b', 'c'])the test is green again
I can also skip both numbers
161 self.assertEqual(a_list[1:3], ['b', 'c']) 162 self.assertEqual(a_list[:], [])the terminal shows AssertionError
AssertionError: Lists differ: ['a', 'b', 'c', 'd'] != []I get the entire list back or a copy
162 self.assertEqual(a_list[:], a_list.copy())the test is green again
This is also called slicing, I change the name of the test
154 def test_looking_at_parts_of_a_list_aka_slicing(self): 155 a_list = ['a', 'b', 'c', 'd'] 156 self.assertEqual(a_list[0:2], ['a', 'b']) 157 self.assertEqual(a_list[:2], ['a', 'b']) 158 self.assertEqual(a_list[1:4], ['b', 'c', 'd']) 159 self.assertEqual(a_list[1:], ['b', 'c', 'd']) 160 self.assertEqual(a_list[0:3], ['a', 'b', 'c']) 161 self.assertEqual(a_list[1:3], ['b', 'c']) 162 self.assertEqual(a_list[:], a_list.copy()) 163 164 165# Exceptions seen
test_index_error
IndexError is raised when I try to get an item from a list but use a number that points to something that is NOT in it. When I see this Exception I know the underlying data structure is a list
RED: make it fail
I add a failing test
162 self.assertEqual(a_list[:], a_list.copy())
163
164 def test_index_error(self):
165 a_list = ['a', 'b', 'c', 'd']
166 a_list[4]
167
168
169# Exceptions seen
the terminal shows IndexError
IndexError: list index out of range
when I use an index that is greater than or the same as the number of things in the list, I am pointing to something that is NOT in the list
GREEN: make it pass
I add assertRaises
164def test_index_error(self):
165 a_list = ['a', 'b', 'c', 'd']
166
167 with self.assertRaises(IndexError):
168 a_list[4]
the test passes
REFACTOR: make it better
I add IndexError to the list of Exceptions seen
171# Exceptions seen 172# AssertionError 173# TypeError 174# ValueError 175# IndexErrorI get IndexError when I use a number that is smaller than the number of things in the list as a negative number
167 with self.assertRaises(IndexError): 168 a_list[4] 169 a_list[-5]the terminal shows IndexError
IndexError: list index out of rangeI add the assertRaises method
167 with self.assertRaises(IndexError): 168 a_list[4] 169 with self.assertRaises(IndexError): 170 a_list[-5] 171 172 173# Exceptions seenthe test passes
IndexError is also raised when I call the pop method with an empty list
167 with self.assertRaises(IndexError): 168 a_list[4] 169 with self.assertRaises(IndexError): 170 a_list[-5] 171 [].pop()the terminal shows IndexError
IndexError: pop from empty listI add assertRaises
169 with self.assertRaises(IndexError): 170 a_list[-5] 171 with self.assertRaises(IndexError): 172 [].pop()the terminal shows green
I cannot remove the last item from a list that has no items, this is the same as trying to get an item from a list that has no items
171 with self.assertRaises(IndexError): 172 [].pop() 173 [][-1]the terminal shows IndexError
IndexError: list index out of rangeI add assertRaises
171 with self.assertRaises(IndexError): 172 [].pop() 173 with self.assertRaises(IndexError): 174 [][-1]the test passes. Any index given to an empty list raises IndexError
close the project
I close
test_lists.pyin the editorI click in the terminal and exit the tests with ctrl+c on the keyboard, the terminal shows
.../pumping_pythonI am back in the
pumping_pythondirectory
Note
on Windows without Windows Subsystem for Linux
the terminal shows
(.venv) ...\pumping_python\listsI deactivate the virtual environment
deactivatethe terminal goes back to the command line,
(.venv)is no longer on the left side...\pumping_python\listsI change directory to the parent of
listscd ..the terminal shows
...\pumping_pythonI am back in the
pumping_pythondirectory
review
I ran tests to show that I can make a list with list() or square brackets ([]), then I ran the following tests for the methods of lists from append to sort
I also added tests for
How many questions can you answer after going through this chapter?
code from the chapter
what is next?
you know
rate pumping python
If this has been a 7 star experience for you, please leave a 5 star review. It helps other people get into the book too