Traffic Light
I want to make a Traffic Light that changes color because of a timer. If the inputs are
what color is the light now?
is the timer done?
then this is the truth table I get
current light (first) |
timer (second) |
show (output) |
|---|---|---|
RED |
done |
GREEN |
RED |
NOT done |
RED |
YELLOW |
done |
RED |
YELLOW |
NOT done |
YELLOW |
GREEN |
done |
YELLOW |
GREEN |
NOT done |
GREEN |
preview
These are the tests I have at the end of the chapter
1import src.traffic_light
2import unittest
3
4
5RED, YELLOW, GREEN = 'RED', 'YELLOW', 'GREEN'
6NO_WALK = 'NO WALK'
7WALK = (RED, 'WALK')
8YELLOW_NO_WALK = (YELLOW, NO_WALK)
9GREEN_NO_WALK = (GREEN, NO_WALK)
10
11
12class TestTrafficLight(unittest.TestCase):
13
14 def test_red_traffic_light_w_walk(self):
15 self.assertEqual(
16 src.traffic_light.show(
17 current_light=RED,
18 timer_done=True,
19 walk_button=True,
20 ),
21 WALK
22 )
23
24 self.assertEqual(
25 src.traffic_light.show(
26 current_light=RED,
27 timer_done=True,
28 walk_button=False,
29 ),
30 GREEN_NO_WALK
31 )
32
33 self.assertEqual(
34 src.traffic_light.show(
35 current_light=RED,
36 timer_done=False,
37 walk_button=True,
38 ),
39 WALK
40 )
41
42 self.assertEqual(
43 src.traffic_light.show(
44 current_light=RED,
45 timer_done=False,
46 walk_button=False,
47 ),
48 WALK
49 )
50
51 def test_yellow_traffic_light_w_walk(self):
52 self.assertEqual(
53 src.traffic_light.show(
54 current_light=YELLOW,
55 timer_done=True,
56 walk_button=True,
57 ),
58 WALK
59 )
60
61 self.assertEqual(
62 src.traffic_light.show(
63 current_light=YELLOW,
64 timer_done=True,
65 walk_button=False,
66 ),
67 WALK
68 )
69
70 self.assertEqual(
71 src.traffic_light.show(
72 current_light=YELLOW,
73 timer_done=False,
74 walk_button=True,
75 ),
76 YELLOW_NO_WALK
77 )
78
79 self.assertEqual(
80 src.traffic_light.show(
81 current_light=YELLOW,
82 timer_done=False,
83 walk_button=False,
84 ),
85 YELLOW_NO_WALK
86 )
87
88 def test_green_traffic_light_w_walk(self):
89 self.assertEqual(
90 src.traffic_light.show(
91 current_light=GREEN,
92 timer_done=True,
93 walk_button=True,
94 ),
95 YELLOW_NO_WALK
96 )
97
98 self.assertEqual(
99 src.traffic_light.show(
100 current_light=GREEN,
101 timer_done=True,
102 walk_button=False,
103 ),
104 YELLOW_NO_WALK
105 )
106
107 self.assertEqual(
108 src.traffic_light.show(
109 current_light=GREEN,
110 timer_done=False,
111 walk_button=True,
112 ),
113 GREEN_NO_WALK
114 )
115
116 self.assertEqual(
117 src.traffic_light.show(
118 current_light=GREEN,
119 timer_done=False,
120 walk_button=False,
121 ),
122 GREEN_NO_WALK
123 )
124
125
126# Exceptions seen
127# AssertionError
128# NameError
129# AttributeError
130# TypeError
131# SyntaxError
requirements
start the project
I name this project
traffic_lightI open a terminal
I use uv to make a directory for the project and initialize it
uv init traffic_lightthe terminal shows
Initialized project `traffic-light` at `.../pumping_python/traffic_light`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.pytotraffic_light.pyand move it to thesrcfoldermv main.py src/traffic_light.pyMove-Item main.py src/traffic_light.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_traffic_light.pyNew-Item tests/test_traffic_light.pythe terminal goes back to the command line.
I open
test_traffic_light.pyin the editor of the Integrated Development Environment (IDE)Tip
I can open a file from the terminal in the Integrated Development Environment (IDE) with the name of the program and the name of the file. That means if I type this in the terminal
code tests/test_traffic_light.pyVisual Studio Code opens
test_traffic_light.pyin the editorI add the first failing test to
test_traffic_light.py1import unittest 2 3 4class TestTrafficLight(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 install the Python packages that I wrote in the requirements file
uv add --requirement requirements.txtthe terminal shows that it installed the Python packages
I use tree to look at the structure of the project
treethe terminal shows
. ├── README.md ├── pyproject.toml ├── requirements.txt ├── src │ └── traffic_light.py ├── tests │ ├── __init__.py │ └── test_traffic_light.py └── uv.lockI use pytest-watcher to run the tests automatically
uv run pytest-watcher . --nowthe terminal is my friend, and shows AssertionError
================================ FAILURES ================================ ____________________ TestTrafficLight.test_failure _______________________ self = <tests.test_traffic_light.TestTrafficLight testMethod=test_failure> def test_failure(self): > self.assertFalse(True) E AssertionError: True is not false tests/test_traffic_light.py:7: AssertionError ======================== short test summary info ========================= FAILED tests/test_traffic_light.py::TestTrafficLight::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_traffic_light.py4class TestTrafficLight(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_red_traffic_light
The truth table for if the Traffic Light is RED is
current light |
timer |
show |
|---|---|---|
RED |
done |
GREEN |
RED |
NOT done |
RED |
RED: make it fail
I change test_failure to test_red_traffic_light, then add an assertion for when the light is RED and the timer is done
current light |
timer done |
show |
|---|---|---|
RED |
done |
GREEN |
4class TestTrafficLight(unittest.TestCase):
5
6 def test_red_traffic_light(self):
7 my_expectation = 'GREEN'
8 reality = src.traffic_light.show(
9 current_light='RED',
10 timer_done=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 so that I can test
traffic_light.pyfrom thesrcfolder1import src.traffic_light 2import unittest 3 4 5class TestTrafficLight(unittest.TestCase):the terminal is my friend, and shows AttributeError
AttributeError: module 'src.traffic_light' has no attribute 'show'because
traffic_light.pyin thesrcfolder does not have anything namedshowin 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 use the Explorer to open
traffic_light.pyfrom thesrcfolder in the editorI add a function to
traffic_light.py1def show(): 2 return Nonethe terminal is my friend, and shows TypeError
TypeError: show() got an unexpected keyword argument 'current_light'because the test called the
showfunction with two keyword arguments and this definition only takes calls with 0 argumentsI add TypeError to the list of Exceptions seen in
test_traffic_light.py16# Exceptions seen 17# AssertionError 18# NameError 19# AttributeError 20# TypeErrorI add the keyword argument to the function in
traffic_light.py1def show(current_light): 2 return Nonethe terminal is my friend, and shows TypeError
TypeError: show() got an unexpected keyword argument 'timer_done'because the test called the
showfunction with two keyword arguments and this definition only takes calls with 1 inputI add
timer_doneto the function signature1def show(current_light, timer_done): 2 return Nonethe terminal is my friend, and shows AssertionError
AssertionError: None != 'GREEN'the
showfunction always returns None and the assertion expects'GREEN'I change the return statement to give the test what it expects
1def show(current_light, timer_done): 2 return 'GREEN'the test passes. The
showfunction always returns GREEN, it does not care about the inputs. Is this Contradiction or Tautology?
REFACTOR: make it better
I add an assertion for when the light is RED and the timer is NOT done, in
test_traffic_light.pycurrent light
timer
show
RED
done
GREEN
RED
NOT done
RED
7 def test_red_traffic_light(self): 8 my_expectation = 'GREEN' 9 reality = src.traffic_light.show( 10 current_light='RED', 11 timer_done=True, 12 ) 13 self.assertEqual(reality, my_expectation) 14 15 my_expectation = 'RED' 16 reality = src.traffic_light.show( 17 current_light='RED', 18 timer_done=False, 19 ) 20 self.assertEqual(reality, my_expectation) 21 22 23# Exceptions seenthe terminal is my friend, and shows AssertionError
AssertionError: 'GREEN' != 'RED'because the
showfunction returns'GREEN'and the assertion expects'RED'I add an if statement for this case, to
traffic_light.py1def show(current_light, timer_done): 2 if timer_done == False: 3 return 'RED' 4 return 'GREEN'the test passes.
I use the bool built-in function
1def show(current_light, timer_done): 2 # if timer_done == False: 3 if bool(timer_done) == False: 4 return 'RED' 5 return 'GREEN'the test is still green.
I use logical_negation (NOT) to write the statement in terms of True
1def show(current_light, timer_done): 2 # if timer_done == False: 3 # if bool(timer_done) == False: 4 if not bool(timer_done) == True: 5 return 'RED' 6 return 'GREEN'still green.
I remove
== True1def show(current_light, timer_done): 2 # if timer_done == False: 3 # if bool(timer_done) == False: 4 # if not bool(timer_done) == True: 5 if not bool(timer_done): 6 return 'RED' 7 return 'GREEN'green.
I remove bool
1def show(current_light, timer_done): 2 # if timer_done == False: 3 # if bool(timer_done) == False: 4 # if not bool(timer_done) == True: 5 # if not bool(timer_done): 6 if not timer_done: 7 return 'RED' 8 return 'GREEN'still green because
if bool(something) == Falseis the same asif not bool(something) == Trueis the same asif not somethingI remove the commented lines
1def show(current_light, timer_done): 2 if not timer_done: 3 return 'RED' 4 return 'GREEN'If the current Traffic Light is RED, the
showfunction returnsGREEN if the timer is done
RED if the timer is NOT done
test_yellow_traffic_light
The truth table for if the Traffic Light is YELLOW is
current light |
timer |
show |
|---|---|---|
YELLOW |
done |
RED |
YELLOW |
NOT done |
YELLOW |
RED: make it fail
I add a test with an assertion for if the Traffic Light is YELLOW and the timer is done, to test_traffic_light.py
current light |
timer |
show |
|---|---|---|
YELLOW |
done |
RED |
7 def test_red_traffic_light(self):
8 my_expectation = 'GREEN'
9 reality = src.traffic_light.show(
10 current_light='RED',
11 timer_done=True,
12 )
13 self.assertEqual(reality, my_expectation)
14
15 my_expectation = 'RED'
16 reality = src.traffic_light.show(
17 current_light='RED',
18 timer_done=False,
19 )
20 self.assertEqual(reality, my_expectation)
21
22 def test_yellow_traffic_light(self):
23 my_expectation = 'RED'
24 reality = src.traffic_light.show(
25 current_light='YELLOW',
26 timer_done=True,
27 )
28 self.assertEqual(reality, my_expectation)
29
30
31# Exceptions seen
the terminal is my friend, and shows AssertionError
AssertionError: 'GREEN' != 'RED'
because the show function returned 'GREEN' and the assertion expects 'RED'
GREEN: make it pass
I add an if statement to traffic_light.py
1def show(current_light, timer_done):
2 if not timer_done:
3 return 'RED'
4
5 if current_light == 'YELLOW':
6 return 'RED'
7
8 return 'GREEN'
the test passes. This is what happens when the show function is called
if the timer is NOT done it returns RED
if the timer is done
it returns RED if the current light is YELLOW
it returns GREEN if the current light is NOT YELLOW
REFACTOR: make it better
I add an assertion for when the light is YELLOW and the timer is NOT done, to test_yellow_traffic_light in
test_traffic_light.pycurrent light
timer
show
YELLOW
done
RED
YELLOW
NOT done
YELLOW
22 def test_yellow_traffic_light(self): 23 my_expectation = 'RED' 24 reality = src.traffic_light.show( 25 current_light='YELLOW', 26 timer_done=True, 27 ) 28 self.assertEqual(reality, my_expectation) 29 30 my_expectation = 'YELLOW' 31 reality = src.traffic_light.show( 32 current_light='YELLOW', 33 timer_done=False, 34 ) 35 self.assertEqual(reality, my_expectation) 36 37 38# Exceptions seenthe terminal is my friend, and shows AssertionError
AssertionError: 'RED' != 'YELLOW'because the
showfunction returned'RED'and the assertion expects'YELLOW'I add an if statement to the one for when the timer is NOT done, in
traffic_light.py1def show(current_light, timer_done): 2 if not timer_done: 3 if current_light == 'YELLOW': 4 return 'YELLOW' 5 return 'RED' 6 7 if current_light == 'YELLOW': 8 return 'RED' 9 10 return 'GREEN'the test passes.
This is what happens when the show function is called
if the timer is NOT done
it returns YELLOW if the current light is YELLOW
it returns RED if the current light is NOT YELLOW
if the timer is done
it returns RED if the current light is YELLOW
it returns GREEN if the current light is NOT YELLOW
test_green_traffic_light
The truth table for if the Traffic Light is GREEN is
current light |
timer |
show |
|---|---|---|
GREEN |
done |
YELLOW |
GREEN |
NOT done |
GREEN |
RED: make it fail
I add a test with an assertion for if the Traffic Light is GREEN and the timer is done, to test_traffic_light.py
current light |
timer |
show |
|---|---|---|
GREEN |
done |
YELLOW |
22 def test_yellow_traffic_light(self):
23 my_expectation = 'RED'
24 reality = src.traffic_light.show(
25 current_light='YELLOW',
26 timer_done=True,
27 )
28 self.assertEqual(reality, my_expectation)
29
30 my_expectation = 'YELLOW'
31 reality = src.traffic_light.show(
32 current_light='YELLOW',
33 timer_done=False,
34 )
35 self.assertEqual(reality, my_expectation)
36
37 def test_green_traffic_light(self):
38 my_expectation = 'YELLOW'
39 reality = src.traffic_light.show(
40 current_light='GREEN',
41 timer_done=True,
42 )
43 self.assertEqual(reality, my_expectation)
44
45
46# Exceptions seen
the terminal is my friend, and shows AssertionError
AssertionError: 'GREEN' != 'YELLOW'
because the show function returned 'GREEN' and the assertion expects 'YELLOW'
GREEN: make it pass
I add an if statement to traffic_light.py
1def show(current_light, timer_done):
2 if not timer_done:
3 if current_light == 'YELLOW':
4 return 'YELLOW'
5 return 'RED'
6
7 if current_light == 'YELLOW':
8 return 'RED'
9
10 if current_light == 'GREEN':
11 return 'YELLOW'
12
13 return 'GREEN'
the test passes. This is what happens when the show function is called
if the timer is NOT done
it returns YELLOW if the current light is YELLOW
it returns RED if the current light is NOT YELLOW
if the timer is done
it returns RED if the current light is YELLOW
it returns YELLOW if the current light is GREEN
it returns GREEN if the current light is NOT YELLOW AND the current light is NOT GREEN
REFACTOR: make it better
I add an assertion for when the light is GREEN and the timer is NOT done, to
test_traffic_light.pycurrent light
timer
show
GREEN
done
YELLOW
GREEN
NOT done
GREEN
37 def test_green_traffic_light(self): 38 my_expectation = 'YELLOW' 39 reality = src.traffic_light.show( 40 current_light='GREEN', 41 timer_done=True, 42 ) 43 self.assertEqual(reality, my_expectation) 44 45 my_expectation = 'GREEN' 46 reality = src.traffic_light.show( 47 current_light='GREEN', 48 timer_done=False, 49 ) 50 self.assertEqual(reality, my_expectation) 51 52 53# Exceptions seenthe terminal is my friend, and shows AssertionError
AssertionError: 'RED' != 'GREEN'because the
showfunction returned'RED'and the assertion expects'GREEN'I add an if statement to the one for when the timer is NOT done in
traffic_light.py1def show(current_light, timer_done): 2 if not timer_done: 3 if current_light == 'YELLOW': 4 return 'YELLOW' 5 if current_light == 'GREEN': 6 return 'GREEN' 7 return 'RED' 8 9 if current_light == 'YELLOW': 10 return 'RED' 11 12 if current_light == 'GREEN': 13 return 'YELLOW' 14 15 return 'GREEN'the test passes. This is what happens when the
showfunction is calledif the timer is NOT done
it returns YELLOW if the current light is YELLOW
it returns GREEN if the current light is GREEN
it returns RED if the current light is NOT YELLOW and the current light is NOT GREEN
if the timer is done
it returns RED if the current light is YELLOW
it returns YELLOW if the current light is GREEN
it returns GREEN if the current light is NOT YELLOW AND the current light is NOT GREEN
I add an if statement for when the timer is NOT done and the light is RED, to make it clearer
1def show(current_light, timer_done): 2 if not timer_done: 3 if current_light == 'YELLOW': 4 return 'YELLOW' 5 if current_light == 'GREEN': 6 return 'GREEN' 7 if current_light == 'RED': 8 return 'RED' 9 10 if current_light == 'YELLOW': 11 return 'RED' 12 13 if current_light == 'GREEN': 14 return 'YELLOW' 15 16 return 'GREEN'the test is still green. The
showfunction returns the current light when the timer is NOT doneI add a return statement to return the current light when the timer is NOT done
1def show(current_light, timer_done): 2 if not timer_done: 3 return current_light 4 if current_light == 'YELLOW': 5 return 'YELLOW' 6 if current_light == 'GREEN': 7 return 'GREEN' 8 if current_light == 'RED': 9 return 'RED' 10 11 if current_light == 'YELLOW': 12 return 'RED' 13 14 if current_light == 'GREEN': 15 return 'YELLOW' 16 17 return 'GREEN'still green.
I remove the other if statements from the one for when the timer is NOT done (lines 4-9) because they are no longer used
1def show(current_light, timer_done): 2 if not timer_done: 3 return current_light 4 5 if current_light == 'YELLOW': 6 return 'RED' 7 8 if current_light == 'GREEN': 9 return 'YELLOW' 10 11 return 'GREEN'I add variables for the colors to use them to remove the repetition of
'YELLOW'and'GREEN'1def show(current_light, timer_done): 2 yellow, green = 'YELLOW', 'GREEN' 3 4 if not timer_done: 5 return current_light 6 7 if current_light == 'YELLOW': 8 return 'RED' 9 10 if current_light == 'GREEN': 11 return 'YELLOW' 12 13 return 'GREEN'I use the new variables to remove the repetition of
'YELLOW'and'GREEN'1def show(current_light, timer_done): 2 yellow, green = 'YELLOW', 'GREEN' 3 4 if not timer_done: 5 return current_light 6 7 # if current_light == 'YELLOW': 8 if current_light == yellow: 9 return 'RED' 10 11 # if current_light == 'GREEN': 12 if current_light == green: 13 # return 'YELLOW' 14 return yellow 15 16 # return 'GREEN' 17 return greenthe test is still green.
I remove the commented lines
1def show(current_light, timer_done): 2 yellow, green = 'YELLOW', 'GREEN' 3 4 if not timer_done: 5 return current_light 6 7 if current_light == yellow: 8 return 'RED' 9 10 if current_light == green: 11 return yellow 12 13 return green
This is what happens when the show function is called
if the timer is NOT done it returns the current light
if the timer is done
it returns RED if the current light is YELLOW
it returns YELLOW if the current light is GREEN
it returns GREEN if the current light is NOT YELLOW AND the current light is NOT GREEN
test_red_traffic_light_w_walk
The inputs for the Traffic Light up till now are
did the person push the walk button?
what color is the light now?
is the timer done?
which gives this truth table
current light |
timer |
walk button |
show |
|---|---|---|---|
RED |
done |
pushed |
RED |
RED |
done |
NOT pushed |
GREEN |
RED |
NOT done |
pushed |
RED |
RED |
NOT done |
NOT pushed |
RED |
current light |
timer |
walk button |
show |
|---|---|---|---|
YELLOW |
done |
pushed |
RED |
YELLOW |
done |
NOT pushed |
RED |
YELLOW |
NOT done |
pushed |
YELLOW |
YELLOW |
NOT done |
NOT pushed |
YELLOW |
current light |
timer |
walk button |
show |
|---|---|---|---|
GREEN |
done |
pushed |
YELLOW |
GREEN |
done |
NOT pushed |
YELLOW |
GREEN |
NOT done |
pushed |
GREEN |
GREEN |
NOT done |
NOT pushed |
GREEN |
I want the Traffic Light to show WALK when a person can cross the street or NO WALK when a person can NOT cross the street. This means the truth table for if the Traffic Light is RED with the walk sign is
current light |
timer |
walk button |
show |
|---|---|---|---|
RED |
done |
pushed |
RED + WALK |
RED |
done |
NOT pushed |
GREEN + NO WALK |
RED |
NOT done |
pushed |
RED + WALK |
RED |
NOT done |
NOT pushed |
RED + WALK |
RED: make it fail
I add the value for the current_light parameter in the call to the show function for when the light is RED, the timer is done and the walk button is pushed, to make it clearer, then I change the expectation of the first assertion in test_red_traffic_light_w_walk_button
current light |
timer |
walk button |
show |
|---|---|---|---|
RED |
done |
pushed |
RED + WALK |
10 def test_red_traffic_light_w_walk_button(self):
11 self.assertEqual(
12 src.traffic_light.show(
13 current_light=RED,
14 timer_done=True,
15 walk_button=True,
16 ),
17 (RED, 'WALK')
18 )
the terminal is my friend, and shows AssertionError
AssertionError: 'RED' != ('RED', 'WALK')
GREEN: make it pass
I change the return statement for this case, in the show function in traffic_light.py
1def show(
2 current_light='RED', timer_done=False,
3 walk_button=False,
4 ):
5 red, yellow, green = 'RED', 'YELLOW', 'GREEN'
6
7 if not timer_done:
8 return current_light
9
10 if current_light == yellow:
11 return red
12
13 if current_light == green:
14 return yellow
15
16 if walk_button:
17 return red, 'WALK'
18
19 return green
the test passes. This is what happens when the show function is called
if the timer is NOT done it returns the current light
if the timer is done
it returns RED if the current light is YELLOW
it returns YELLOW if the current light is GREEN
if the current light is NOT YELLOW AND the current light is NOT GREEN
it returns
'RED', 'WALK'if the walk button is pushedit returns GREEN if the walk button is NOT pushed
REFACTOR: make it better
I add values for the other parameters, to make it clearer for when the light is RED, the timer is done, and the walk button is pushed, then I change the expectation of the second assertion in test_red_traffic_light_w_walk_button in
test_traffic_light.pycurrent light
timer
walk button
show
RED
done
pushed
RED + WALK
RED
done
NOT pushed
GREEN + NO WALK
10 def test_red_traffic_light_w_walk_button(self): 11 self.assertEqual( 12 src.traffic_light.show( 13 current_light=RED, 14 timer_done=True, 15 walk_button=True, 16 ), 17 (RED, 'WALK') 18 ) 19 20 self.assertEqual( 21 src.traffic_light.show( 22 current_light=RED, 23 timer_done=True, 24 walk_button=False, 25 ), 26 (GREEN, 'NO WALK') 27 )the terminal is my friend, and shows AssertionError
AssertionError: 'GREEN' != ('GREEN', 'NO WALK')I add
'NO WALK'to the return statement for this case intraffic_light.py1def show( 2 current_light='RED', timer_done=False, 3 walk_button=False, 4 ): 5 red, yellow, green = 'RED', 'YELLOW', 'GREEN' 6 7 if not timer_done: 8 return current_light 9 10 if current_light == yellow: 11 return red 12 13 if current_light == green: 14 return yellow 15 16 if walk_button: 17 return red, 'WALK' 18 19 return green, 'NO WALK'the test passes. This is what happens when the
showfunction is calledif the timer is NOT done it returns the current light
if the timer is done
it returns RED if the current light is YELLOW
it returns YELLOW if the current light is GREEN
if the current light is NOT YELLOW AND the current light is NOT GREEN
it returns
'RED', 'WALK'if the walk button is pushedit returns
'GREEN', 'NO WALK'if the walk button is NOT pushed
I change the third assertion for when the light is RED, the timer is NOT done, and the walk button is pushed, in test_red_traffic_light_w_walk_button in
test_traffic_light.pycurrent light
timer
walk button
show
RED
done
pushed
RED + WALK
RED
done
NOT pushed
GREEN + NO WALK
RED
NOT done
pushed
RED + WALK
10 def test_red_traffic_light_w_walk_button(self): 11 self.assertEqual( 12 src.traffic_light.show( 13 current_light=RED, 14 timer_done=True, 15 walk_button=True, 16 ), 17 (RED, 'WALK') 18 ) 19 20 self.assertEqual( 21 src.traffic_light.show( 22 current_light=RED, 23 timer_done=True, 24 walk_button=False, 25 ), 26 (GREEN, 'NO WALK') 27 ) 28 29 self.assertEqual( 30 src.traffic_light.show( 31 current_light=RED, 32 timer_done=False, 33 walk_button=True, 34 ), 35 (RED, 'WALK') 36 )the terminal is my friend, and shows AssertionError
AssertionError: 'RED' != ('RED', 'WALK')I add an if statement for this case to the one for when the timer is NOT done, in
traffic_light.py1def show( 2 current_light='RED', timer_done=False, 3 walk_button=False, 4 ): 5 red, yellow, green = 'RED', 'YELLOW', 'GREEN' 6 7 if not timer_done: 8 if current_light == red: 9 return current_light, 'WALK' 10 return current_light 11 12 if current_light == yellow: 13 return red 14 15 if current_light == green: 16 return yellow 17 18 if walk_button: 19 return red, 'WALK' 20 21 return green, 'NO WALK'the terminal is my friend, and shows AssertionError
AssertionError: ('RED', 'WALK') != 'RED'this time for the next assertion
I add values for the other parameters in the next assertion, to make it clearer for the case where the light is RED, the timer is NOT done, and the walk button is NOT pushed, in test_red_traffic_light_w_walk_button in
test_traffic_light.pycurrent light
timer
walk button
show
RED
done
pushed
RED + WALK
RED
done
NOT pushed
GREEN + NO WALK
RED
NOT done
pushed
RED + WALK
RED
NOT done
NOT pushed
RED + WALK
10 def test_red_traffic_light_w_walk_button(self): 11 self.assertEqual( 12 src.traffic_light.show( 13 current_light=RED, 14 timer_done=True, 15 walk_button=True, 16 ), 17 (RED, 'WALK') 18 ) 19 20 self.assertEqual( 21 src.traffic_light.show( 22 current_light=RED, 23 timer_done=True, 24 walk_button=False, 25 ), 26 (GREEN, 'NO WALK') 27 ) 28 29 self.assertEqual( 30 src.traffic_light.show( 31 current_light=RED, 32 timer_done=False, 33 walk_button=True, 34 ), 35 (RED, 'WALK') 36 ) 37 38 self.assertEqual( 39 src.traffic_light.show( 40 current_light=RED, 41 timer_done=False, 42 walk_button=False, 43 ), 44 (RED, 'WALK') 45 ) 46 47 def test_yellow_traffic_light_w_walk_button(self):the test passes. This is what happens when the
showfunction is calledif the timer is NOT done
it returns
'RED', 'WALK'if the current light is REDit returns the current light if the current light is NOT RED
if the timer is done
it returns RED if the current light is YELLOW
it returns YELLOW if the current light is GREEN
if the current light is NOT YELLOW AND the current light is NOT GREEN
it returns
'RED', 'WALK'if the walk button is pushedit returns
'GREEN', 'NO WALK'if the walk button is NOT pushed
I change the name of the test from test_red_traffic_light_w_walk_button to test_red_traffic_light_w_walk
8class TestTrafficLight(unittest.TestCase): 9 10 def test_red_traffic_light_w_walk(self): 11 self.assertEqual( 12 src.traffic_light.show( 13 current_light=RED, 14 timer_done=True, 15 walk_button=True, 16 ), 17 (RED, 'WALK') 18 )
test_yellow_traffic_light_w_walk
The truth table for if the Traffic Light is YELLOW with the walk sign is
current light |
timer |
walk button |
show |
|---|---|---|---|
YELLOW |
done |
pushed |
RED + WALK |
YELLOW |
done |
NOT pushed |
RED + WALK |
YELLOW |
NOT done |
pushed |
YELLOW + NO WALK |
YELLOW |
NOT done |
NOT pushed |
YELLOW + NO WALK |
I change the expectation of the first assertion for when the light is YELLOW, the timer is done and the walk button is pushed, in test_yellow_traffic_light_w_walk_button
current light
timer
walk button
show
YELLOW
done
pushed
RED + WALK
47 def test_yellow_traffic_light_w_walk_button(self): 48 self.assertEqual( 49 src.traffic_light.show( 50 current_light=YELLOW, 51 timer_done=True, 52 walk_button=True, 53 ), 54 (RED, 'WALK') 55 )the terminal is my friend, and shows AssertionError
AssertionError: 'RED' != ('RED', 'WALK')I add
'WALK'to the if statement for this case, intraffic_light.py1def show( 2 current_light='RED', timer_done=False, 3 walk_button=False, 4 ): 5 red, yellow, green = 'RED', 'YELLOW', 'GREEN' 6 7 if not timer_done: 8 if current_light == red: 9 return current_light, 'WALK' 10 return current_light 11 12 if current_light == yellow: 13 return red, 'WALK' 14 15 if current_light == green: 16 return yellow 17 18 if walk_button: 19 return red, 'WALK' 20 21 return green, 'NO WALK'the terminal is my friend, and shows AssertionError
AssertionError: ('RED', 'WALK') != 'RED'I have to make the same change to the expectation of the next assertion
I change the second assertion which is for when the light is YELLOW, the timer is done and the walk button is NOT pushed, in test_yellow_traffic_light_w_walk_button in
test_traffic_light.pycurrent light
timer
walk button
show
YELLOW
done
pushed
RED + WALK
YELLOW
done
NOT pushed
RED + WALK
47 def test_yellow_traffic_light_w_walk_button(self): 48 self.assertEqual( 49 src.traffic_light.show( 50 current_light=YELLOW, 51 timer_done=True, 52 walk_button=True, 53 ), 54 (RED, 'WALK') 55 ) 56 57 self.assertEqual( 58 src.traffic_light.show( 59 current_light=YELLOW, 60 timer_done=True, 61 walk_button=False, 62 ), 63 (RED, 'WALK') 64 )the test passes. This is what happens when the
showfunction is calledif the timer is NOT done
it returns
'RED', 'WALK'if the current light is REDit returns the current light if the current light is NOT RED
if the timer is done
it returns
'RED', 'WALK'if the current light is YELLOWit returns YELLOW if the current light is GREEN
if the current light is NOT YELLOW AND the current light is NOT GREEN
it returns
'RED', 'WALK'if the walk button is pushedit returns
'GREEN', 'NO WALK'if the walk button is NOT pushed
I change the third assertion, which is for when the light is YELLOW, the timer is NOT done and the walk button is pushed
current light
timer
walk button
show
YELLOW
done
pushed
RED + WALK
YELLOW
done
NOT pushed
RED + WALK
YELLOW
NOT done
pushed
YELLOW + NO WALK
47 def test_yellow_traffic_light_w_walk_button(self): 48 self.assertEqual( 49 src.traffic_light.show( 50 current_light=YELLOW, 51 timer_done=True, 52 walk_button=True, 53 ), 54 (RED, 'WALK') 55 ) 56 57 self.assertEqual( 58 src.traffic_light.show( 59 current_light=YELLOW, 60 timer_done=True, 61 walk_button=False, 62 ), 63 (RED, 'WALK') 64 ) 65 66 self.assertEqual( 67 src.traffic_light.show( 68 current_light=YELLOW, 69 timer_done=False, 70 walk_button=True, 71 ), 72 (YELLOW, 'NO WALK') 73 )the terminal is my friend, and shows AssertionError
AssertionError: 'YELLOW' != ('YELLOW', 'NO WALK')I add an if statement to the one for when the timer is NOT done in
traffic_light.py1def show( 2 current_light='RED', timer_done=False, 3 walk_button=False, 4 ): 5 red, yellow, green = 'RED', 'YELLOW', 'GREEN' 6 7 if not timer_done: 8 if current_light == red: 9 return current_light, 'WALK' 10 if current_light == yellow: 11 return current_light, 'NO WALK' 12 return current_light 13 14 if current_light == yellow: 15 return red, 'WALK' 16 17 if current_light == green: 18 return yellow 19 20 if walk_button: 21 return red, 'WALK' 22 23 return green, 'NO WALK'the terminal is my friend, and shows AssertionError
AssertionError: ('YELLOW', 'NO WALK') != 'YELLOW'I have to make the same change to the next assertion in the test
I change the last assertion, which is for when the light is YELLOW, the timer is NOT done, and the walk button is NOT pushed, in test_yellow_traffic_light_w_walk_button in
test_traffic_light.pycurrent light
timer
walk button
show
YELLOW
done
pushed
RED + WALK
YELLOW
done
NOT pushed
RED + WALK
YELLOW
NOT done
pushed
YELLOW + NO WALK
YELLOW
NOT done
NOT pushed
YELLOW + NO WALK
47 def test_yellow_traffic_light_w_walk_button(self): 48 self.assertEqual( 49 src.traffic_light.show( 50 current_light=YELLOW, 51 timer_done=True, 52 walk_button=True, 53 ), 54 (RED, 'WALK') 55 ) 56 57 self.assertEqual( 58 src.traffic_light.show( 59 current_light=YELLOW, 60 timer_done=True, 61 walk_button=False, 62 ), 63 (RED, 'WALK') 64 ) 65 66 self.assertEqual( 67 src.traffic_light.show( 68 current_light=YELLOW, 69 timer_done=False, 70 walk_button=True, 71 ), 72 (YELLOW, 'NO WALK') 73 ) 74 75 self.assertEqual( 76 src.traffic_light.show( 77 current_light=YELLOW, 78 timer_done=False, 79 walk_button=False, 80 ), 81 (YELLOW, 'NO WALK') 82 ) 83 84 def test_green_traffic_light_w_walk_button(self):the test passes. This is what happens when the
showfunction is calledif the timer is NOT done
it returns
'RED', 'WALK'if the current light is REDit returns
'YELLOW', 'NO WALK'if the current light is YELLOWit returns the current light if the current light is NOT RED AND NOT YELLOW
if the timer is done
it returns
'RED', 'WALK'if the current light is YELLOWit returns YELLOW if the current light is GREEN
if the current light is NOT YELLOW AND the current light is NOT GREEN
it returns
'RED', 'WALK'if the walk button is pushedit returns
'GREEN', 'NO WALK'if the walk button is NOT pushed
I change the name of the test from test_yellow_traffic_light_w_walk_button to test_yellow_traffic_light_w_walk
38 self.assertEqual( 39 src.traffic_light.show( 40 current_light=RED, 41 timer_done=False, 42 walk_button=False, 43 ), 44 (RED, 'WALK') 45 ) 46 47 def test_yellow_traffic_light_w_walk(self): 48 self.assertEqual( 49 src.traffic_light.show( 50 current_light=YELLOW, 51 timer_done=True, 52 walk_button=True, 53 ), 54 (RED, 'WALK') 55 )
test_green_traffic_light_w_walk
The truth table for if the Traffic Light is GREEN with the walk sign is
current light |
timer |
walk button |
show |
|---|---|---|---|
GREEN |
done |
pushed |
YELLOW + NO WALK |
GREEN |
done |
NOT pushed |
YELLOW + NO WALK |
GREEN |
NOT done |
pushed |
GREEN + NO WALK |
GREEN |
NOT done |
NOT pushed |
GREEN + NO WALK |
I change the expectation of the first assertion for if the light is GREEN, the timer is done, and the walk button is pushed, in test_green_traffic_light_w_walk_button
current light
timer
walk button
show
GREEN
done
pushed
YELLOW + NO WALK
84 def test_green_traffic_light_w_walk_button(self): 85 self.assertEqual( 86 src.traffic_light.show( 87 current_light=GREEN, 88 timer_done=True, 89 walk_button=True, 90 ), 91 (YELLOW, 'NO WALK') 92 )the terminal is my friend, and shows AssertionError
AssertionError: 'YELLOW' != ('YELLOW', 'NO WALK')I add
'NO WALK'to the if statement for when the current light is GREEN1def show( 2 current_light='RED', timer_done=False, 3 walk_button=False, 4 ): 5 red, yellow, green = 'RED', 'YELLOW', 'GREEN' 6 7 if not timer_done: 8 if current_light == red: 9 return current_light, 'WALK' 10 if current_light == yellow: 11 return current_light, 'NO WALK' 12 return current_light 13 14 if current_light == yellow: 15 return red, 'WALK' 16 17 if current_light == green: 18 return yellow, 'NO WALK' 19 20 if walk_button: 21 return red, 'WALK' 22 23 return green, 'NO WALK'the terminal is my friend, and shows AssertionError
AssertionError: ('YELLOW', 'NO WALK') != 'YELLOW'I have to make the same change to the next assertion
I change the second assertion, which is for when the light is GREEN, the timer is done, and the walk button is NOT pushed, in test_green_traffic_light_w_walk_button in
test_traffic_light.pycurrent light
timer
walk button
show
GREEN
done
pushed
YELLOW + NO WALK
GREEN
done
NOT pushed
YELLOW + NO WALK
84 def test_green_traffic_light_w_walk_button(self): 85 self.assertEqual( 86 src.traffic_light.show( 87 current_light=GREEN, 88 timer_done=True, 89 walk_button=True, 90 ), 91 (YELLOW, 'NO WALK') 92 ) 93 94 self.assertEqual( 95 src.traffic_light.show( 96 current_light=GREEN, 97 timer_done=True, 98 walk_button=False, 99 ), 100 (YELLOW, 'NO WALK') 101 )the test passes. This is what happens when the
showfunction is calledif the timer is NOT done
it returns
'RED', 'WALK'if the current light is REDit returns
'YELLOW', 'NO WALK'if the current light is YELLOWit returns the current light if the current light is NOT RED AND NOT YELLOW
if the timer is done
it returns
'RED', 'WALK'if the current light is YELLOWit returns
'YELLOW', 'NO WALK'if the current light is GREENif the current light is NOT YELLOW AND the current light is NOT GREEN
it returns
'RED', 'WALK'if the walk button is pushedit returns
'GREEN', 'NO WALK'if the walk button is NOT pushed
I change the third assertion, which is for when the light is GREEN, the timer is NOT done, and the walk button is pushed
current light
timer
walk button
show
GREEN
done
pushed
YELLOW + NO WALK
GREEN
done
NOT pushed
YELLOW + NO WALK
GREEN
NOT done
pushed
GREEN + NO WALK
84 def test_green_traffic_light_w_walk_button(self): 85 self.assertEqual( 86 src.traffic_light.show( 87 current_light=GREEN, 88 timer_done=True, 89 walk_button=True, 90 ), 91 (YELLOW, 'NO WALK') 92 ) 93 94 self.assertEqual( 95 src.traffic_light.show( 96 current_light=GREEN, 97 timer_done=True, 98 walk_button=False, 99 ), 100 (YELLOW, 'NO WALK') 101 ) 102 103 self.assertEqual( 104 src.traffic_light.show( 105 current_light=GREEN, 106 timer_done=False, 107 walk_button=True, 108 ), 109 (GREEN, 'NO WALK') 110 )the terminal is my friend, and shows AssertionError
AssertionError: 'GREEN' != ('GREEN', 'NO WALK')I change the return statement of the if statement for when the timer is NOT done in the
showfunction intraffic_light.py1def show( 2 current_light='RED', timer_done=False, 3 walk_button=False, 4 ): 5 red, yellow, green = 'RED', 'YELLOW', 'GREEN' 6 7 if not timer_done: 8 if current_light == red: 9 return current_light, 'WALK' 10 if current_light == yellow: 11 return current_light, 'NO WALK' 12 return current_light, 'NO WALK' 13 14 if current_light == yellow: 15 return red, 'WALK' 16 17 if current_light == green: 18 return yellow, 'NO WALK' 19 20 if walk_button: 21 return red, 'WALK' 22 23 return green, 'NO WALK'the terminal is my friend, and shows AssertionError
AssertionError: ('GREEN', 'NO WALK') != 'GREEN'the
showfunction now returns('GREEN', 'NO WALK')and the next assertion expects'GREEN'. I have to make the same change in the next assertionI change the last assertion, which is for when the light is GREEN, the timer is NOT done, and the walk button is NOT pushed, in test_green_traffic_light_w_walk_button in
test_traffic_light.pycurrent light
timer
walk button
show
GREEN
done
pushed
YELLOW + NO WALK
GREEN
done
NOT pushed
YELLOW + NO WALK
GREEN
NOT done
pushed
GREEN + NO WALK
GREEN
NOT done
NOT pushed
GREEN + NO WALK
84 def test_green_traffic_light_w_walk_button(self): 85 self.assertEqual( 86 src.traffic_light.show( 87 current_light=GREEN, 88 timer_done=True, 89 walk_button=True, 90 ), 91 (YELLOW, 'NO WALK') 92 ) 93 94 self.assertEqual( 95 src.traffic_light.show( 96 current_light=GREEN, 97 timer_done=True, 98 walk_button=False, 99 ), 100 (YELLOW, 'NO WALK') 101 ) 102 103 self.assertEqual( 104 src.traffic_light.show( 105 current_light=GREEN, 106 timer_done=False, 107 walk_button=True, 108 ), 109 (GREEN, 'NO WALK') 110 ) 111 112 self.assertEqual( 113 src.traffic_light.show( 114 current_light=GREEN, 115 timer_done=False, 116 walk_button=False, 117 ), 118 (GREEN, 'NO WALK') 119 ) 120 121 122# Exceptions seenthe test passes. This is what happens when the
showfunction is calledif the timer is NOT done
it returns
'RED', 'WALK'if the current light is REDit returns
'YELLOW', 'NO WALK'if the current light is YELLOWit returns the current light,
'NO WALK'if the current light is NOT RED AND NOT YELLOW
if the timer is done
it returns
'RED', 'WALK'if the current light is YELLOWit returns
'YELLOW', 'NO WALK'if the current light is GREENif the current light is NOT YELLOW AND the current light is NOT GREEN
it returns
'RED', 'WALK'if the walk button is pushedit returns
'GREEN', 'NO WALK'if the walk button is NOT pushed
I change the name of the test from test_green_traffic_light_w_walk_button to test_green_traffic_light_w_walk
75 self.assertEqual( 76 src.traffic_light.show( 77 current_light=YELLOW, 78 timer_done=False, 79 walk_button=False, 80 ), 81 (YELLOW, 'NO WALK') 82 ) 83 84 def test_green_traffic_light_w_walk(self): 85 self.assertEqual( 86 src.traffic_light.show( 87 current_light=GREEN, 88 timer_done=True, 89 walk_button=True, 90 ), 91 (YELLOW, 'NO WALK') 92 )
I add more global variables to
test_traffic_light.pyto use them to remove repetition from the tests1import src.traffic_light 2import unittest 3 4 5RED, YELLOW, GREEN = 'RED', 'YELLOW', 'GREEN' 6NO_WALK = 'NO WALK' 7WALK = (RED, 'WALK') 8YELLOW_NO_WALK = (YELLOW, NO_WALK) 9GREEN_NO_WALK = (GREEN, NO_WALK) 10 11 12class TestTrafficLight(unittest.TestCase):I use the
GREEN_NO_WALKglobal variable for(GREEN, 'NO WALK')in the second assertion of test_red_traffic_light_w_walk14 def test_red_traffic_light_w_walk(self): 15 self.assertEqual( 16 src.traffic_light.show( 17 current_light=RED, 18 timer_done=True, 19 walk_button=True, 20 ), 21 (RED, 'WALK') 22 ) 23 24 self.assertEqual( 25 src.traffic_light.show( 26 current_light=RED, 27 timer_done=True, 28 walk_button=False, 29 ), 30 # (GREEN, 'NO WALK') 31 GREEN_NO_WALK 32 )the test is still green.
I use the
WALKglobal variable for(RED, 'WALK')in test_red_traffic_light_w_walk14 def test_red_traffic_light_w_walk(self): 15 self.assertEqual( 16 src.traffic_light.show( 17 current_light=RED, 18 timer_done=True, 19 walk_button=True, 20 ), 21 # (RED, 'WALK') 22 WALK 23 ) 24 25 self.assertEqual( 26 src.traffic_light.show( 27 current_light=RED, 28 timer_done=True, 29 walk_button=False, 30 ), 31 # (GREEN, 'NO WALK') 32 GREEN_NO_WALK 33 ) 34 35 self.assertEqual( 36 src.traffic_light.show( 37 current_light=RED, 38 timer_done=False, 39 walk_button=True, 40 ), 41 # (RED, 'WALK') 42 WALK 43 ) 44 45 self.assertEqual( 46 src.traffic_light.show( 47 current_light=RED, 48 timer_done=False, 49 walk_button=False, 50 ), 51 # (RED, 'WALK') 52 WALK 53 ) 54 55 def test_yellow_traffic_light_w_walk(self):still green.
I remove the commented lines
14 def test_red_traffic_light_w_walk(self): 15 self.assertEqual( 16 src.traffic_light.show( 17 current_light=RED, 18 timer_done=True, 19 walk_button=True, 20 ), 21 WALK 22 ) 23 24 self.assertEqual( 25 src.traffic_light.show( 26 current_light=RED, 27 timer_done=True, 28 walk_button=False, 29 ), 30 GREEN_NO_WALK 31 ) 32 33 self.assertEqual( 34 src.traffic_light.show( 35 current_light=RED, 36 timer_done=False, 37 walk_button=True, 38 ), 39 WALK 40 ) 41 42 self.assertEqual( 43 src.traffic_light.show( 44 current_light=RED, 45 timer_done=False, 46 walk_button=False, 47 ), 48 WALK 49 ) 50 51 def test_yellow_traffic_light_w_walk(self):I use the
WALKglobal variable for(RED, 'WALK')in test_yellow_traffic_light_w_walk51 def test_yellow_traffic_light_w_walk(self): 52 self.assertEqual( 53 src.traffic_light.show( 54 current_light=YELLOW, 55 timer_done=True, 56 walk_button=True, 57 ), 58 # (RED, 'WALK') 59 WALK 60 ) 61 62 self.assertEqual( 63 src.traffic_light.show( 64 current_light=YELLOW, 65 timer_done=True, 66 walk_button=False, 67 ), 68 # (RED, 'WALK') 69 WALK 70 )green.
I use the
YELLOW_NO_WALKglobal variable for(YELLOW, 'NO WALK')in test_yellow_traffic_light_w_walk51 def test_yellow_traffic_light_w_walk(self): 52 self.assertEqual( 53 src.traffic_light.show( 54 current_light=YELLOW, 55 timer_done=True, 56 walk_button=True, 57 ), 58 # (RED, 'WALK') 59 WALK 60 ) 61 62 self.assertEqual( 63 src.traffic_light.show( 64 current_light=YELLOW, 65 timer_done=True, 66 walk_button=False, 67 ), 68 # (RED, 'WALK') 69 WALK 70 ) 71 72 self.assertEqual( 73 src.traffic_light.show( 74 current_light=YELLOW, 75 timer_done=False, 76 walk_button=True, 77 ), 78 # (YELLOW, 'NO WALK') 79 YELLOW_NO_WALK 80 ) 81 82 self.assertEqual( 83 src.traffic_light.show( 84 current_light=YELLOW, 85 timer_done=False, 86 walk_button=False, 87 ), 88 # (YELLOW, 'NO WALK') 89 YELLOW_NO_WALK 90 )still green.
I remove the commented lines from test_yellow_traffic_light_w_walk
51 def test_yellow_traffic_light_w_walk(self): 52 self.assertEqual( 53 src.traffic_light.show( 54 current_light=YELLOW, 55 timer_done=True, 56 walk_button=True, 57 ), 58 WALK 59 ) 60 61 self.assertEqual( 62 src.traffic_light.show( 63 current_light=YELLOW, 64 timer_done=True, 65 walk_button=False, 66 ), 67 WALK 68 ) 69 70 self.assertEqual( 71 src.traffic_light.show( 72 current_light=YELLOW, 73 timer_done=False, 74 walk_button=True, 75 ), 76 YELLOW_NO_WALK 77 ) 78 79 self.assertEqual( 80 src.traffic_light.show( 81 current_light=YELLOW, 82 timer_done=False, 83 walk_button=False, 84 ), 85 YELLOW_NO_WALK 86 ) 87 88 def test_green_traffic_light_w_walk(self):I use the
YELLOW_NO_WALKglobal variable for(YELLOW, 'NO WALK')in test_green_traffic_light_w_walk88 def test_green_traffic_light_w_walk(self): 89 self.assertEqual( 90 src.traffic_light.show( 91 current_light=GREEN, 92 timer_done=True, 93 walk_button=True, 94 ), 95 # (YELLOW, 'NO WALK') 96 YELLOW_NO_WALK 97 ) 98 99 self.assertEqual( 100 src.traffic_light.show( 101 current_light=GREEN, 102 timer_done=True, 103 walk_button=False, 104 ), 105 # (YELLOW, 'NO WALK') 106 YELLOW_NO_WALK 107 )green.
I use the
GREEN_NO_WALKglobal variable for(GREEN, 'NO WALK')in test_green_traffic_light_w_walk88 def test_green_traffic_light_w_walk(self): 89 self.assertEqual( 90 src.traffic_light.show( 91 current_light=GREEN, 92 timer_done=True, 93 walk_button=True, 94 ), 95 # (YELLOW, 'NO WALK') 96 YELLOW_NO_WALK 97 ) 98 99 self.assertEqual( 100 src.traffic_light.show( 101 current_light=GREEN, 102 timer_done=True, 103 walk_button=False, 104 ), 105 # (YELLOW, 'NO WALK') 106 YELLOW_NO_WALK 107 ) 108 109 self.assertEqual( 110 src.traffic_light.show( 111 current_light=GREEN, 112 timer_done=False, 113 walk_button=True, 114 ), 115 # (GREEN, 'NO WALK') 116 GREEN_NO_WALK 117 ) 118 119 self.assertEqual( 120 src.traffic_light.show( 121 current_light=GREEN, 122 timer_done=False, 123 walk_button=False, 124 ), 125 # (GREEN, 'NO WALK') 126 GREEN_NO_WALK 127 )still green.
I remove the commented lines from test_green_traffic_light_w_walk
88 def test_green_traffic_light_w_walk(self): 89 self.assertEqual( 90 src.traffic_light.show( 91 current_light=GREEN, 92 timer_done=True, 93 walk_button=True, 94 ), 95 YELLOW_NO_WALK 96 ) 97 98 self.assertEqual( 99 src.traffic_light.show( 100 current_light=GREEN, 101 timer_done=True, 102 walk_button=False, 103 ), 104 YELLOW_NO_WALK 105 ) 106 107 self.assertEqual( 108 src.traffic_light.show( 109 current_light=GREEN, 110 timer_done=False, 111 walk_button=True, 112 ), 113 GREEN_NO_WALK 114 ) 115 116 self.assertEqual( 117 src.traffic_light.show( 118 current_light=GREEN, 119 timer_done=False, 120 walk_button=False, 121 ), 122 GREEN_NO_WALK 123 ) 124 125 126# Exceptions seen
REFACTOR: make it better
I add variables for
'WALK'and'NO WALK'to theshowfunction intraffic_light.py1def show( 2 current_light='RED', timer_done=False, 3 walk_button=False, 4 ): 5 red, yellow, green = 'RED', 'YELLOW', 'GREEN' 6 walk = (red, 'WALK') 7 no_walk = 'NO WALK'I use the new variables to remove repetition
1def show( 2 current_light='RED', timer_done=False, 3 walk_button=False, 4 ): 5 red, yellow, green = 'RED', 'YELLOW', 'GREEN' 6 walk = (red, 'WALK') 7 no_walk = 'NO WALK' 8 9 if not timer_done: 10 if current_light == red: 11 # return current_light, 'WALK' 12 return walk 13 if current_light == yellow: 14 # return current_light, 'NO WALK' 15 return current_light, no_walk 16 # return current_light, 'NO WALK' 17 return current_light, no_walk 18 19 if current_light == yellow: 20 # return red, 'WALK' 21 return walk 22 23 if current_light == green: 24 # return yellow, 'NO WALK' 25 return yellow, no_walk 26 27 if walk_button: 28 # return red, 'WALK' 29 return walk 30 31 # return green, 'NO WALK' 32 return green, no_walkthe tests are still green.
I write a new if statement with an else clause, that covers the 3 cases when the timer is NOT done
9 if not timer_done: 10 if current_light != red: 11 return current_light, no_walk 12 else: 13 return walk 14 if current_light == red: 15 # return current_light, 'WALK' 16 return walk 17 if current_light == yellow: 18 # return current_light, 'NO WALK' 19 return current_light, no_walk 20 # return current_light, 'NO WALK' 21 return current_light, no_walkstill green.
I write out the if statement for when the light is RED and the timer is done, to make it clearer
23 if current_light == yellow: 24 # return red, 'WALK' 25 return walk 26 27 if current_light == green: 28 # return yellow, 'NO WALK' 29 return yellow, no_walk 30 31 # if walk_button: 32 # return red, 'WALK' 33 # return walk 34 35 # return green, 'NO WALK' 36 # return green, no_walk 37 38 if current_light == red: 39 if not walk_button: 40 return green, no_walk 41 else: 42 return walkgreen.
the
walkvariable which is'RED', 'WALK', happens 3 times in the function, I add a return statement to make it the default state of the light38 if current_light == red: 39 if not walk_button: 40 return green, no_walk 41 else: 42 return walk 43 44 return walkstill green. This means if none of the conditions in the
showfunction are met, the light stays RED and shows'WALK'I no longer need the else clause for when the walk button is pushed because it returns the default state (
'RED', 'WALK') when the list is RED and the timer is done. I comment it out38 if current_light == red: 39 if not walk_button: 40 return green, no_walk 41 # else: 42 # return walk 43 44 return walkthe tests are still green.
I rewrite the if statement for when the current light is red AND the timer is done AND the walk button is pushed with Logical Conjunction(AND)
38 # if current_light == red: 39 # if not walk_button: 40 if current_light == red and not walk_button: 41 return green, no_walk 42 # else: 43 # return walk 44 45 return walkstill green.
I no longer need the if statement for YELLOW because it returns the default state (
'RED', 'WALK') when the timer is done. I comment it out23 # if current_light == yellow: 24 # return red, 'WALK' 25 # return walk 26 27 if current_light == green: 28 # return yellow, 'NO WALK' 29 return yellow, no_walk 30 31 # if walk_button: 32 # return red, 'WALK' 33 # return walk 34 35 # return green, 'NO WALK' 36 # return green, no_walk 37 38 if current_light == red: 39 if not walk_button: 40 return green, no_walk 41 # else: 42 # return walk 43 44 return walkgreen. Why does this work?
I add an if statement for when the timer is done to make it clearer
23 # if current_light == yellow: 24 # return red, 'WALK' 25 # return walk 26 27 if timer_done: 28 if current_light == green: 29 # return yellow, 'NO WALK' 30 return yellow, no_walk 31 32 # if walk_button: 33 # return red, 'WALK' 34 # return walk 35 36 # return green, 'NO WALK' 37 # return green, no_walk 38 39 # if current_light == red: 40 # if not walk_button: 41 if current_light == red and not walk_button: 42 return green, no_walk 43 # else: 44 # return walk 45 46 return walkstill green.
I no longer need the else clause for when the current light is NOT RED and the timer is NOT done because it returns the default state (
'RED', 'WALK') . I comment it out and the other if statements below it to make sure they are not run9 if not timer_done: 10 if current_light != red: 11 return current_light, no_walk 12 # else: 13 # return walk 14 # if current_light == red: 15 # return current_light, 'WALK' 16 # return walk 17 # if current_light == yellow: 18 # return current_light, 'NO WALK' 19 # return current_light, no_walk 20 # return current_light, 'NO WALK' 21 # return current_light, no_walk 22 23 # if current_light == yellow: 24 # return red, 'WALK' 25 # return walkthe tests are still green.
I use Logical Conjunction(AND) to change the if statement for when the current light is NOT red AND the timer is NOT done
1def show( 2 current_light='RED', timer_done=False, 3 walk_button=False, 4 ): 5 red, yellow, green = 'RED', 'YELLOW', 'GREEN' 6 walk = (red, 'WALK') 7 no_walk = 'NO WALK' 8 9 # if not timer_done: 10 # if current_light != red: 11 if not timer_done and current_light != red: 12 return current_light, no_walk 13 # else:still green.
I remove the commented lines
1def show( 2 current_light='RED', timer_done=False, 3 walk_button=False, 4 ): 5 red, yellow, green = 'RED', 'YELLOW', 'GREEN' 6 walk = (red, 'WALK') 7 no_walk = 'NO WALK' 8 9 if not timer_done and current_light != red: 10 return current_light, no_walk 11 12 if timer_done: 13 if current_light == green: 14 return yellow, no_walk 15 if current_light == red and not walk_button: 16 return green, no_walk 17 18 return walk
This is what happens when the show function is called
if the timer is NOT done
it returns the current light,
'NO WALK'if the current light is NOT RED
if the timer is done
it returns
'YELLOW', 'NO WALK'if the current light is GREENit returns
'GREEN', 'NO WALK'if the current light is RED AND the walk button is NOT pushed
it returns
'RED', 'WALK'if none of the above conditions are met
The function does not look like the truth table and makes every test pass. There is also a problem with the if statement for when the timer is done AND the current light is NOT RED
if not timer_done and current_light != red:
return current_light, no_walk
What does it return if I call the show function with a color that is NOT RED, YELLOW or GREEN. There is one way to find out …
close the project
I close
test_traffic_light.pyandtraffic_light.pyin the editorI click in the terminal where the tests are running, then use q on the keyboard to leave the tests. The terminal goes back to the command line.
I change directory to the parent of
traffic_lightcd ..the terminal shows
.../pumping_pythonI am back in the
pumping_pythondirectory
review
I ran tests for a Traffic Light that has a timer and a button for people to push when they want to walk. If the inputs are
what color is the light now?
is the timer done?
did the person push the walk button?
then this is the truth table for the Traffic Light
current light |
timer |
walk button |
show |
|---|---|---|---|
RED |
done |
pushed |
RED + WALK |
RED |
done |
NOT pushed |
GREEN + NO WALK |
RED |
NOT done |
pushed |
RED + WALK |
RED |
NOT done |
NOT pushed |
RED + WALK |
current light |
timer |
walk button |
show |
|---|---|---|---|
YELLOW |
done |
pushed |
RED + WALK |
YELLOW |
done |
NOT pushed |
RED + WALK |
YELLOW |
NOT done |
pushed |
YELLOW + NO WALK |
YELLOW |
NOT done |
NOT pushed |
YELLOW + NO WALK |
current light |
timer |
walk button |
show |
|---|---|---|---|
GREEN |
done |
pushed |
YELLOW + NO WALK |
GREEN |
done |
NOT pushed |
YELLOW + NO WALK |
GREEN |
NOT done |
pushed |
GREEN + NO WALK |
GREEN |
NOT done |
NOT pushed |
GREEN + NO WALK |
The Traffic Light only shows 'WALK' when the light is RED.
What if there is an emergency vehicle? If the Traffic Light changes based on the emergency vehicle, its inputs would be
what color is the light now?
is the timer done?
did the person push the walk button?
is there an emergency vehicle?
and the truth table would be
current light |
timer |
walk button |
emergency |
show |
|---|---|---|---|---|
RED |
done |
pushed |
emergency |
RED + NO WALK |
RED |
done |
pushed |
NOT emergency |
GREEN + NO WALK |
RED |
done |
NOT pushed |
emergency |
RED + NO WALK |
RED |
done |
NOT pushed |
NOT emergency |
GREEN + NO WALK |
current light |
timer |
walk button |
emergency |
show |
|---|---|---|---|---|
RED |
NOT done |
pushed |
emergency |
RED + NO WALK |
RED |
NOT done |
pushed |
NOT emergency |
RED + WALK |
RED |
NOT done |
NOT pushed |
emergency |
RED + NO WALK |
RED |
NOT done |
NOT pushed |
NOT emergency |
RED + WALK |
current light |
timer |
walk button |
emergency |
show |
|---|---|---|---|---|
YELLOW |
done |
pushed |
emergency |
RED + NO WALK |
YELLOW |
done |
pushed |
NOT emergency |
RED + WALK |
YELLOW |
done |
NOT pushed |
emergency |
RED + NO WALK |
YELLOW |
done |
NOT pushed |
NOT emergency |
RED + WALK |
current light |
timer |
walk button |
emergency |
show |
|---|---|---|---|---|
YELLOW |
NOT done |
pushed |
emergency |
RED + NO WALK |
YELLOW |
NOT done |
pushed |
NOT emergency |
YELLOW + NO WALK |
YELLOW |
NOT done |
NOT pushed |
emergency |
RED + NO WALK |
YELLOW |
NOT done |
NOT pushed |
NOT emergency |
YELLOW + NO WALK |
current light |
timer |
walk button |
emergency |
show |
|---|---|---|---|---|
GREEN |
done |
pushed |
emergency |
YELLOW + NO WALK |
GREEN |
done |
pushed |
NOT emergency |
YELLOW + NO WALK |
GREEN |
done |
NOT pushed |
emergency |
YELLOW + NO WALK |
GREEN |
done |
NOT pushed |
NOT emergency |
YELLOW + NO WALK |
current light |
timer |
walk button |
emergency |
show |
|---|---|---|---|---|
GREEN |
NOT done |
pushed |
emergency |
YELLOW + NO WALK |
GREEN |
NOT done |
pushed |
NOT emergency |
GREEN + NO WALK |
GREEN |
NOT done |
NOT pushed |
emergency |
YELLOW + NO WALK |
GREEN |
NOT done |
NOT pushed |
NOT emergency |
GREEN + NO WALK |
code from the chapter
what is next?
you 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.