Elevator
I want to make an Elevator that goes up and down when I push a button, if the inputs are
are the doors clear?
was the number for a floor pushed?
I get this truth table for the Elevator
doors |
floor button |
output |
|---|---|---|
clear |
pushed |
MOVE |
clear |
NOT pushed |
NOT MOVE |
NOT clear |
pushed |
NOT MOVE |
NOT clear |
NOT pushed |
NOT MOVE |
preview
These are the tests I have at the end of the chapter
1import src.elevator
2import unittest
3
4
5NOT_MOVE = 'NOT MOVE'
6
7
8class TestElevator(unittest.TestCase):
9
10 def test_doors_clear_number_pushed_w_emergency(self):
11 self.assertEqual(
12 src.elevator.elevator(
13 doors_clear=True,
14 number_pushed=True,
15 above_weight_limit=True,
16 emergency=True,
17 ),
18 NOT_MOVE
19 )
20
21 self.assertEqual(
22 src.elevator.elevator(
23 doors_clear=True,
24 number_pushed=True,
25 above_weight_limit=True,
26 emergency=False,
27 ),
28 NOT_MOVE
29 )
30
31 self.assertEqual(
32 src.elevator.elevator(
33 doors_clear=True,
34 number_pushed=True,
35 above_weight_limit=False,
36 emergency=True,
37 ),
38 NOT_MOVE
39 )
40
41 self.assertEqual(
42 src.elevator.elevator(
43 doors_clear=True,
44 number_pushed=True,
45 above_weight_limit=False,
46 emergency=False,
47 ),
48 'MOVE'
49 )
50
51 def test_doors_clear_number_not_pushed_w_emergency(self):
52 self.assertEqual(
53 src.elevator.elevator(
54 doors_clear=True,
55 number_pushed=False,
56 above_weight_limit=True,
57 emergency=True,
58 ),
59 NOT_MOVE
60 )
61
62 self.assertEqual(
63 src.elevator.elevator(
64 doors_clear=True,
65 number_pushed=False,
66 above_weight_limit=True,
67 emergency=False,
68 ),
69 NOT_MOVE
70 )
71
72 self.assertEqual(
73 src.elevator.elevator(
74 doors_clear=True,
75 number_pushed=False,
76 above_weight_limit=False,
77 emergency=True,
78 ),
79 NOT_MOVE
80 )
81
82 self.assertEqual(
83 src.elevator.elevator(
84 doors_clear=True,
85 number_pushed=False,
86 above_weight_limit=False,
87 emergency=False,
88 ),
89 NOT_MOVE
90 )
91
92 def test_doors_not_clear_number_pushed_w_emergency(self):
93 self.assertEqual(
94 src.elevator.elevator(
95 doors_clear=False,
96 number_pushed=True,
97 above_weight_limit=True,
98 emergency=True,
99 ),
100 NOT_MOVE
101 )
102
103 self.assertEqual(
104 src.elevator.elevator(
105 doors_clear=False,
106 number_pushed=True,
107 above_weight_limit=True,
108 emergency=False,
109 ),
110 NOT_MOVE
111 )
112
113 self.assertEqual(
114 src.elevator.elevator(
115 doors_clear=False,
116 number_pushed=True,
117 above_weight_limit=False,
118 emergency=True,
119 ),
120 NOT_MOVE
121 )
122
123 self.assertEqual(
124 src.elevator.elevator(
125 doors_clear=False,
126 number_pushed=True,
127 above_weight_limit=False,
128 emergency=False,
129 ),
130 NOT_MOVE
131 )
132
133 def test_doors_not_clear_number_not_pushed_w_emergency(self):
134 self.assertEqual(
135 src.elevator.elevator(
136 doors_clear=False,
137 number_pushed=False,
138 above_weight_limit=True,
139 emergency=True,
140 ),
141 NOT_MOVE
142 )
143
144 self.assertEqual(
145 src.elevator.elevator(
146 doors_clear=False,
147 number_pushed=False,
148 above_weight_limit=True,
149 emergency=False,
150 ),
151 NOT_MOVE
152 )
153
154 self.assertEqual(
155 src.elevator.elevator(
156 doors_clear=False,
157 number_pushed=False,
158 above_weight_limit=False,
159 emergency=True,
160 ),
161 NOT_MOVE
162 )
163
164 self.assertEqual(
165 src.elevator.elevator(
166 doors_clear=False,
167 above_weight_limit=False,
168 number_pushed=False,
169 emergency=False,
170 ),
171 NOT_MOVE
172 )
173
174
175# Exceptions seen
176# AssertionError
177# NameError
178# AttributeError
179# TypeError
requirements
number the project
I name this project
elevatorI open a terminal
I use uv to make a directory for the project and initialize it
uv init elevatorthe terminal shows
Initialized project `elevator` at `.../pumping_python/elevator`then goes back to the command line.
I make a directory for the source code
mkdir srcthe terminal goes back to the command line.
I use the mv program to change the name of
main.pytoelevator.pyand move it to thesrcfoldermv main.py src/elevator.pyMove-Item main.py src/elevator.pythe terminal goes back to the command line.
I make a directory for the tests
mkdir teststhe terminal goes back to the command line.
I make the
testsdirectory a Python packageDanger
use 2 underscores (__) before and after
initfor__init__.pynot_init_.pytouch tests/__init__.pyNew-Item tests/__init__.pythe terminal goes back to the command line.
I make a Python file for the tests in the
testsdirectorytouch tests/test_elevator.pyNew-Item tests/test_elevator.pythe terminal goes back to the command line.
I open
test_elevator.pyI add the first failing test to
test_elevator.py1import unittest 2 3 4class TestElevator(unittest.TestCase): 5 6 def test_failure(self): 7 self.assertFalse(True)I go back to the terminal to make a requirements file for the Python packages I need
echo "pytest" > requirements.txtthe terminal goes back to the command line.
I add pytest-watcher to the requirements file
echo "pytest-watcher" >> requirements.txtthe terminal goes back to the command line.
I use uv to install pytest-watcher with the requirements file
uv add --requirement requirements.txtthe terminal shows that it installed pytest-watcher and its dependencies.
I use tree to look at the structure of the project
treethe terminal shows
. ├── README.md ├── pyproject.toml ├── requirements.txt ├── src │ └── elevator.py ├── tests │ ├── __init__.py │ └── test_elevator.py └── uv.lockif you do not see
uv.lockin your tree, make sure you ranuv add --requirement requirements.txt, then run the tests nextI use pytest-watcher to run the tests automatically
uv run pytest-watcher . --nowthe terminal is my friend, and shows AssertionError
======================== FAILURES ======================== _________________ TestElevator.test_failure ___________________ self = <tests.test_elevator.TestElevator testMethod=test_failure> def test_failure(self): > self.assertFalse(True) E AssertionError: True is not false tests/test_elevator.py:7: AssertionError ================ short test summary info ================= FAILED tests/test_elevator.py::TestElevator::test_failure - AssertionError: True is not false =================== 1 failed in X.YZs ====================if the terminal does not show the same error, then check
if your
tests/__init__.pyhas two underscores (__) before and afterinitfor__init__.pynot_init_.pyif you ran
echo "pytest-watcher" >> requirements.txt, to addpytest-watcherto the requirements file
fix those errors and try to run
uv run pytest-watcher . --nowagainI add AssertionError to the list of Exceptions seen in
test_elevator.py4class TestElevator(unittest.TestCase): 5 6 def test_failure(self): 7 self.assertFalse(True) 8 9 10# Exceptions seen 11# AssertionErrorthen I change True to False in the assertion
7 self.assertFalse(False)the test passes.
test_doors_clear_number_pushed
RED: make it fail
I change test_failure to test_doors_clear_number_pushed, then add an assertion for when the doors are clear and the button for a floor is pushed
doors |
floor button |
output |
|---|---|---|
clear |
pushed |
MOVE |
4class TestElevator(unittest.TestCase):
5
6 def test_doors_clear_number_pushed(self):
7 my_expectation = 'MOVE'
8 reality = src.elevator.elevator(
9 doors_clear=True,
10 number_pushed=True,
11 )
12 self.assertEqual(reality, my_expectation)
13
14
15# Exceptions seen
16# AssertionError
the terminal is my friend, and shows NameError
NameError: name 'src' is not defined
because I do not have a definition for src in this file
GREEN: make it pass
I add NameError to the list of Exceptions seen
15# Exceptions seen 16# AssertionError 17# NameErrorI add an import statement at the top of the file
1import src.elevator 2import unittest 3 4 5class TestElevator(unittest.TestCase):the terminal is my friend, and shows AttributeError
AttributeError: module 'src.elevator' has no attribute 'elevator'because
elevator.pyin thesrcfolder does not have anything namedelevatorin itIf you get ModuleNotFoundError
ModuleNotFoundError: No module named 'src'check if you have
__init__.pyin thetestsfolder with underscores (__) before and afterinitfor__init__.pynot_init_.py, then add ModuleNotFoundError to the list of Exceptions seenI add AttributeError to the list of Exceptions seen
16# Exceptions seen 17# AssertionError 18# NameError 19# AttributeErrorI open
elevator.pyfrom thesrcfolderI add a function named
elevatortoelevator.py1def elevator(): 2 return Nonethe terminal is my friend, and shows TypeError
TypeError: elevator() got an unexpected keyword argument 'doors_clear'because the test called the
elevatorfunction with two keyword arguments (doors_clearandnumber_pushed) and this definition only takes calls with 0 argumentsI add TypeError to the list of Exceptions seen in
test_elevator.py16# Exceptions seen 17# AssertionError 18# NameError 19# AttributeError 20# TypeErrorI add the keyword argument to the function in
elevator.py1def elevator(doors_clear): 2 return Nonethe terminal is my friend, and shows TypeError
TypeError: elevator() got an unexpected keyword argument 'number_pushed'because the test called the
elevatorfunction with two keyword arguments (doors_clearandnumber_pushed) and this definition only takes calls with 1 inputI add
number_pushedto the function signature1def elevator(doors_clear, number_pushed): 2 return Nonethe terminal is my friend, and shows AssertionError
AssertionError: None != 'MOVE'the
elevatorfunction returned None and the assertion expects ‘MOVE’I change the return statement to give the test what it wants
1def elevator(doors_clear, number_pushed): 2 return 'MOVE'the test passes. The
elevatorfunction always returns MOVE, it does not care about the inputs. Is this Tautology?
test_doors_clear_number_not_pushed
RED: make it fail
I add a test named test_doors_clear_number_not_pushed with an assertion for when the doors are clear and the button for a floor is NOT pushed, in test_elevator.py
doors |
floor button |
output |
|---|---|---|
clear |
NOT pushed |
NOT MOVE |
7 def test_doors_clear_number_pushed(self):
8 my_expectation = 'MOVE'
9 reality = src.elevator.elevator(
10 doors_clear=True,
11 number_pushed=True,
12 )
13 self.assertEqual(reality, my_expectation)
14
15 def test_doors_clear_number_not_pushed(self):
16 my_expectation = 'NOT MOVE'
17 reality = src.elevator.elevator(
18 doors_clear=True,
19 number_pushed=False,
20 )
21 self.assertEqual(reality, my_expectation)
22
23
24# Exceptions seen
the terminal is my friend, and shows AssertionError
AssertionError: 'MOVE' != 'NOT MOVE'
because the elevator function returns ‘MOVE’ and the assertion expects ‘NOT MOVE’
GREEN: make it pass
I add an if statement to the elevator function in elevator.py
1def elevator(doors_clear, number_pushed):
2 if number_pushed == False:
3 return 'NOT MOVE'
4
5 return 'MOVE'
the test passes.
REFACTOR: make it better
I use the bool built-in function
1def elevator(doors_clear, number_pushed): 2 # if number_pushed == False: 3 if bool(number_pushed) == False: 4 return 'NOT MOVE' 5 6 return 'MOVE'the test is still green.
I use Logical Negation (NOT) to write it in terms of True
1def elevator(doors_clear, number_pushed): 2 # if number_pushed == False: 3 # if bool(number_pushed) == False: 4 if bool(not number_pushed) == True: 5 return 'NOT MOVE' 6 7 return 'MOVE'still green.
I remove
== True1def elevator(doors_clear, number_pushed): 2 # if number_pushed == False: 3 # if bool(number_pushed) == False: 4 # if bool(not number_pushed) == True: 5 if bool(not number_pushed): 6 return 'NOT MOVE' 7 8 return 'MOVE'green.
I remove bool
1def elevator(doors_clear, number_pushed): 2 # if number_pushed == False: 3 # if bool(number_pushed) == False: 4 # if bool(not number_pushed) == True: 5 # if bool(not number_pushed): 6 if not number_pushed: 7 return 'NOT MOVE' 8 9 return 'MOVE'still green, because
if bool(something) == Falseis the same asif bool(not something) == Trueis the same asif bool(not something)is the same asif not something.I remove the commented lines
1def elevator(doors_clear, number_pushed): 2 if not number_pushed: 3 return 'NOT MOVE' 4 5 return 'MOVE'this is what happens when the
elevatorfunction is calledit returns ‘NOT MOVE’ if the button for the floor is NOT pushed
it returns ‘MOVE’ if the above condition is NOT met
test_doors_not_clear_number_pushed
RED: make it fail
I add a test with an assertion for when the doors are NOT clear and the button for a floor is pushed, in test_elevator.py
doors |
floor button |
output |
|---|---|---|
NOT clear |
pushed |
NOT MOVE |
15 def test_doors_clear_number_not_pushed(self):
16 my_expectation = 'NOT MOVE'
17 reality = src.elevator.elevator(
18 doors_clear=True,
19 number_pushed=False,
20 )
21 self.assertEqual(reality, my_expectation)
22
23 def test_doors_not_clear_number_pushed(self):
24 my_expectation = 'NOT MOVE'
25 reality = src.elevator.elevator(
26 doors_clear=False,
27 number_pushed=True,
28 )
29 self.assertEqual(reality, my_expectation)
30
31
32# Exceptions seen
the terminal is my friend, and shows AssertionError
AssertionError: 'MOVE' != 'NOT MOVE'
because the elevator function returns ‘MOVE’ and the assertion expects ‘NOT MOVE’
GREEN: make it pass
I add an if statement to elevator.py
1def elevator(doors_clear, number_pushed):
2 if doors_clear == False:
3 return 'NOT MOVE'
4
5 if not number_pushed:
6 return 'NOT MOVE'
7
8 return 'MOVE'
the test passes.
REFACTOR: make it better
I use the bool built-in function
1def elevator(doors_clear, number_pushed): 2 # if doors_clear == False: 3 if bool(doors_clear) == False: 4 return 'NOT MOVE' 5 6 if not number_pushed: 7 return 'NOT MOVE' 8 9 return 'MOVE'the test is still green.
I use Logical Negation (NOT) to write the new if statement in terms of True
1def elevator(doors_clear, number_pushed): 2# if doors_clear == False: 3# if bool(doors_clear) == False: 4if bool(not doors_clear) == True: 5 return 'NOT MOVE' 6 7if not number_pushed: 8 return 'NOT MOVE' 9 10return 'MOVE'still green.
I remove
== True1def elevator(doors_clear, number_pushed): 2 # if doors_clear == False: 3 # if bool(doors_clear) == False: 4 # if bool(not doors_clear) == True: 5 if bool(not doors_clear): 6 return 'NOT MOVE' 7 8 if not number_pushed: 9 return 'NOT MOVE' 10 11 return 'MOVE'green.
I remove bool
1def elevator(doors_clear, number_pushed): 2 # if doors_clear == False: 3 # if bool(doors_clear) == False: 4 # if bool(not doors_clear) == True: 5 # if bool(not doors_clear): 6 if not doors_clear: 7 return 'NOT MOVE' 8 9 if not number_pushed: 10 return 'NOT MOVE' 11 12 return 'MOVE'because
if bool(something) == Falseis the same asif bool(not something) == Trueis the same asif bool(not something)is the same asif not something.I add a variable
1def elevator(doors_clear, number_pushed): 2 not_move = 'NOT MOVE' 3 # if doors_clear == False: 4 # if bool(doors_clear) == False: 5 # if bool(not doors_clear) == True:I use the variable to remove repetition of ‘NOT MOVE’ from the function
1def elevator(doors_clear, number_pushed): 2 not_move = 'NOT MOVE' 3 # if doors_clear == False: 4 # if bool(doors_clear) == False: 5 # if bool(not doors_clear) == True: 6 # if bool(not doors_clear): 7 if not doors_clear: 8 # return 'NOT MOVE' 9 return not_move 10 11 if not number_pushed: 12 # return 'NOT MOVE' 13 return not_move 14 15 return 'MOVE'still green.
I remove the commented lines
1def elevator(doors_clear, number_pushed): 2 not_move = 'NOT MOVE' 3 4 if not doors_clear: 5 return not_move 6 7 if not number_pushed: 8 return not_move 9 10 return 'MOVE'this is what happens when the
elevatorfunction is calledit returns ‘NOT MOVE’ if the button for the floor is NOT pushed
it returns ‘NOT MOVE’ if the doors are NOT clear
it returns ‘MOVE’ if the above conditions are NOT met
test_doors_not_clear_number_not_pushed
I add a test with an assertion for when the doors are NOT clear and the button for the floor is NOT pushed to test_elevator.py
doors |
floor button |
output |
|---|---|---|
NOT clear |
NOT pushed |
NOT MOVE |
23 def test_doors_not_clear_number_pushed(self):
24 my_expectation = 'NOT MOVE'
25 reality = src.elevator.elevator(
26 doors_clear=False,
27 number_pushed=True,
28 )
29 self.assertEqual(reality, my_expectation)
30
31 def test_doors_not_clear_number_not_pushed(self):
32 my_expectation = 'NOT MOVE'
33 reality = src.elevator.elevator(
34 doors_clear=False,
35 number_pushed=False,
36 )
37 self.assertEqual(reality, my_expectation)
38
39
40# Exceptions seen
the test is still green.
REFACTOR: make it better
‘NOT MOVE’ happens in 3 of the 4 tests, I make a global variable to remove repetition of the variables from the tests
1import src.elevator 2import unittest 3 4 5NOT_MOVE = 'NOT MOVE' 6 7 8class TestElevator(unittest.TestCase):this way all the tests can use the same global variable and I do not have to make one for each test
I use the new global variable to remove ‘NOT_MOVE’ from test_doors_clear_number_not_pushed
18 def test_doors_clear_number_not_pushed(self): 19 # my_expectation = 'NOT MOVE' 20 reality = src.elevator.elevator( 21 doors_clear=True, 22 number_pushed=False, 23 ) 24 # self.assertEqual(reality, my_expectation) 25 self.assertEqual(reality, NOT_MOVE) 26 27 def test_doors_not_clear_number_pushed(self):still green.
I remove the commented lines
18 def test_doors_clear_number_not_pushed(self): 19 reality = src.elevator.elevator( 20 doors_clear=True, 21 number_pushed=False, 22 ) 23 self.assertEqual(reality, NOT_MOVE) 24 25 def test_doors_not_clear_number_pushed(self):I use the new global variable to remove ‘NOT_MOVE’ from test_doors_not_clear_number_pushed
25 def test_doors_not_clear_number_pushed(self): 26 # my_expectation = 'NOT MOVE' 27 reality = src.elevator.elevator( 28 doors_clear=False, 29 number_pushed=True, 30 ) 31 # self.assertEqual(reality, my_expectation) 32 self.assertEqual(reality, NOT_MOVE) 33 34 def test_doors_not_clear_number_not_pushed(self):green.
I remove the commented lines
25 def test_doors_not_clear_number_pushed(self): 26 reality = src.elevator.elevator( 27 doors_clear=False, 28 number_pushed=True, 29 ) 30 self.assertEqual(reality, NOT_MOVE) 31 32 def test_doors_not_clear_number_not_pushed(self):I use the new global variable to remove ‘NOT_MOVE’ from test_doors_not_clear_number_not_pushed
32 def test_doors_not_clear_number_not_pushed(self): 33 # my_expectation = 'NOT MOVE' 34 reality = src.elevator.elevator( 35 doors_clear=False, 36 number_pushed=False, 37 ) 38 # self.assertEqual(reality, my_expectation) 39 self.assertEqual(reality, NOT_MOVE) 40 41 42# Exceptions seenstill green.
I remove the commented lines
32 def test_doors_not_clear_number_not_pushed(self): 33 reality = src.elevator.elevator( 34 doors_clear=False, 35 number_pushed=False, 36 ) 37 self.assertEqual(reality, NOT_MOVE) 38 39 40# Exceptions seen
test_weight_w_doors_clear_number_pushed
So far, the truth table for the elevator is
doors |
floor button |
output |
|---|---|---|
clear |
pushed |
MOVE |
clear |
NOT pushed |
NOT MOVE |
NOT clear |
pushed |
NOT MOVE |
NOT clear |
NOT pushed |
NOT MOVE |
I want the elevator to move only when it is NOT above a weight limit, the inputs for the elevator will then be
are the doors clear?
was the number for a floor pushed?
is the elevator above the weight limit?
The truth table for when the doors are clear and the button for a floor is pushed, is:
doors |
floor number |
weight limit |
output |
|---|---|---|---|
clear |
pushed |
above |
NOT MOVE |
clear |
pushed |
NOT above |
MOVE |
RED: make it fail
I add an assertion with a value for above_weight_limit to test_doors_clear_number_pushed, for when the doors are clear, the button for a floor is pushed and the elevator is above the weight limit
doors |
floor number |
weight limit |
output |
|---|---|---|---|
clear |
pushed |
above |
NOT MOVE |
10 def test_doors_clear_number_pushed(self):
11 reality = src.elevator.elevator(
12 doors_clear=True,
13 number_pushed=True,
14 above_weight_limit=True,
15 )
16 self.assertEqual(reality, NOT_MOVE)
17
18 my_expectation = 'MOVE'
19 reality = src.elevator.elevator(
20 doors_clear=True,
21 number_pushed=True,
22 )
23 self.assertEqual(reality, my_expectation)
24
25 def test_doors_clear_number_not_pushed(self):
the terminal is my friend, and shows TypeError
TypeError: elevator() got an unexpected keyword argument 'above_weight_limit'
because the test called the elevator function with 3 keyword arguments (doors_clear, number_pushed and above_weight_limit) and the function only takes calls with 2 arguments (doors_clear and number_pushed)
GREEN: make it pass
I add
above_weight_limitto the function signature inelevator.py1def elevator( 2 doors_clear, number_pushed, 3 above_weight_limit, 4 ): 5 not_move = 'NOT MOVE' 6 7 if not doors_clear: 8 return not_move 9 10 if not number_pushed: 11 return not_move 12 13 return 'MOVE'the terminal is my friend, and shows TypeError
FAILED ...test_doors_clear_number_not_pushed - TypeError: elevator() missing 1 required positional argument: 'above_weight_limit' FAILED t...test_doors_not_clear_number_not_pushed - TypeError: elevator() missing 1 required positional argument: 'above_weight_limit' FAILED ...test_doors_not_clear_number_pushed - TypeError: elevator() missing 1 required positional argument: 'above_weight_limit'because the tests call the
elevatorfunction with 2 arguments (doors_clearandnumber_pushed) and I just changed the function signature to make it take 3 required arguments (doors_clear,number_pushedandabove_weight_limit). I have to makeabove_weight_limita choice.the terminal also shows AssertionError
AssertionError: 'MOVE' != 'NOT MOVE'because the
elevatorfunction returned ‘MOVE’ when it was called with theabove_weight_limitparameter and the assertion expects ‘NOT MOVE’
I add a default value to make
above_weight_limita choice1def elevator( 2 doors_clear, number_pushed, 3 above_weight_limit=False, 4 ):the TypeError goes away because
src.elevator.elevator( doors_clear=True, number_pushed=False, )is now the same as
src.elevator.elevator( doors_clear=True, number_pushed=False, above_weight_limit=False, )A function uses the default value for a parameter when it is called without the parameter.
the terminal still shows AssertionError
AssertionError: 'MOVE' != 'NOT MOVE'because the
elevatorfunction returned ‘MOVE’ and the assertion expects ‘NOT MOVE’I add an if statement to the function in
elevator.py1def elevator( 2 doors_clear, number_pushed, 3 above_weight_limit=False, 4 ): 5 not_move = 'NOT MOVE' 6 7 if above_weight_limit == True: 8 return not_move 9 10 if not doors_clear: 11 return not_move 12 13 if not number_pushed: 14 return not_move 15 16 return 'MOVE'the test passes.
REFACTOR: make it better
I use the bool built-in function
7 # if above_weight_limit == True: 8 if bool(above_weight_limit) == True: 9 return not_movethe test is still green.
I remove
== True7 # if above_weight_limit == True: 8 # if bool(above_weight_limit) == True: 9 if bool(above_weight_limit): 10 return not_movestill green.
I remove bool
7 # if above_weight_limit == True: 8 # if bool(above_weight_limit) == True: 9 # if bool(above_weight_limit): 10 if above_weight_limit: 11 return not_movegreen, because
if bool(something) == Trueis the same asif bool(something)is the same asif something.I remove the commented lines
1def elevator( 2 doors_clear, number_pushed, 3 above_weight_limit=False, 4 ): 5 not_move = 'NOT MOVE' 6 7 if above_weight_limit: 8 return not_move 9 10 if not doors_clear: 11 return not_move 12 13 if not number_pushed: 14 return not_move 15 16 return 'MOVE'this is what happens when the
elevatorfunction is calledit returns ‘NOT MOVE’ if the elevator is above the weight limit
it returns ‘NOT MOVE’ if the button for the floor is NOT pushed
it returns ‘NOT MOVE’ if the doors are NOT clear
it returns ‘MOVE’ if the above conditions are NOT met
I do not need to add a value for the
above_weight_limitparameter to the next assertion for when the doors are clear, the button for the floor is pushed and the elevator is NOT above the weight limitdoors
floor number
weight limit
output
clear
pushed
NOT above
MOVE
because
src.elevator.elevator( doors_clear=True, number_pushed=True, )is the same as
src.elevator.elevator( doors_clear=True, number_pushed=True, above_weight_limit=False, )A function uses the default value for a parameter when it is called without the parameter.
I change the name of the test from test_doors_clear_number_pushed to test_weight_w_doors_clear_number_pushed
5class TestElevator(unittest.TestCase): 6 7 def test_weight_w_doors_clear_number_pushed(self): 8 reality = src.elevator.elevator( 9 doors_clear=True, 10 number_pushed=True, 11 above_weight_limit=True, 12 ) 13 self.assertEqual(reality, NOT_MOVE)
test_weight_w_doors_clear_number_not_pushed
The truth table for when the doors are clear and the button for a floor is NOT pushed, is:
doors |
floor number |
weight limit |
output |
|---|---|---|---|
clear |
NOT pushed |
above |
NOT MOVE |
clear |
NOT pushed |
NOT above |
NOT MOVE |
I add a value for the
above_weight_limitparameter to the assertion for when the doors are clear, the button for a floor is NOT pushed and the elevator is above the weight limit, in test_doors_clear_number_not_pusheddoors
floor number
weight limit
output
clear
NOT pushed
above
NOT MOVE
25 def test_doors_clear_number_not_pushed(self): 26 reality = src.elevator.elevator( 27 doors_clear=True, 28 number_pushed=False, 29 above_weight_limit=True, 30 ) 31 self.assertEqual(reality, NOT_MOVE) 32 33 def test_doors_not_clear_number_pushed(self):the test is still green.
I add an assertion for when the doors are clear, the button for the floor is NOT pushed and the elevator is NOT above the weight limit
doors
floor number
weight limit
output
clear
NOT pushed
NOT above
NOT MOVE
25 def test_doors_clear_number_not_pushed(self): 26 reality = src.elevator.elevator( 27 doors_clear=True, 28 number_pushed=False, 29 above_weight_limit=True, 30 ) 31 self.assertEqual(reality, NOT_MOVE) 32 33 reality = src.elevator.elevator( 34 doors_clear=True, 35 number_pushed=False, 36 ) 37 self.assertEqual(reality, NOT_MOVE) 38 39 def test_doors_not_clear_number_pushed(self):still green. I do not need to add a value for the
above_weight_limitparameter becausesrc.elevator.elevator( doors_clear=True, number_pushed=False, )is the same as
src.elevator.elevator( doors_clear=True, number_pushed=False, above_weight_limit=False, )A function uses the default value for a parameter when it is called without the parameter.
I change the name of the test from test_doors_clear_number_not_pushed to test_weight_w_doors_clear_number_not_pushed
18 my_expectation = 'MOVE' 19 reality = src.elevator.elevator( 20 doors_clear=True, 21 number_pushed=True, 22 ) 23 self.assertEqual(reality, my_expectation) 24 25 def test_weight_w_doors_clear_number_not_pushed(self): 26 reality = src.elevator.elevator( 27 doors_clear=True, 28 number_pushed=False, 29 above_weight_limit=True, 30 ) 31 self.assertEqual(reality, NOT_MOVE)
test_weight_w_doors_not_clear_number_pushed
The truth table for when the doors are NOT clear and the button for a floor is pushed, is:
doors |
floor number |
weight limit |
output |
|---|---|---|---|
NOT clear |
pushed |
above |
NOT MOVE |
NOT clear |
pushed |
NOT above |
NOT MOVE |
I add a value for the
above_weight_limitparameter to the assertion in test_doors_not_clear_number_pushed for the case where the doors are NOT clear, the button for a floor is pushed and the elevator is above the weight limitdoors
floor number
weight limit
output
NOT clear
pushed
above
NOT MOVE
39 def test_doors_not_clear_number_pushed(self): 40 reality = src.elevator.elevator( 41 doors_clear=False, 42 number_pushed=True, 43 above_weight_limit=True, 44 ) 45 self.assertEqual(reality, NOT_MOVE) 46 47 def test_doors_not_clear_number_not_pushed(self):the test is still green.
I add an assertion to test_doors_not_clear_number_pushed, for when the doors are NOT clear, the button for the floor is pushed and the elevator is NOT above the weight limit
doors
floor number
weight limit
output
NOT clear
pushed
NOT above
NOT MOVE
39 def test_doors_not_clear_number_pushed(self): 40 reality = src.elevator.elevator( 41 doors_clear=False, 42 number_pushed=True, 43 above_weight_limit=True, 44 ) 45 self.assertEqual(reality, NOT_MOVE) 46 47 reality = src.elevator.elevator( 48 doors_clear=False, 49 number_pushed=True, 50 ) 51 self.assertEqual(reality, NOT_MOVE) 52 53 def test_doors_not_clear_number_not_pushed(self):still green. I do not need to add a value for the
above_weight_limitparameter becausesrc.elevator.elevator( doors_clear=False, number_pushed=True, )is the same as
src.elevator.elevator( doors_clear=False, number_pushed=True, above_weight_limit=False, )A function uses the default value for a parameter when it is called without the parameter.
I change the name of the test from test_doors_not_clear_number_pushed to test_weight_w_doors_not_clear_number_pushed
33 reality = src.elevator.elevator( 34 doors_clear=True, 35 number_pushed=False, 36 ) 37 self.assertEqual(reality, NOT_MOVE) 38 39 def test_weight_w_doors_not_clear_number_pushed(self): 40 reality = src.elevator.elevator( 41 doors_clear=False, 42 number_pushed=True, 43 above_weight_limit=True, 44 ) 45 self.assertEqual(reality, NOT_MOVE)
test_weight_w_doors_not_clear_number_not_pushed
The truth table for when the doors are NOT clear and the button for a floor is NOT pushed, is:
doors |
floor number |
weight limit |
output |
|---|---|---|---|
NOT clear |
NOT pushed |
above |
NOT MOVE |
NOT clear |
NOT pushed |
NOT above |
NOT MOVE |
I add a value for the
above_weight_limitparameter to the assertion for when the doors are NOT clear, the button for a floor is NOT pushed and the elevator is above the weight , in test_doors_not_clear_number_not_pusheddoors
floor number
weight limit
output
NOT clear
NOT pushed
above
NOT MOVE
53 def test_doors_not_clear_number_not_pushed(self): 54 reality = src.elevator.elevator( 55 doors_clear=False, 56 number_pushed=False, 57 above_weight_limit=True, 58 ) 59 self.assertEqual(reality, NOT_MOVE) 60 61 62# Exceptions seengreen.
I add an assertion for when the doors are NOT clear, the button for the floor is NOT pushed and the elevator is NOT above the weight limit
doors
floor number
weight limit
output
NOT clear
NOT pushed
NOT above
NOT MOVE
53 def test_doors_not_clear_number_not_pushed(self): 54 reality = src.elevator.elevator( 55 doors_clear=False, 56 number_pushed=False, 57 above_weight_limit=True, 58 ) 59 self.assertEqual(reality, NOT_MOVE) 60 61 reality = src.elevator.elevator( 62 doors_clear=False, 63 number_pushed=False, 64 ) 65 self.assertEqual(reality, NOT_MOVE) 66 67 68# Exceptions seenstill green. I do not need to add a value for the
above_weight_limitparameter becausesrc.elevator.elevator( doors_clear=False, number_pushed=False, )is the same as
src.elevator.elevator( doors_clear=False, number_pushed=False, above_weight_limit=False, )A function uses the default value for a parameter when it is called without the parameter.
I change the name of the test from test_doors_not_clear_number_pushed to test_weight_w_doors_not_clear_number_pushed
47 reality = src.elevator.elevator( 48 doors_clear=False, 49 number_pushed=True, 50 ) 51 self.assertEqual(reality, NOT_MOVE) 52 53 def test_weight_w_doors_not_clear_number_not_pushed(self): 54 reality = src.elevator.elevator( 55 doors_clear=False, 56 number_pushed=False, 57 above_weight_limit=True, 58 ) 59 self.assertEqual(reality, NOT_MOVE)I call the
elevatorfunction directly in test_weight_w_doors_not_clear_number_not_pushed, I do not need therealityvariable because it is only used once in each assertion56 def test_weight_w_doors_not_clear_number_not_pushed(self): 57 reality = src.elevator.elevator( 58 doors_clear=False, 59 number_pushed=False, 60 above_weight_limit=True, 61 ) 62 # self.assertEqual(reality, NOT_MOVE) 63 self.assertEqual( 64 src.elevator.elevator( 65 doors_clear=False, 66 number_pushed=False, 67 above_weight_limit=True, 68 ), 69 NOT_MOVE 70 ) 71 72 reality = src.elevator.elevator( 73 doors_clear=False, 74 number_pushed=False, 75 ) 76 # self.assertEqual(reality, NOT_MOVE) 77 self.assertEqual( 78 src.elevator.elevator( 79 doors_clear=False, 80 number_pushed=False, 81 ), 82 NOT_MOVE 83 ) 84 85 86# Exceptions seenthe test is still green.
I remove the commented lines and
realityvariables56 def test_weight_w_doors_not_clear_number_not_pushed(self): 57 self.assertEqual( 58 src.elevator.elevator( 59 doors_clear=False, 60 above_weight_limit=False, 61 number_pushed=True, 62 ), 63 NOT_MOVE 64 ) 65 66 self.assertEqual( 67 src.elevator.elevator( 68 doors_clear=False, 69 above_weight_limit=False, 70 number_pushed=False, 71 ), 72 NOT_MOVE 73 ) 74 75 76# Exceptions seenI do the same thing in test_weight_w_doors_not_clear_number_pushed
39 def test_weight_w_doors_not_clear_number_pushed(self): 40 reality = src.elevator.elevator( 41 doors_clear=False, 42 number_pushed=True, 43 above_weight_limit=True, 44 ) 45 # self.assertEqual(reality, NOT_MOVE) 46 self.assertEqual( 47 src.elevator.elevator( 48 doors_clear=False, 49 number_pushed=True, 50 above_weight_limit=True, 51 ), 52 NOT_MOVE 53 ) 54 55 reality = src.elevator.elevator( 56 doors_clear=False, 57 number_pushed=True, 58 ) 59 # self.assertEqual(reality, NOT_MOVE) 60 self.assertEqual( 61 src.elevator.elevator( 62 doors_clear=False, 63 number_pushed=True, 64 ), 65 NOT_MOVE 66 ) 67 68 def test_weight_w_doors_not_clear_number_not_pushed(self):still green.
I remove the commented lines and
realityvariables from test_weight_w_doors_not_clear_number_pushed39 def test_weight_w_doors_not_clear_number_pushed(self): 40 self.assertEqual( 41 src.elevator.elevator( 42 doors_clear=False, 43 number_pushed=True, 44 above_weight_limit=True, 45 ), 46 NOT_MOVE 47 ) 48 49 self.assertEqual( 50 src.elevator.elevator( 51 doors_clear=False, 52 number_pushed=True, 53 ), 54 NOT_MOVE 55 ) 56 57 def test_weight_w_doors_not_clear_number_not_pushed(self):on to test_weight_w_doors_clear_number_not_pushed
25 def test_weight_w_doors_clear_number_not_pushed(self): 26 reality = src.elevator.elevator( 27 doors_clear=True, 28 number_pushed=False, 29 above_weight_limit=True, 30 ) 31 # self.assertEqual(reality, NOT_MOVE) 32 self.assertEqual( 33 src.elevator.elevator( 34 doors_clear=True, 35 number_pushed=False, 36 above_weight_limit=True, 37 ), 38 NOT_MOVE 39 ) 40 41 reality = src.elevator.elevator( 42 doors_clear=True, 43 number_pushed=False, 44 ) 45 # self.assertEqual(reality, NOT_MOVE) 46 self.assertEqual( 47 src.elevator.elevator( 48 doors_clear=True, 49 number_pushed=False, 50 ), 51 NOT_MOVE 52 ) 53 54 def test_weight_w_doors_not_clear_number_pushed(self):green.
I remove the commented lines and
realityvariables from test_weight_w_doors_clear_number_not_pushed25 def test_weight_w_doors_clear_number_not_pushed(self): 26 self.assertEqual( 27 src.elevator.elevator( 28 doors_clear=True, 29 number_pushed=False, 30 above_weight_limit=True, 31 ), 32 NOT_MOVE 33 ) 34 35 self.assertEqual( 36 src.elevator.elevator( 37 doors_clear=True, 38 number_pushed=False, 39 ), 40 NOT_MOVE 41 ) 42 43 def test_weight_w_doors_not_clear_number_pushed(self):I call the
elevatorfunction directly then remove the commented lines and unused variables in test_weight_w_doors_clear_number_pushed10 def test_weight_w_doors_clear_number_pushed(self): 11 self.assertEqual( 12 src.elevator.elevator( 13 doors_clear=True, 14 number_pushed=True, 15 above_weight_limit=True, 16 ), 17 NOT_MOVE 18 ) 19 20 self.assertEqual( 21 src.elevator.elevator( 22 doors_clear=True, 23 number_pushed=True, 24 ), 25 'MOVE' 26 ) 27 28 def test_weight_w_doors_clear_number_not_pushed(self):still green.
test_doors_clear_number_pushed_w_emergency
The truth table for the elevator is
doors |
floor number |
weight limit |
output |
|---|---|---|---|
clear |
pushed |
above |
NOT MOVE |
clear |
pushed |
NOT above |
MOVE |
clear |
NOT pushed |
above |
NOT MOVE |
clear |
NOT pushed |
NOT above |
NOT MOVE |
doors |
floor number |
weight limit |
output |
|---|---|---|---|
NOT clear |
pushed |
above |
NOT MOVE |
NOT clear |
pushed |
NOT above |
NOT MOVE |
NOT clear |
NOT pushed |
above |
NOT MOVE |
NOT clear |
NOT pushed |
NOT above |
NOT MOVE |
I want to make sure the elevator can be stopped with a button in an emergency. The inputs will then be
are the doors clear?
was the number for a floor pushed?
is the elevator above the weight limit?
was the emergency button pushed?
and the truth table for when the doors are clear and the number for a floor is pushed, is
doors |
floor number |
weight limit |
emergency button |
output |
|---|---|---|---|---|
clear |
pushed |
above |
pushed |
NOT MOVE |
clear |
pushed |
above |
NOT pushed |
NOT MOVE |
clear |
pushed |
NOT above |
pushed |
NOT MOVE |
clear |
pushed |
NOT above |
NOT pushed |
MOVE |
RED: make it fail
I add a value for emergency to the first assertion in test_weight_w_doors_clear_number_pushed for the case where the doors are clear, the button for a floor is pushed, the elevator is above the weight limit, and the emergency button is pushed
doors |
floor number |
weight limit |
emergency button |
output |
|---|---|---|---|---|
clear |
pushed |
above |
pushed |
NOT MOVE |
10 def test_weight_w_doors_clear_number_pushed(self):
11 self.assertEqual(
12 src.elevator.elevator(
13 doors_clear=True,
14 number_pushed=True,
15 above_weight_limit=True,
16 emergency=True,
17 ),
18 NOT_MOVE
19 )
20
21 self.assertEqual(
22 src.elevator.elevator(
23 doors_clear=True,
24 number_pushed=True,
25 ),
26 'MOVE'
27 )
28
29 def test_weight_w_doors_clear_number_not_pushed(self):
the terminal shows TypeError
TypeError: elevator() got an unexpected keyword argument 'emergency'
because the test called the elevator function with 4 keyword arguments (doors_clear, number_pushed, above_weight_limit and emergency) and the definition only takes calls with 2 required arguments (doors_clear and number_pushed) and 1 optional argument (above_weight_limit)
GREEN: make it pass
I add
emergencyto theelevatorfunction signature inelevator.py1def elevator( 2 doors_clear, number_pushed, 3 above_weight_limit=False, emergency, 4 ): 5 not_move = 'NOT MOVE' 6 7 if above_weight_limit: 8 return not_move 9 10 if not doors_clear: 11 return not_move 12 13 if not number_pushed: 14 return not_move 15 16 return 'MOVE'the terminal is my friend, and shows SyntaxError
SyntaxError: parameter without a default follows parameter with a defaultbecause parameters without default values must come before parameters with default values
I add a default value for the
emergencyparameter in the function signature to make it a choice1def elevator( 2 doors_clear, number_pushed, 3 above_weight_limit=False, emergency=False, 4 ):the test passes.
REFACTOR: make it better
I add an assertion to test_weight_w_doors_clear_number_pushed for when the doors are clear, the button for a floor is pushed, the elevator is above the weight limit, and the emergency button is NOT pushed
doors
floor number
weight limit
emergency button
output
clear
pushed
above
NOT pushed
NOT MOVE
10 def test_weight_w_doors_clear_number_pushed(self): 11 self.assertEqual( 12 src.elevator.elevator( 13 doors_clear=True, 14 number_pushed=True, 15 above_weight_limit=True, 16 emergency=True, 17 ), 18 NOT_MOVE 19 ) 20 21 self.assertEqual( 22 src.elevator.elevator( 23 doors_clear=True, 24 number_pushed=True, 25 above_weight_limit=True, 26 emergency=False, 27 ), 28 NOT_MOVE 29 ) 30 31 self.assertEqual( 32 src.elevator.elevator( 33 doors_clear=True, 34 number_pushed=True, 35 ), 36 'MOVE' 37 ) 38 39 def test_weight_w_doors_clear_number_not_pushed(self):the test is still green.
I add an assertion to test_weight_w_doors_clear_number_pushed for when the doors are clear, the button for the floor is pushed, the elevator is NOT above the weight limit and the emergency button is pushed, in test_weight_w_doors_clear_number_pushed in
test_elevator.pydoors
floor number
weight limit
emergency button
output
clear
pushed
NOT above
pushed
NOT MOVE
10 def test_weight_w_doors_clear_number_pushed(self): 11 self.assertEqual( 12 src.elevator.elevator( 13 doors_clear=True, 14 number_pushed=True, 15 above_weight_limit=True, 16 emergency=True, 17 ), 18 NOT_MOVE 19 ) 20 21 self.assertEqual( 22 src.elevator.elevator( 23 doors_clear=True, 24 number_pushed=True, 25 above_weight_limit=True, 26 emergency=False, 27 ), 28 NOT_MOVE 29 ) 30 31 self.assertEqual( 32 src.elevator.elevator( 33 doors_clear=True, 34 number_pushed=True, 35 above_weight_limit=False, 36 emergency=True, 37 ), 38 NOT_MOVE 39 ) 40 41 self.assertEqual( 42 src.elevator.elevator( 43 doors_clear=True, 44 number_pushed=True, 45 ), 46 'MOVE' 47 ) 48 49 def test_weight_w_doors_clear_number_not_pushed(self):the terminal is my friend, and shows AssertionError
AssertionError: 'MOVE' != 'NOT MOVE'because the
elevatorfunction returns ‘MOVE’ and the assertion expects ‘NOT MOVE’I add an if statement to the
elevatorfunction inelevator.py1def elevator( 2 doors_clear, number_pushed, 3 above_weight_limit=False, emergency=False, 4 ): 5 not_move = 'NOT MOVE' 6 7 if emergency == True: 8 return not_move 9 10 if above_weight_limit: 11 return not_move 12 13 if not doors_clear: 14 return not_move 15 16 if not number_pushed: 17 return not_move 18 19 return 'MOVE'the test passes.
I use the bool built-in function
7 # if emergency == True: 8 if bool(emergency) == True: 9 return not_movethe test is still green.
I remove
== True7 # if emergency == True: 8 # if bool(emergency) == True: 9 if bool(emergency): 10 return not_movestill green.
I remove bool
7 # if emergency == True: 8 # if bool(emergency) == True: 9 # if bool(emergency): 10 if emergency: 11 return not_movegreen, because
if bool(something) == Trueis the same asif something == Trueis the same asif somethingI remove the commented lines
1def elevator( 2 doors_clear, number_pushed, 3 above_weight_limit=False, emergency=False, 4 ): 5 not_move = 'NOT MOVE' 6 7 if emergency: 8 return not_move 9 10 if above_weight_limit: 11 return not_move 12 13 if not doors_clear: 14 return not_move 15 16 if not number_pushed: 17 return not_move 18 19 return 'MOVE'this is what happens when the
elevatorfunction is calledit returns ‘NOT MOVE’ if the emergency button is pushed
it returns ‘NOT MOVE’ if the elevator is above the weight limit
it returns ‘NOT MOVE’ if the button for the floor is NOT pushed
it returns ‘NOT MOVE’ if the doors are NOT clear
it returns ‘MOVE’ if the above conditions are NOT met
I add values for the
above_weight_limitandemergencyparameters to test_weight_w_doors_clear_number_pushed, even though I do not need to because they have default values. This will make things clearer in the last assertion which is for when the doors are clear, the button for the floor is pushed, the elevator is NOT above the weight limit, and the emergency button is NOT pushed, intest_elevator.pydoors
floor number
weight limit
emergency button
output
clear
pushed
NOT above
NOT pushed
MOVE
10 def test_weight_w_doors_clear_number_pushed(self): 11 self.assertEqual( 12 src.elevator.elevator( 13 doors_clear=True, 14 number_pushed=True, 15 above_weight_limit=True, 16 emergency=True, 17 ), 18 NOT_MOVE 19 ) 20 21 self.assertEqual( 22 src.elevator.elevator( 23 doors_clear=True, 24 number_pushed=True, 25 above_weight_limit=True, 26 emergency=False, 27 ), 28 NOT_MOVE 29 ) 30 31 self.assertEqual( 32 src.elevator.elevator( 33 doors_clear=True, 34 number_pushed=True, 35 above_weight_limit=False, 36 emergency=True, 37 ), 38 NOT_MOVE 39 ) 40 41 self.assertEqual( 42 src.elevator.elevator( 43 doors_clear=True, 44 number_pushed=True, 45 above_weight_limit=False, 46 emergency=False, 47 ), 48 'MOVE' 49 ) 50 51 def test_weight_w_doors_clear_number_not_pushed(self):green.
I change the name of the test from test_weight_w_doors_clear_number_pushed to test_doors_clear_number_pushed_w_emergency
8class TestElevator(unittest.TestCase): 9 10 def test_doors_clear_number_pushed_w_emergency(self): 11 self.assertEqual( 12 src.elevator.elevator( 13 doors_clear=True, 14 number_pushed=True, 15 above_weight_limit=True, 16 emergency=True, 17 ), 18 NOT_MOVE 19 )
test_doors_clear_number_not_pushed_w_emergency
The truth table for when the doors are clear and the button for a floor is NOT pushed, is
doors |
floor number |
weight limit |
emergency button |
output |
|---|---|---|---|---|
clear |
NOT pushed |
above |
pushed |
NOT MOVE |
clear |
NOT pushed |
above |
NOT pushed |
NOT MOVE |
clear |
NOT pushed |
NOT above |
pushed |
NOT MOVE |
clear |
NOT pushed |
NOT above |
NOT pushed |
NOT MOVE |
I add a value for the
emergencyparameter to the first assertion in test_weight_w_doors_clear_number_not_pushed for when the doors are clear, button for a floor is NOT pushed, the elevator is above the weight limit, and the emergency button is pusheddoors
floor number
weight limit
emergency button
output
clear
NOT pushed
above
pushed
NOT MOVE
51 def test_weight_w_doors_clear_number_not_pushed(self): 52 self.assertEqual( 53 src.elevator.elevator( 54 doors_clear=True, 55 number_pushed=False, 56 above_weight_limit=True, 57 emergency=True, 58 ), 59 NOT_MOVE 60 )still green.
I add an assertion for when the doors are clear, the button for a floor is NOT pushed, the elevator is above the weight limit, and the emergency button is NOT pushed
doors
floor number
weight limit
emergency button
output
clear
NOT pushed
above
NOT pushed
NOT MOVE
51 def test_weight_w_doors_clear_number_not_pushed(self): 52 self.assertEqual( 53 src.elevator.elevator( 54 doors_clear=True, 55 number_pushed=False, 56 above_weight_limit=True, 57 emergency=True, 58 ), 59 NOT_MOVE 60 ) 61 62 self.assertEqual( 63 src.elevator.elevator( 64 doors_clear=True, 65 number_pushed=False, 66 above_weight_limit=True, 67 emergency=False, 68 ), 69 NOT_MOVE 70 ) 71 72 self.assertEqual( 73 src.elevator.elevator( 74 doors_clear=True, 75 number_pushed=False, 76 ), 77 NOT_MOVE 78 ) 79 80 def test_weight_w_doors_not_clear_number_pushed(self):the test is still green.
I add values for the
above_weight_limitandemergencyparameters, even though I do not need to because they have default values. This will make things clearer in the last assertion, for when the doors are clear, the button for the floor is NOT pushed, the elevator is NOT above the weight limit, and the emergency button is pusheddoors
floor number
weight limit
emergency button
output
clear
NOT pushed
NOT above
pushed
NOT MOVE
51 def test_weight_w_doors_clear_number_not_pushed(self): 52 self.assertEqual( 53 src.elevator.elevator( 54 doors_clear=True, 55 above_weight_limit=False, 56 number_pushed=True, 57 emergency=True, 58 ), 59 NOT_MOVE 60 ) 61 62 self.assertEqual( 63 src.elevator.elevator( 64 doors_clear=True, 65 above_weight_limit=False, 66 number_pushed=True, 67 emergency=False, 68 ), 69 NOT_MOVE 70 ) 71 72 self.assertEqual( 73 src.elevator.elevator( 74 doors_clear=True, 75 above_weight_limit=False, 76 number_pushed=False, 77 emergency=True, 78 ), 79 NOT_MOVE 80 ) 81 82 def test_weight_w_doors_not_clear_number_pushed(self):still green.
I add an assertion for when the doors are clear, the button for the floor is NOT pushed, the elevator is NOT above the weight limit, and the emergency button is NOT pushed
doors
floor number
weight limit
emergency button
output
clear
NOT pushed
NOT above
NOT pushed
NOT MOVE
51 def test_weight_w_doors_clear_number_not_pushed(self): 52 self.assertEqual( 53 src.elevator.elevator( 54 doors_clear=True, 55 number_pushed=False, 56 above_weight_limit=True, 57 emergency=True, 58 ), 59 NOT_MOVE 60 ) 61 62 self.assertEqual( 63 src.elevator.elevator( 64 doors_clear=True, 65 number_pushed=False, 66 above_weight_limit=True, 67 emergency=False, 68 ), 69 NOT_MOVE 70 ) 71 72 self.assertEqual( 73 src.elevator.elevator( 74 doors_clear=True, 75 number_pushed=False, 76 above_weight_limit=False, 77 emergency=True, 78 ), 79 NOT_MOVE 80 ) 81 82 self.assertEqual( 83 src.elevator.elevator( 84 doors_clear=True, 85 number_pushed=False, 86 above_weight_limit=False, 87 emergency=False, 88 ), 89 NOT_MOVE 90 ) 91 92 def test_weight_w_doors_not_clear_number_pushed(self):green.
I change the name of the test from test_weight_w_doors_clear_number_not_pushed to test_doors_clear_number_not_pushed_w_emergency
41 self.assertEqual( 42 src.elevator.elevator( 43 doors_clear=True, 44 number_pushed=True, 45 above_weight_limit=False, 46 emergency=False, 47 ), 48 'MOVE' 49 ) 50 51 def test_doors_clear_number_not_pushed_w_emergency(self): 52 self.assertEqual( 53 src.elevator.elevator( 54 doors_clear=True, 55 number_pushed=False, 56 above_weight_limit=True, 57 emergency=True, 58 ), 59 NOT_MOVE 60 )
test_doors_not_clear_number_pushed_w_emergency
The truth table for when the doors are NOT clear and the button for a floor is pushed, is
doors |
floor number |
weight limit |
emergency button |
output |
|---|---|---|---|---|
NOT clear |
pushed |
above |
pushed |
NOT MOVE |
NOT clear |
pushed |
above |
NOT pushed |
NOT MOVE |
NOT clear |
pushed |
NOT above |
pushed |
NOT MOVE |
NOT clear |
pushed |
NOT above |
NOT pushed |
NOT MOVE |
I add a value for the
emergencyparameter to the first assertion of test_weight_w_doors_not_clear_number_pushed, for when the doors are NOT clear, the button for a floor is pushed, the elevator is above the weight limit, and the emergency button is pusheddoors
floor number
weight limit
emergency button
output
NOT clear
pushed
above
pushed
NOT MOVE
92 def test_weight_w_doors_not_clear_number_pushed(self): 93 self.assertEqual( 94 src.elevator.elevator( 95 doors_clear=False, 96 number_pushed=True, 97 above_weight_limit=True, 98 emergency=True, 99 ), 100 NOT_MOVE 101 )still green.
I add an assertion for when the doors are NOT clear, the button for a floor is pushed, the elevator is above the weight limit, and the emergency button is NOT pushed
doors
floor number
weight limit
emergency button
output
NOT clear
pushed
above
NOT pushed
NOT MOVE
92 def test_weight_w_doors_not_clear_number_pushed(self): 93 self.assertEqual( 94 src.elevator.elevator( 95 doors_clear=False, 96 number_pushed=True, 97 above_weight_limit=True, 98 emergency=True, 99 ), 100 NOT_MOVE 101 ) 102 103 self.assertEqual( 104 src.elevator.elevator( 105 doors_clear=False, 106 number_pushed=True, 107 above_weight_limit=True, 108 emergency=False, 109 ), 110 NOT_MOVE 111 ) 112 113 self.assertEqual( 114 src.elevator.elevator( 115 doors_clear=False, 116 number_pushed=True, 117 ), 118 NOT_MOVE 119 ) 120 121 def test_weight_w_doors_not_clear_number_not_pushed(self):still green.
I add a value for the
above_weight_limit, even though I do not need to because it has a default value. I also add a value for theemergencyparameter. This will make things clearer in the third assertion which is for when the doors are NOT clear, the button for the floor is pushed, the elevator is NOT above the weight limit, and the emergency button is pusheddoors
floor number
weight limit
emergency button
output
NOT clear
pushed
NOT above
pushed
NOT MOVE
92 def test_weight_w_doors_not_clear_number_pushed(self): 93 self.assertEqual( 94 src.elevator.elevator( 95 doors_clear=False, 96 number_pushed=True, 97 above_weight_limit=True, 98 emergency=True, 99 ), 100 NOT_MOVE 101 ) 102 103 self.assertEqual( 104 src.elevator.elevator( 105 doors_clear=False, 106 number_pushed=True, 107 above_weight_limit=True, 108 emergency=False, 109 ), 110 NOT_MOVE 111 ) 112 113 self.assertEqual( 114 src.elevator.elevator( 115 doors_clear=False, 116 number_pushed=True, 117 above_weight_limit=False, 118 emergency=True, 119 ), 120 NOT_MOVE 121 ) 122 123 def test_weight_w_doors_not_clear_number_not_pushed(self):the test is still green.
I add an assertion for when the doors are NOT clear, the button for the floor is pushed, the elevator is NOT above the weight limit, and the emergency button is NOT pushed
doors
floor number
weight limit
emergency button
output
NOT clear
pushed
NOT above
NOT pushed
NOT MOVE
92 def test_weight_w_doors_not_clear_number_pushed(self): 93 self.assertEqual( 94 src.elevator.elevator( 95 doors_clear=False, 96 number_pushed=True, 97 above_weight_limit=True, 98 emergency=True, 99 ), 100 NOT_MOVE 101 ) 102 103 self.assertEqual( 104 src.elevator.elevator( 105 doors_clear=False, 106 number_pushed=True, 107 above_weight_limit=True, 108 emergency=False, 109 ), 110 NOT_MOVE 111 ) 112 113 self.assertEqual( 114 src.elevator.elevator( 115 doors_clear=False, 116 number_pushed=True, 117 above_weight_limit=False, 118 emergency=True, 119 ), 120 NOT_MOVE 121 ) 122 123 self.assertEqual( 124 src.elevator.elevator( 125 doors_clear=False, 126 number_pushed=True, 127 above_weight_limit=False, 128 emergency=False, 129 ), 130 NOT_MOVE 131 ) 132 133 def test_weight_w_doors_not_clear_number_not_pushed(self):still green.
I change the name of the test from test_weight_w_doors_not_clear_number_pushed to test_doors_not_clear_number_pushed_w_emergency
82 self.assertEqual( 83 src.elevator.elevator( 84 doors_clear=True, 85 number_pushed=False, 86 above_weight_limit=False, 87 emergency=False, 88 ), 89 NOT_MOVE 90 ) 91 92 def test_doors_not_clear_number_pushed_w_emergency(self): 93 self.assertEqual( 94 src.elevator.elevator( 95 doors_clear=False, 96 number_pushed=True, 97 above_weight_limit=True, 98 emergency=True, 99 ), 100 NOT_MOVE 101 )
test_doors_not_clear_number_not_pushed_w_emergency
The truth table for when the doors are NOT clear and the button for a floor is NOT pushed, is
doors |
floor number |
weight limit |
emergency button |
output |
|---|---|---|---|---|
NOT clear |
NOT pushed |
above |
pushed |
NOT MOVE |
NOT clear |
NOT pushed |
above |
NOT pushed |
NOT MOVE |
NOT clear |
NOT pushed |
NOT above |
pushed |
NOT MOVE |
NOT clear |
NOT pushed |
NOT above |
NOT pushed |
NOT MOVE |
I add a value for the
emergencyparameter to the first assertion in test_weight_w_doors_not_clear_number_not_pushed, for when the doors are NOT clear, the button for a floor is NOT pushed, the elevator is above the weight limit, and the emergency button is pusheddoors
floor number
weight limit
emergency button
output
NOT clear
NOT pushed
above
pushed
NOT MOVE
133 def test_weight_w_doors_not_clear_number_not_pushed(self): 134 self.assertEqual( 135 src.elevator.elevator( 136 doors_clear=False, 137 number_pushed=False, 138 above_weight_limit=True, 139 emergency=True, 140 ), 141 NOT_MOVE 142 )the test is still green.
I add an assertion for when the doors are NOT clear, the button for a floor is NOT pushed, the elevator is above the weight limit, and the emergency button is NOT pushed
doors
floor number
weight limit
emergency button
output
NOT clear
NOT pushed
above
NOT pushed
NOT MOVE
133 def test_weight_w_doors_not_clear_number_not_pushed(self): 134 self.assertEqual( 135 src.elevator.elevator( 136 doors_clear=False, 137 number_pushed=False, 138 above_weight_limit=True, 139 emergency=True, 140 ), 141 NOT_MOVE 142 ) 143 144 self.assertEqual( 145 src.elevator.elevator( 146 doors_clear=False, 147 number_pushed=False, 148 above_weight_limit=True, 149 emergency=False, 150 ), 151 NOT_MOVE 152 ) 153 154 self.assertEqual( 155 src.elevator.elevator( 156 doors_clear=False, 157 number_pushed=False, 158 ), 159 NOT_MOVE 160 ) 161 162 163# Exceptions seenstill green.
I add values for the
above_weight_limitparameter, even though I do not need to because it has a default value. I also add a value for theemergencyparameter. This will make things clearer in the third assertion, which is for when the doors are NOT clear, the button for the floor is NOT pushed, the elevator is NOT above the weight limit, and the emergency button is pusheddoors
floor number
weight limit
emergency button
output
NOT clear
NOT pushed
NOT above
pushed
NOT MOVE
133 def test_weight_w_doors_not_clear_number_not_pushed(self): 134 self.assertEqual( 135 src.elevator.elevator( 136 doors_clear=False, 137 number_pushed=False, 138 above_weight_limit=True, 139 emergency=True, 140 ), 141 NOT_MOVE 142 ) 143 144 self.assertEqual( 145 src.elevator.elevator( 146 doors_clear=False, 147 number_pushed=False, 148 above_weight_limit=True, 149 emergency=False, 150 ), 151 NOT_MOVE 152 ) 153 154 self.assertEqual( 155 src.elevator.elevator( 156 doors_clear=False, 157 number_pushed=False, 158 above_weight_limit=False, 159 emergency=True, 160 ), 161 NOT_MOVE 162 ) 163 164 165# Exceptions seengreen.
I add an assertion for when the doors are NOT clear, the button for the floor is NOT pushed, the elevator is NOT above the weight limit, and the emergency button is NOT pushed
doors
floor number
weight limit
emergency button
output
NOT clear
NOT pushed
NOT above
NOT pushed
NOT MOVE
133 def test_weight_w_doors_not_clear_number_not_pushed(self): 134 self.assertEqual( 135 src.elevator.elevator( 136 doors_clear=False, 137 number_pushed=False, 138 above_weight_limit=True, 139 emergency=True, 140 ), 141 NOT_MOVE 142 ) 143 144 self.assertEqual( 145 src.elevator.elevator( 146 doors_clear=False, 147 number_pushed=False, 148 above_weight_limit=True, 149 emergency=False, 150 ), 151 NOT_MOVE 152 ) 153 154 self.assertEqual( 155 src.elevator.elevator( 156 doors_clear=False, 157 number_pushed=False, 158 above_weight_limit=False, 159 emergency=True, 160 ), 161 NOT_MOVE 162 ) 163 164 self.assertEqual( 165 src.elevator.elevator( 166 doors_clear=False, 167 above_weight_limit=False, 168 number_pushed=False, 169 emergency=False, 170 ), 171 NOT_MOVE 172 ) 173 174 175# Exceptions seenall the tests are still green.
I change the name of the test from test_weight_w_doors_not_clear_number_not_pushed to test_doors_not_clear_number_not_pushed_w_emergency
123 self.assertEqual( 124 src.elevator.elevator( 125 doors_clear=False, 126 above_weight_limit=True, 127 number_pushed=False, 128 emergency=False, 129 ), 130 NOT_MOVE 131 ) 132 133 def test_doors_not_clear_number_not_pushed_w_emergency(self): 134 self.assertEqual( 135 src.elevator.elevator( 136 doors_clear=False, 137 above_weight_limit=False, 138 number_pushed=True, 139 emergency=True, 140 ), 141 NOT_MOVE 142 )To review, the
elevatorfunction1def elevator( 2 doors_clear, number_pushed, 3 above_weight_limit=False, emergency=False, 4 ): 5 not_move = 'NOT MOVE' 6 7 if emergency: 8 return not_move 9 10 if above_weight_limit: 11 return not_move 12 13 if not doors_clear: 14 return not_move 15 16 if not number_pushed: 17 return not_move 18 19 return 'MOVE'returns ‘NOT MOVE’ if the emergency button is pushed
returns ‘NOT MOVE’ if the elevator is above the weight limit
returns ‘NOT MOVE’ if the button for the floor is NOT pushed
returns ‘NOT MOVE’ if the doors are NOT clear
returns ‘MOVE’ if the above conditions are NOT met
All the if statements return ‘NOT MOVE’ which means I could use Logical Disjunction (OR) to put them together though it will be a long statement
1def elevator( 2 doors_clear, number_pushed, 3 above_weight_limit=False, emergency=False, 4 ): 5 if ( 6 emergency 7 or above_weight_limit 8 or not doors_clear 9 or not number_pushed 10 ): 11 return 'NOT MOVE' 12 13 return 'MOVE'the tests are still green.
I rewrite the statement in terms of NOT because it happens two times
1def elevator( 2 doors_clear, number_pushed, 3 above_weight_limit=False, emergency=False, 4 ): 5 # if ( 6 # emergency 7 # or above_weight_limit 8 # or not doors_clear 9 # or not number_pushed 10 # ): 11 if ( 12 emergency 13 or above_weight_limit 14 or ( 15 (not doors_clear) 16 (not and) 17 (not number_pushed) 18 ) 19 ): 20 return 'NOT MOVE' 21 22 return 'MOVE'the terminal is my friend, and shows SyntaxError
SyntaxError: invalid syntaxI “factor” out the nots
1def elevator( 2 doors_clear, number_pushed, 3 above_weight_limit=False, emergency=False, 4 ): 5 # if ( 6 # emergency 7 # or above_weight_limit 8 # or not doors_clear 9 # or not number_pushed 10 # ): 11 # if ( 12 # emergency 13 # or above_weight_limit 14 # or ( 15 # (not doors_clear) 16 # (not and) 17 # (not number_pushed) 18 # ) 19 # ): 20 if ( 21 emergency 22 or above_weight_limit 23 or not ( 24 doors_clear 25 and 26 number_pushed 27 ) 28 ): 29 return 'NOT MOVE' 30 31 return 'MOVE'the tests are green again
I remove the commented lines
1def elevator( 2 doors_clear, number_pushed, 3 above_weight_limit=False, emergency=False, 4 ): 5 if ( 6 emergency 7 or above_weight_limit 8 or not ( 9 doors_clear 10 and 11 number_pushed 12 ) 13 ): 14 return 'NOT MOVE' 15 16 return 'MOVE'Which do you like better? One if statement to bind them all or many simple statements?
close the project
I close
test_elevator.pyandelevator.pyI click in the terminal, then use q on the doorsboard to leave the tests. The terminal goes back to the command line.
I change directory to the parent of
elevatorcd ..the terminal shows
.../pumping_pythonI am back in the
pumping_pythondirectory
review
I ran tests for a elevator with these inputs:
are the doors clear?
is it above the weight limit?
was the number for a floor pushed?
was the emergency button pushed?
the inputs gave me this truth table
doors |
floor number |
weight limit |
emergency button |
output |
|---|---|---|---|---|
clear |
pushed |
above |
pushed |
NOT MOVE |
clear |
pushed |
above |
NOT pushed |
NOT MOVE |
clear |
pushed |
NOT above |
pushed |
NOT MOVE |
clear |
pushed |
NOT above |
NOT pushed |
MOVE |
doors |
floor number |
weight limit |
emergency button |
output |
|---|---|---|---|---|
clear |
NOT pushed |
above |
pushed |
NOT MOVE |
clear |
NOT pushed |
above |
NOT pushed |
NOT MOVE |
clear |
NOT pushed |
NOT above |
pushed |
NOT MOVE |
clear |
NOT pushed |
NOT above |
NOT pushed |
NOT MOVE |
doors |
floor number |
weight limit |
emergency button |
output |
|---|---|---|---|---|
NOT clear |
pushed |
above |
pushed |
NOT MOVE |
NOT clear |
pushed |
above |
NOT pushed |
NOT MOVE |
NOT clear |
pushed |
NOT above |
pushed |
NOT MOVE |
NOT clear |
pushed |
NOT above |
NOT pushed |
NOT MOVE |
doors |
floor number |
weight limit |
emergency button |
output |
|---|---|---|---|---|
NOT clear |
NOT pushed |
above |
pushed |
NOT MOVE |
NOT clear |
NOT pushed |
above |
NOT pushed |
NOT MOVE |
NOT clear |
NOT pushed |
NOT above |
pushed |
NOT MOVE |
NOT clear |
NOT pushed |
NOT above |
NOT pushed |
NOT MOVE |
the only time this elevator goes up or down is when the doors are clear, the button for a floor is pushed, the elevator is NOT above the weight limit, and the emergency button is NOT pushed.
code from the chapter
what is next?
you now know
rate pumping python
If this has been a 7 star experience for you, please CLICK HERE to leave a 5 star review of pumping python. It helps other people get into the book too.