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_light

  • I open a terminal

  • I use uv to make a directory for the project and initialize it

    uv init traffic_light
    

    the 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 src
    

    the terminal goes back to the command line.

  • I use the mv program to change the name of main.py to traffic_light.py and move it to the src folder

    mv main.py src/traffic_light.py
    
    Move-Item main.py src/traffic_light.py
    

    the terminal goes back to the command line.

  • I make a directory for the tests

    mkdir tests
    

    the terminal goes back to the command line.

  • I make the tests directory a Python package

    Danger

    use 2 underscores (__) before and after init for __init__.py not _init_.py

    touch tests/__init__.py
    
    New-Item tests/__init__.py
    

    the terminal goes back to the command line.

  • I make a Python file for the tests in the tests directory

    touch tests/test_traffic_light.py
    
    New-Item tests/test_traffic_light.py
    

    the terminal goes back to the command line.

  • I open test_traffic_light.py in 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.py
    

    Visual Studio Code opens test_traffic_light.py in the editor

  • I add the first failing test to test_traffic_light.py

    1import 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.txt
    

    the terminal goes back to the command line.

  • I add pytest-watcher to the requirements file

    echo "pytest-watcher" >> requirements.txt
    

    the terminal goes back to the command line.

  • I install the Python packages that I wrote in the requirements file

    uv add --requirement requirements.txt
    

    the terminal shows that it installed the Python packages

  • I use tree to look at the structure of the project

    tree
    

    the terminal shows

    .
    ├── README.md
    ├── pyproject.toml
    ├── requirements.txt
    ├── src
       └── traffic_light.py
    ├── tests
       ├── __init__.py
       └── test_traffic_light.py
    └── uv.lock
    
  • I use pytest-watcher to run the tests automatically

    uv run pytest-watcher . --now
    

    the 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 ============================
    

    because True is NOT False

    if the terminal does not show the same error, then check

    • if your tests/__init__.py has two underscores (__) before and after init for __init__.py not _init_.py

    • if you ran echo "pytest-watcher" >> requirements.txt, to add pytest-watcher to the requirements file

    fix those errors and try to run uv run pytest-watcher . --now again

  • I add AssertionError to the list of Exceptions seen in test_traffic_light.py

     4class TestTrafficLight(unittest.TestCase):
     5
     6    def test_failure(self):
     7        self.assertFalse(True)
     8
     9
    10# Exceptions seen
    11# AssertionError
    
  • then 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# NameError
    
  • I add an import statement at the top of the file so that I can test traffic_light.py from the src folder

    1import 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.py in the src folder does not have anything named show in it

    If you get ModuleNotFoundError

    ModuleNotFoundError: No module named 'src'
    

    check if you have __init__.py in the tests folder with underscores (__) before and after init for __init__.py not _init_.py, then add ModuleNotFoundError to the list of Exceptions seen

  • I add AttributeError to the list of Exceptions seen

    16# Exceptions seen
    17# AssertionError
    18# NameError
    19# AttributeError
    
  • I use the Explorer to open traffic_light.py from the src folder in the editor

  • I add a function to traffic_light.py

    1def show():
    2    return None
    

    the terminal is my friend, and shows TypeError

    TypeError: show() got an unexpected keyword argument 'current_light'
    

    because the test called the show function with two keyword arguments and this definition only takes calls with 0 arguments

  • I add TypeError to the list of Exceptions seen in test_traffic_light.py

    16# Exceptions seen
    17# AssertionError
    18# NameError
    19# AttributeError
    20# TypeError
    
  • I add the keyword argument to the function in traffic_light.py

    1def show(current_light):
    2    return None
    

    the terminal is my friend, and shows TypeError

    TypeError: show() got an unexpected keyword argument 'timer_done'
    

    because the test called the show function with two keyword arguments and this definition only takes calls with 1 input

  • I add timer_done to the function signature

    1def show(current_light, timer_done):
    2    return None
    

    the terminal is my friend, and shows AssertionError

    AssertionError: None != 'GREEN'
    

    the show function 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 show function 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.py

    current 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 seen
    

    the terminal is my friend, and shows AssertionError

    AssertionError: 'GREEN' != 'RED'
    

    because the show function returns 'GREEN' and the assertion expects 'RED'

  • I add an if statement for this case, to traffic_light.py

    1def 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 == 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    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) == False is the same as if not bool(something) == True is the same as if not something

  • I 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 show function returns

    • GREEN 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.py

    current 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 seen
    

    the terminal is my friend, and shows AssertionError

    AssertionError: 'RED' != 'YELLOW'
    

    because the show function 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.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    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.py

    current 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 seen
    

    the terminal is my friend, and shows AssertionError

    AssertionError: 'RED' != 'GREEN'
    

    because the show function 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.py

     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        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 show function is called

  • if 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 show function returns the current light when the timer is NOT done

  • I 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 green
    

    the 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_button


So far, the truth table for the Traffic Light is

current light

timer

show

RED

done

GREEN

RED

NOT done

RED

YELLOW

done

RED

YELLOW

NOT done

YELLOW

GREEN

done

YELLOW

GREEN

NOT done

GREEN

I want to add a walk button for a person to push when they want to cross the street. The inputs for the Traffic Light will then be

  • did the person push the walk button?

  • what color is the light now?

  • is the timer done?

and the truth table for if the Traffic Light is RED is

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


RED: make it fail


I add an assertion for when the current light is RED, the timer is done and the walk button is pushed, to test_red_traffic_light in test_traffic_light.py

current light

timer

walk button

show

RED

done

pushed

RED

 7    def test_red_traffic_light(self):
 8        my_expectation = 'RED'
 9        reality = src.traffic_light.show(
10            current_light='RED',
11            timer_done=True,
12            walk_button=True,
13        )
14        self.assertEqual(reality, my_expectation)
15
16        my_expectation = 'GREEN'
17        reality = src.traffic_light.show(
18            current_light='RED',
19            timer_done=True,
20        )
21        self.assertEqual(reality, my_expectation)
22
23        my_expectation = 'RED'
24        reality = src.traffic_light.show(
25            current_light='RED',
26            timer_done=False,
27        )
28        self.assertEqual(reality, my_expectation)
29
30    def test_yellow_traffic_light(self):

the terminal is my friend, and shows TypeError

TypeError: show() got an unexpected keyword argument 'walk_button'

because the show function only takes 2 arguments (current_light and timer_done) and the test called it with 3 arguments (current_light, timer_done and walk_button)


GREEN: make it pass


  • I add a keyword argument to the show function in traffic_light.py

     1def show(current_light, timer_done, walk_button):
     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
    

    the terminal is my friend, and shows 3 failures with TypeError

    FAILED ...test_green_traffic_light - TypeError: show() missing 1 required positional arg...
    FAILED ...test_red_traffic_light - TypeError: show() missing 1 required positional arg...
    FAILED ...test_yellow_traffic_light - TypeError: show() missing 1 required positional arg...
    

    because all the other tests call the show function with two arguments and I changed the function signature to make it expect three. I need to make the third argument a choice.

  • I could add the walk_button parameter to every call to the show function in every test or add a default value for the new keyword argument to make it a choice, NOT a requirement. I make it a choice

    1def show(
    2        current_light, timer_done,
    3        walk_button=False,
    4    ):
    

    the terminal is my friend, and shows AssertionError

    AssertionError: 'GREEN' != 'RED'
    

    yes!

  • I add an if statement for walk_button

     1def show(
     2        current_light, timer_done,
     3        walk_button=False
     4    ):
     5    yellow, green = '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 == True:
    17        return 'RED'
    18
    19    return green
    

    the test passes.


REFACTOR: make it better


  • I use the bool built-in function

    16    # if walk_button == True:
    17    if bool(walk_button) == True:
    18        return 'RED'
    19
    20    return green
    

    the test is still green.

  • I remove == True

    16    # if walk_button == True:
    17    # if bool(walk_button) == True:
    18    if bool(walk_button):
    19        return 'RED'
    20
    21    return green
    

    still green.

  • I remove bool

    16    # if walk_button == True:
    17    # if bool(walk_button) == True:
    18    # if bool(walk_button):
    19    if walk_button:
    20        return 'RED'
    

    green because if bool(something) == True is the same as if something

  • I add a variable to use to remove repetition of 'RED'

    1def show(
    2        current_light, timer_done,
    3        walk_button=False
    4    ):
    5    red, yellow, green = 'RED', 'YELLOW', 'GREEN'
    6
    7    if not timer_done:
    
  • I use the variable to remove repetition of 'RED'

     1def show(
     2        current_light, timer_done,
     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        return red
    13
    14    if current_light == green:
    15        return 'YELLOW'
    16
    17    # if walk_button == True:
    18    # if bool(walk_button) == True:
    19    # if bool(walk_button):
    20    if walk_button:
    21        # return 'RED'
    22        return red
    23
    24    return green
    

    still green.

  • I remove the commented lines

     1def show(
     2        current_light, timer_done,
     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
    18
    19    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

      • if the current light is NOT YELLOW AND the current light is NOT GREEN

        • it returns RED if the walk button is pushed

        • it returns GREEN if the walk button is NOT pushed

  • I do not need to do anything to the assertion for when the light is RED, the timer is done and the walk button is NOT pushed

    current light

    timer

    walk button

    show

    RED

    done

    pushed

    RED

    RED

    done

    NOT pushed

    GREEN

    because

    src.traffic_light.show(
        current_light='RED',
        timer_done=True,
    )
    

    is now the same as

    src.traffic_light.show(
        current_light='RED',
        timer_done=True,
        walk_button=False,
    )
    

    since the default value for the walk_button parameter is False. A function uses the default value for a parameter when it is called without the parameter.

  • I add walk_button to the third assertion for when the light is RED, the timer is NOT done and the walk button is pushed

    current light

    timer

    walk button

    show

    RED

    done

    pushed

    RED

    RED

    done

    NOT pushed

    GREEN

    RED

    NOT done

    pushed

    RED

     7    def test_red_traffic_light(self):
     8        my_expectation = 'RED'
     9        reality = src.traffic_light.show(
    10            current_light='RED',
    11            timer_done=True,
    12            walk_button=True,
    13        )
    14        self.assertEqual(reality, my_expectation)
    15
    16        my_expectation = 'GREEN'
    17        reality = src.traffic_light.show(
    18            current_light='RED',
    19            timer_done=True,
    20        )
    21        self.assertEqual(reality, my_expectation)
    22
    23        my_expectation = 'RED'
    24        reality = src.traffic_light.show(
    25            current_light='RED',
    26            timer_done=False,
    27            walk_button=True,
    28        )
    29        self.assertEqual(reality, my_expectation)
    30
    31    def test_yellow_traffic_light(self):
    

    green.

  • I change the expectation to make sure the test works

    23        my_expectation = 'BOOM'
    

    the terminal is my friend, and shows AssertionError

    AssertionError: 'RED' != 'BOOM'
    

    because the show function returned 'RED' and the assertion expects 'BOOM'

  • I change the expectation back

    23        my_expectation = 'RED'
    24        reality = src.traffic_light.show(
    25            current_light='RED',
    26            timer_done=False,
    27            walk_button=True,
    28        )
    29        self.assertEqual(reality, my_expectation)
    30
    31    def test_yellow_traffic_light(self):
    

    the test is green again

  • I add an assertion for when the light is RED, the timer is NOT done and the walk button is NOT pushed

    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

     7    def test_red_traffic_light(self):
     8        my_expectation = 'RED'
     9        reality = src.traffic_light.show(
    10            current_light='RED',
    11            timer_done=True,
    12            walk_button=True,
    13        )
    14        self.assertEqual(reality, my_expectation)
    15
    16        my_expectation = 'GREEN'
    17        reality = src.traffic_light.show(
    18            current_light='RED',
    19            timer_done=True,
    20        )
    21        self.assertEqual(reality, my_expectation)
    22
    23        my_expectation = 'RED'
    24        reality = src.traffic_light.show(
    25            current_light='RED',
    26            timer_done=False,
    27            walk_button=True,
    28        )
    29        self.assertEqual(reality, my_expectation)
    30
    31        reality = src.traffic_light.show(
    32            current_light='RED',
    33            timer_done=False,
    34        )
    35        self.assertEqual(reality, my_expectation)
    36
    37    def test_yellow_traffic_light(self):
    

    green.

  • I add a variable to use to remove repetition of 'RED' from the test

     7    def test_red_traffic_light(self):
     8        red = 'RED'
     9
    10        my_expectation = 'RED'
    
  • I use the red local variable to remove the repetition of 'RED' and my_expectation when its value is 'RED'

     7    def test_red_traffic_light(self):
     8        red = 'RED'
     9
    10        # my_expectation = 'RED'
    11        reality = src.traffic_light.show(
    12            # current_light='RED',
    13            current_light=red,
    14            timer_done=True,
    15            walk_button=True,
    16        )
    17        # self.assertEqual(reality, my_expectation)
    18        self.assertEqual(reality, red)
    19
    20        my_expectation = 'GREEN'
    21        reality = src.traffic_light.show(
    22            # current_light='RED',
    23            current_light=red,
    24            timer_done=True,
    25        )
    26        self.assertEqual(reality, my_expectation)
    27
    28        # my_expectation = 'RED'
    29        reality = src.traffic_light.show(
    30            # current_light='RED',
    31            current_light=red,
    32            timer_done=False,
    33            walk_button=True,
    34        )
    35        # self.assertEqual(reality, my_expectation)
    36        self.assertEqual(reality, red)
    37
    38        reality = src.traffic_light.show(
    39            # current_light='RED',
    40            current_light=red,
    41            timer_done=False,
    42        )
    43        # self.assertEqual(reality, my_expectation)
    44        self.assertEqual(reality, red)
    45
    46    def test_yellow_traffic_light(self):
    

    still green.

  • I remove the commented lines

     7    def test_red_traffic_light(self):
     8        red = 'RED'
     9
    10        reality = src.traffic_light.show(
    11            current_light=red,
    12            timer_done=True,
    13            walk_button=True,
    14        )
    15        self.assertEqual(reality, red)
    16
    17        my_expectation = 'GREEN'
    18        reality = src.traffic_light.show(
    19            current_light=red,
    20            timer_done=True,
    21        )
    22        self.assertEqual(reality, my_expectation)
    23
    24        reality = src.traffic_light.show(
    25            current_light=red,
    26            timer_done=False,
    27            walk_button=True,
    28        )
    29        self.assertEqual(reality, red)
    30
    31        reality = src.traffic_light.show(
    32            current_light=red,
    33            timer_done=False,
    34        )
    35        self.assertEqual(reality, red)
    36
    37    def test_yellow_traffic_light(self):
    
  • I add a default value for the current_light keyword argument to the show function traffic_light.py as a fail safe so that the light is always RED if no value is given

    1def show(
    2        current_light='RED', timer_done,
    3        walk_button=False,
    4    ):
    

    the terminal is my friend, and shows SyntaxError

    SyntaxError: parameter without a default follows parameter with a default
    

    because parameters without default values must come before parameters with default values

  • I add SyntaxError to the list of Exceptions seen in test_traffic_light.py

    68# Exceptions seen
    69# AssertionError
    70# NameError
    71# AttributeError
    72# TypeError
    73# SyntaxError
    
  • I add a default value for timer_done to the show function traffic_light.py

    1def show(
    2    current_light='RED', timer_done=False,
    3    walk_button=False,
    4):
    

    the test is green again. All the arguments in the function are now choices, which means

    src.traffic_light.show()
    

    is the same as

    src.traffic_light.show(
        current_light='RED',
        timer_done=False,
        walk_button=False,
    )
    

    because

  • I change the name of test_red_traffic_light to test_red_traffic_light_w_walk_button in test_traffic_light.py

    5class TestTrafficLight(unittest.TestCase):
    6
    7    def test_red_traffic_light_w_walk_button(self):
    8        red = 'RED'
    
  • I remove the current_light parameter from the calls to src.traffic_light.show in test_red_traffic_light_w_walk_button in test_traffic_light.py

     7    def test_red_traffic_light_w_walk_button(self):
     8        red = 'RED'
     9
    10        reality = src.traffic_light.show(
    11            # current_light=red,
    12            timer_done=True,
    13            walk_button=True,
    14        )
    15        self.assertEqual(reality, red)
    16
    17        my_expectation = 'GREEN'
    18        reality = src.traffic_light.show(
    19            # current_light=red,
    20            timer_done=True,
    21        )
    22        self.assertEqual(reality, my_expectation)
    23
    24        reality = src.traffic_light.show(
    25            # current_light=red,
    26            timer_done=False,
    27            walk_button=True,
    28        )
    29        self.assertEqual(reality, red)
    30
    31        reality = src.traffic_light.show(
    32            # current_light=red,
    33            timer_done=False,
    34        )
    35        self.assertEqual(reality, red)
    36
    37    def test_yellow_traffic_light(self):
    

    the test is still green.

  • I remove the timer_done parameter when it is False from test_red_traffic_light_w_walk_button

     7    def test_red_traffic_light_w_walk_button(self):
     8        red = 'RED'
     9
    10        reality = src.traffic_light.show(
    11            # current_light=red,
    12            timer_done=True,
    13            walk_button=True,
    14        )
    15        self.assertEqual(reality, red)
    16
    17        my_expectation = 'GREEN'
    18        reality = src.traffic_light.show(
    19            # current_light=red,
    20            timer_done=True,
    21        )
    22        self.assertEqual(reality, my_expectation)
    23
    24        reality = src.traffic_light.show(
    25            # current_light=red,
    26            # timer_done=False,
    27            walk_button=True,
    28        )
    29        self.assertEqual(reality, red)
    30
    31        reality = src.traffic_light.show(
    32            # current_light=red,
    33            # timer_done=False,
    34        )
    35        self.assertEqual(reality, red)
    36
    37    def test_yellow_traffic_light(self):
    

    still green.

  • I remove the commented lines

     7    def test_red_traffic_light_w_walk_button(self):
     8        red = 'RED'
     9
    10        reality = src.traffic_light.show(
    11            timer_done=True,
    12            walk_button=True,
    13        )
    14        self.assertEqual(reality, red)
    15
    16        my_expectation = 'GREEN'
    17        reality = src.traffic_light.show(
    18            timer_done=True,
    19        )
    20        self.assertEqual(reality, my_expectation)
    21
    22        reality = src.traffic_light.show(
    23            walk_button=True,
    24        )
    25        self.assertEqual(reality, red)
    26
    27        reality = src.traffic_light.show()
    28        self.assertEqual(reality, red)
    29
    30    def test_yellow_traffic_light(self):
    

    green.

REMINDER

This is what happens when the show function is called

 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
18
19    return green
  • 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 if the walk button is pushed

      • it returns GREEN if the walk button is NOT pushed


test_yellow_traffic_light_w_walk_button

The truth table for if the Traffic Light is YELLOW with the walk button is

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

  • I add walk_button to the call to src.traffic_light.show for when the light is YELLOW, the timer is done and the walk button is pushed, in the first assertion of test_yellow_traffic_light in test_traffic_light.py

    current light

    timer

    walk button

    show

    YELLOW

    done

    pushed

    RED

    30    def test_yellow_traffic_light(self):
    31        my_expectation = 'RED'
    32        reality = src.traffic_light.show(
    33            current_light='YELLOW',
    34            timer_done=True,
    35            walk_button=True,
    36        )
    37        self.assertEqual(reality, my_expectation)
    38
    39        my_expectation = 'YELLOW'
    40        reality = src.traffic_light.show(
    41            current_light='YELLOW',
    42            timer_done=False,
    43        )
    44        self.assertEqual(reality, my_expectation)
    45
    46    def test_green_traffic_light(self):
    

    the test is still green.

  • I add an assertion for when the light is YELLOW, the timer is done and the walk button is NOT pushed

    current light

    timer

    walk button

    show

    YELLOW

    done

    pushed

    RED

    YELLOW

    done

    NOT pushed

    RED

    30    def test_yellow_traffic_light(self):
    31        my_expectation = 'RED'
    32        reality = src.traffic_light.show(
    33            current_light='YELLOW',
    34            timer_done=True,
    35            walk_button=True,
    36        )
    37        self.assertEqual(reality, my_expectation)
    38
    39        reality = src.traffic_light.show(
    40            current_light='YELLOW',
    41            timer_done=True,
    42        )
    43        self.assertEqual(reality, my_expectation)
    44
    45        my_expectation = 'YELLOW'
    46        reality = src.traffic_light.show(
    47            current_light='YELLOW',
    48            timer_done=False,
    49        )
    50        self.assertEqual(reality, my_expectation)
    51
    52    def test_green_traffic_light(self):
    

    still green.

  • I add walk_button to the third assertion, 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

    YELLOW

    done

    NOT pushed

    RED

    YELLOW

    NOT done

    pushed

    YELLOW

    30    def test_yellow_traffic_light(self):
    31        my_expectation = 'RED'
    32        reality = src.traffic_light.show(
    33            current_light='YELLOW',
    34            timer_done=True,
    35            walk_button=True,
    36        )
    37        self.assertEqual(reality, my_expectation)
    38
    39        reality = src.traffic_light.show(
    40            current_light='YELLOW',
    41            timer_done=True,
    42        )
    43        self.assertEqual(reality, my_expectation)
    44
    45        my_expectation = 'YELLOW'
    46        reality = src.traffic_light.show(
    47            current_light='YELLOW',
    48            timer_done=False,
    49            walk_button=True,
    50        )
    51        self.assertEqual(reality, my_expectation)
    52
    53    def test_green_traffic_light(self):
    

    green.

  • I add an assertion for when the light is YELLOW, the timer is NOT done and the walk button is NOT pushed

    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

    30    def test_yellow_traffic_light(self):
    31        my_expectation = 'RED'
    32        reality = src.traffic_light.show(
    33            current_light='YELLOW',
    34            timer_done=True,
    35            walk_button=True,
    36        )
    37        self.assertEqual(reality, my_expectation)
    38
    39        reality = src.traffic_light.show(
    40            current_light='YELLOW',
    41            timer_done=True,
    42        )
    43        self.assertEqual(reality, my_expectation)
    44
    45        my_expectation = 'YELLOW'
    46        reality = src.traffic_light.show(
    47            current_light='YELLOW',
    48            timer_done=False,
    49            walk_button=True,
    50        )
    51        self.assertEqual(reality, my_expectation)
    52
    53        reality = src.traffic_light.show(
    54            current_light='YELLOW',
    55        )
    56        self.assertEqual(reality, my_expectation)
    57
    58    def test_green_traffic_light(self):
    

    still green.

  • I change the name of the test from test_yellow_traffic_light to test_yellow_traffic_light_w_walk_button

    27        reality = src.traffic_light.show()
    28        self.assertEqual(reality, red)
    29
    30    def test_yellow_traffic_light_w_walk_button(self):
    31        my_expectation = 'RED'
    32        reality = src.traffic_light.show(
    33            current_light='YELLOW',
    34            timer_done=True,
    35            walk_button=True,
    36        )
    37        self.assertEqual(reality, my_expectation)
    
  • I add a variable to use to remove repetition of 'YELLOW' from the test

    30    def test_yellow_traffic_light_w_walk_button(self):
    31        yellow = 'YELLOW'
    32
    33        my_expectation = 'RED'
    
  • I use the new variable to remove repetition of 'YELLOW' and the my_expectation variable when its value is 'YELLOW'

    30    def test_yellow_traffic_light_w_walk_button(self):
    31        yellow = 'YELLOW'
    32
    33        my_expectation = 'RED'
    34        reality = src.traffic_light.show(
    35            # current_light='YELLOW',
    36            current_light=yellow,
    37            timer_done=True,
    38            walk_button=True,
    39        )
    40        self.assertEqual(reality, my_expectation)
    41
    42        reality = src.traffic_light.show(
    43            # current_light='YELLOW',
    44            current_light=yellow,
    45            timer_done=True,
    46        )
    47        self.assertEqual(reality, my_expectation)
    48
    49        # my_expectation = 'YELLOW'
    50        reality = src.traffic_light.show(
    51            # current_light='YELLOW',
    52            current_light=yellow,
    53            timer_done=False,
    54            walk_button=True,
    55        )
    56        # self.assertEqual(reality, my_expectation)
    57        self.assertEqual(reality, yellow)
    58
    59        reality = src.traffic_light.show(
    60            # current_light='YELLOW',
    61            current_light=yellow,
    62        )
    63        # self.assertEqual(reality, my_expectation)
    64        self.assertEqual(reality, yellow)
    65
    66    def test_green_traffic_light(self):
    

    the test is still green.

  • I add a variable for RED (a repetition of the variable in test_red_traffic_light_w_walk_button, oh boy)

    30    def test_yellow_traffic_light_w_walk_button(self):
    31        red, yellow = 'RED', 'YELLOW'
    32
    33        my_expectation = 'RED'
    
  • I use the new variable to remove repetition, such irony (I use a repetition to remove a repetition)

    30    def test_yellow_traffic_light_w_walk_button(self):
    31        red, yellow = 'RED', 'YELLOW'
    32
    33        # my_expectation = 'RED'
    34        reality = src.traffic_light.show(
    35            # current_light='YELLOW',
    36            current_light=yellow,
    37            timer_done=True,
    38            walk_button=True,
    39        )
    40        # self.assertEqual(reality, my_expectation)
    41        self.assertEqual(reality, red)
    42
    43        reality = src.traffic_light.show(
    44            # current_light='YELLOW',
    45            current_light=yellow,
    46            timer_done=True,
    47        )
    48        # self.assertEqual(reality, my_expectation)
    49        self.assertEqual(reality, red)
    

    still green.

  • I make a global variable to use to remove repetition of 'RED' from test_yellow_traffic_light_w_walk_button and test_red_traffic_light_w_walk_button

    1import src.traffic_light
    2import unittest
    3
    4
    5RED = 'RED'
    6
    7
    8class TestTrafficLight(unittest.TestCase):
    
  • I use the RED global variable to remove repetition from test_red_traffic_light_w_walk_button

    10    def test_red_traffic_light_w_walk_button(self):
    11        # red = 'RED'
    12
    13        reality = src.traffic_light.show(
    14            timer_done=True,
    15            walk_button=True,
    16        )
    17        # self.assertEqual(reality, red)
    18        self.assertEqual(reality, RED)
    19
    20        my_expectation = 'GREEN'
    21        reality = src.traffic_light.show(
    22            timer_done=True,
    23        )
    24        self.assertEqual(reality, my_expectation)
    25
    26        reality = src.traffic_light.show(
    27            walk_button=True,
    28        )
    29        # self.assertEqual(reality, red)
    30        self.assertEqual(reality, RED)
    31
    32        reality = src.traffic_light.show()
    33        # self.assertEqual(reality, red)
    34        self.assertEqual(reality, RED)
    35
    36    def test_yellow_traffic_light_w_walk_button(self):
    

    the test is still green.

  • I remove the commented lines

    10    def test_red_traffic_light_w_walk_button(self):
    11        reality = src.traffic_light.show(
    12            timer_done=True,
    13            walk_button=True,
    14        )
    15        self.assertEqual(reality, RED)
    16
    17        my_expectation = 'GREEN'
    18        reality = src.traffic_light.show(
    19            timer_done=True,
    20        )
    21        self.assertEqual(reality, my_expectation)
    22
    23        reality = src.traffic_light.show(
    24            walk_button=True,
    25        )
    26        self.assertEqual(reality, RED)
    27
    28        reality = src.traffic_light.show()
    29        self.assertEqual(reality, RED)
    30
    31    def test_yellow_traffic_light_w_walk_button(self):
    
  • I use the RED global variable to remove repetition from test_yellow_traffic_light_w_walk_button

    31    def test_yellow_traffic_light_w_walk_button(self):
    32        # red, yellow = 'RED', 'YELLOW'
    33        yellow = 'YELLOW'
    34
    35        # my_expectation = 'RED'
    36        reality = src.traffic_light.show(
    37            # current_light='YELLOW',
    38            current_light=yellow,
    39            timer_done=True,
    40            walk_button=True,
    41        )
    42        # self.assertEqual(reality, my_expectation)
    43        # self.assertEqual(reality, red)
    44        self.assertEqual(reality, RED)
    45
    46        reality = src.traffic_light.show(
    47            # current_light='YELLOW',
    48            current_light=yellow,
    49            timer_done=True,
    50        )
    51        # self.assertEqual(reality, my_expectation)
    52        # self.assertEqual(reality, red)
    53        self.assertEqual(reality, RED)
    

    still green.

  • I remove the commented lines

    31    def test_yellow_traffic_light_w_walk_button(self):
    32        yellow = 'YELLOW'
    33
    34        reality = src.traffic_light.show(
    35            current_light=yellow,
    36            timer_done=True,
    37            walk_button=True,
    38        )
    39        self.assertEqual(reality, RED)
    40
    41        reality = src.traffic_light.show(
    42            current_light=yellow,
    43            timer_done=True,
    44        )
    45        self.assertEqual(reality, RED)
    46
    47        reality = src.traffic_light.show(
    48            current_light=yellow,
    49            timer_done=False,
    50            walk_button=True,
    51        )
    52        self.assertEqual(reality, yellow)
    53
    54        reality = src.traffic_light.show(
    55            current_light=yellow,
    56        )
    57        self.assertEqual(reality, yellow)
    58
    59    def test_green_traffic_light(self):
    

test_green_traffic_light_w_walk_button

The truth table for if the Traffic Light is GREEN with the walk button is

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 add walk_button to the call to src.traffic_light.show for when the light is GREEN, the timer is done and the walk button is pushed, in the first assertion of test_green_traffic_light in test_traffic_light.py

    current light

    timer

    walk button

    show

    GREEN

    done

    pushed

    YELLOW

    59    def test_green_traffic_light(self):
    60        my_expectation = 'YELLOW'
    61        reality = src.traffic_light.show(
    62            current_light='GREEN',
    63            timer_done=True,
    64            walk_button=True,
    65        )
    66        self.assertEqual(reality, my_expectation)
    

    the test is still green.

  • I add an assertion for when the light is GREEN, the timer is done and the walk button is NOT pushed

    current light

    timer

    walk button

    show

    GREEN

    done

    pushed

    YELLOW

    GREEN

    done

    NOT pushed

    YELLOW

    59    def test_green_traffic_light(self):
    60        my_expectation = 'YELLOW'
    61        reality = src.traffic_light.show(
    62            current_light='GREEN',
    63            timer_done=True,
    64            walk_button=True,
    65        )
    66        self.assertEqual(reality, my_expectation)
    67
    68        reality = src.traffic_light.show(
    69            current_light='GREEN',
    70            timer_done=True,
    71        )
    72        self.assertEqual(reality, my_expectation)
    73
    74        my_expectation = 'GREEN'
    75        reality = src.traffic_light.show(
    76            current_light='GREEN',
    77            timer_done=False,
    78        )
    79        self.assertEqual(reality, my_expectation)
    

    still green.

    • I do not need to make a new my_expectation variable because the expectation for the new assertion is the same as the last one ('YELLOW')

    • I do not need to give a value for the walk_button parameter because

      src.traffic_light.show(
          current_light='GREEN',
          timer_done=True,
      )
      

      is the same as

      src.traffic_light.show(
          current_light='GREEN',
          timer_done=True,
          walk_button=False,
      )
      

      the default value for the walk_button parameter is False

  • I add walk_button to the third assertion 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

    GREEN

    done

    NOT pushed

    YELLOW

    GREEN

    NOT done

    pushed

    GREEN

    59    def test_green_traffic_light(self):
    60        my_expectation = 'YELLOW'
    61        reality = src.traffic_light.show(
    62            current_light='GREEN',
    63            timer_done=True,
    64            walk_button=True,
    65        )
    66        self.assertEqual(reality, my_expectation)
    67
    68        reality = src.traffic_light.show(
    69            current_light='GREEN',
    70            timer_done=True,
    71        )
    72        self.assertEqual(reality, my_expectation)
    73
    74        my_expectation = 'GREEN'
    75        reality = src.traffic_light.show(
    76            current_light='GREEN',
    77            timer_done=False,
    78            walk_button=True,
    79        )
    80        self.assertEqual(reality, my_expectation)
    81
    82
    83# Exceptions seen
    

    green.

  • I add an assertion for when the light is GREEN, the timer is NOT done and the walk button is NOT pushed

    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

    59    def test_green_traffic_light(self):
    60        my_expectation = 'YELLOW'
    61        reality = src.traffic_light.show(
    62            current_light='GREEN',
    63            timer_done=True,
    64            walk_button=True,
    65        )
    66        self.assertEqual(reality, my_expectation)
    67
    68        reality = src.traffic_light.show(
    69            current_light='GREEN',
    70            timer_done=True,
    71        )
    72        self.assertEqual(reality, my_expectation)
    73
    74        my_expectation = 'GREEN'
    75        reality = src.traffic_light.show(
    76            current_light='GREEN',
    77            timer_done=False,
    78            walk_button=True,
    79        )
    80        self.assertEqual(reality, my_expectation)
    81
    82        reality = src.traffic_light.show(
    83            current_light='GREEN',
    84        )
    85        self.assertEqual(reality, my_expectation)
    86
    87
    88# Exceptions seen
    

    still green.

  • I change the name of the test from test_green_traffic_light to test_green_traffic_light_w_walk_button

    54        reality = src.traffic_light.show(
    55            current_light=yellow,
    56        )
    57        self.assertEqual(reality, yellow)
    58
    59    def test_green_traffic_light_w_walk_button(self):
    60        my_expectation = 'YELLOW'
    61        reality = src.traffic_light.show(
    62            current_light='GREEN',
    63            timer_done=True,
    64            walk_button=True,
    65        )
    66        self.assertEqual(reality, my_expectation)
    
  • I add a global variable to use to remove repetition of 'YELLOW' from test_green_traffic_light_w_walk_button and test_yellow_traffic_light_w_walk_button

    1import src.traffic_light
    2import unittest
    3
    4
    5RED, YELLOW = 'RED', 'YELLOW'
    6
    7
    8class TestTrafficLight(unittest.TestCase):
    
  • I use the YELLOW global variable to remove repetition from test_yellow_traffic_light_w_walk_button

    31    def test_yellow_traffic_light_w_walk_button(self):
    32        # yellow = 'YELLOW'
    33
    34        reality = src.traffic_light.show(
    35            # current_light=yellow,
    36            current_light=YELLOW,
    37            timer_done=True,
    38            walk_button=True,
    39        )
    40        self.assertEqual(reality, RED)
    41
    42        reality = src.traffic_light.show(
    43            # current_light=yellow,
    44            current_light=YELLOW,
    45            timer_done=True,
    46        )
    47        self.assertEqual(reality, RED)
    48
    49        reality = src.traffic_light.show(
    50            # current_light=yellow,
    51            current_light=YELLOW,
    52            timer_done=False,
    53            walk_button=True,
    54        )
    55        # self.assertEqual(reality, yellow)
    56        self.assertEqual(reality, YELLOW)
    57
    58        reality = src.traffic_light.show(
    59            # current_light=yellow,
    60            current_light=YELLOW,
    61        )
    62        # self.assertEqual(reality, yellow)
    63        self.assertEqual(reality, YELLOW)
    64
    65    def test_green_traffic_light_w_walk_button(self):
    
  • I remove the commented lines

    31    def test_yellow_traffic_light_w_walk_button(self):
    32        reality = src.traffic_light.show(
    33            current_light=YELLOW,
    34            timer_done=True,
    35            walk_button=True,
    36        )
    37        self.assertEqual(reality, RED)
    38
    39        reality = src.traffic_light.show(
    40            current_light=YELLOW,
    41            timer_done=True,
    42        )
    43        self.assertEqual(reality, RED)
    44
    45        reality = src.traffic_light.show(
    46            current_light=YELLOW,
    47            timer_done=False,
    48            walk_button=True,
    49        )
    50        self.assertEqual(reality, YELLOW)
    51
    52        reality = src.traffic_light.show(
    53            current_light=YELLOW,
    54        )
    55        self.assertEqual(reality, YELLOW)
    56
    57    def test_green_traffic_light_w_walk_button(self):
    
  • I add a global variable to use to remove repetition of 'GREEN' from test_green_traffic_light_w_walk_button and test_red_traffic_light_w_walk_button

    1import src.traffic_light
    2import unittest
    3
    4
    5RED, YELLOW, GREEN = 'RED', 'YELLOW', 'GREEN'
    6
    7
    8class TestTrafficLight(unittest.TestCase):
    
  • I use the GREEN global variable to remove repetition from test_red_traffic_light_w_walk_button

    10    def test_red_traffic_light_w_walk_button(self):
    11        reality = src.traffic_light.show(
    12            timer_done=True,
    13            walk_button=True,
    14        )
    15        self.assertEqual(reality, RED)
    16
    17        # my_expectation = 'GREEN'
    18        reality = src.traffic_light.show(
    19            timer_done=True,
    20        )
    21        # self.assertEqual(reality, my_expectation)
    22        self.assertEqual(reality, GREEN)
    23
    24        reality = src.traffic_light.show(
    25            walk_button=True,
    26        )
    27        self.assertEqual(reality, RED)
    28
    29        reality = src.traffic_light.show()
    30        self.assertEqual(reality, RED)
    31
    32    def test_yellow_traffic_light_w_walk_button(self):
    

    the test is still green.

  • I remove the commented lines

    10    def test_red_traffic_light_w_walk_button(self):
    11        reality = src.traffic_light.show(
    12            timer_done=True,
    13            walk_button=True,
    14        )
    15        self.assertEqual(reality, RED)
    16
    17        reality = src.traffic_light.show(
    18            timer_done=True,
    19        )
    20        self.assertEqual(reality, GREEN)
    21
    22        reality = src.traffic_light.show(
    23            walk_button=True,
    24        )
    25        self.assertEqual(reality, RED)
    26
    27        reality = src.traffic_light.show()
    28        self.assertEqual(reality, RED)
    29
    30    def test_yellow_traffic_light_w_walk_button(self):
    
  • I use the GREEN global variable to remove repetition from test_green_traffic_light_w_walk_button

    56    def test_green_traffic_light_w_walk_button(self):
    57        my_expectation = 'YELLOW'
    58        reality = src.traffic_light.show(
    59            # current_light='GREEN',
    60            current_light=GREEN,
    61            timer_done=True,
    62            walk_button=True,
    63        )
    64        self.assertEqual(reality, my_expectation)
    65
    66        reality = src.traffic_light.show(
    67            # current_light='GREEN',
    68            current_light=GREEN,
    69            timer_done=True,
    70        )
    71        self.assertEqual(reality, my_expectation)
    72
    73        # my_expectation = 'GREEN'
    74        reality = src.traffic_light.show(
    75            # current_light='GREEN',
    76            current_light=GREEN,
    77            timer_done=False,
    78            walk_button=True,
    79        )
    80        # self.assertEqual(reality, my_expectation)
    81        self.assertEqual(reality, GREEN)
    82
    83        reality = src.traffic_light.show(
    84            # current_light='GREEN',
    85            current_light=GREEN,
    86        )
    87        # self.assertEqual(reality, my_expectation)
    88        self.assertEqual(reality, GREEN)
    

    still green.

  • I use the YELLOW global variable to remove repetition from test_green_traffic_light_w_walk_button

    56    def test_green_traffic_light_w_walk_button(self):
    57        # my_expectation = 'YELLOW'
    58        reality = src.traffic_light.show(
    59            # current_light='GREEN',
    60            current_light=GREEN,
    61            timer_done=True,
    62            walk_button=True,
    63        )
    64        # self.assertEqual(reality, my_expectation)
    65        self.assertEqual(reality, YELLOW)
    66
    67        reality = src.traffic_light.show(
    68            # current_light='GREEN',
    69            current_light=GREEN,
    70            timer_done=True,
    71        )
    72        # self.assertEqual(reality, my_expectation)
    73        self.assertEqual(reality, YELLOW)
    

    still green.

  • I remove the commented lines

    56    def test_green_traffic_light_w_walk_button(self):
    57        reality = src.traffic_light.show(
    58            current_light=GREEN,
    59            timer_done=True,
    60            walk_button=True,
    61        )
    62        self.assertEqual(reality, YELLOW)
    63
    64        reality = src.traffic_light.show(
    65            current_light=GREEN,
    66            timer_done=True,
    67        )
    68        self.assertEqual(reality, YELLOW)
    69
    70        reality = src.traffic_light.show(
    71            current_light=GREEN,
    72            timer_done=False,
    73            walk_button=True,
    74        )
    75        self.assertEqual(reality, GREEN)
    76
    77        reality = src.traffic_light.show(
    78            current_light=GREEN,
    79        )
    80        self.assertEqual(reality, GREEN)
    81
    82
    83# Exceptions seen
    
  • I want to remove the reality variable, because it is only used once for each assertion, I can make the call to src.traffic_light.show directly, in test_green_traffic_light_w_walk_button

    56    def test_green_traffic_light_w_walk_button(self):
    57        reality = src.traffic_light.show(
    58            current_light=GREEN,
    59            timer_done=True,
    60            walk_button=True,
    61        )
    62        # self.assertEqual(reality, YELLOW)
    63        self.assertEqual(
    64            reality,
    65            YELLOW
    66        )
    67
    68        reality = src.traffic_light.show(
    69            current_light=GREEN,
    70            timer_done=True,
    71        )
    72        # self.assertEqual(reality, YELLOW)
    73        self.assertEqual(
    74            reality,
    75            YELLOW
    76        )
    77
    78        reality = src.traffic_light.show(
    79            current_light=GREEN,
    80            timer_done=False,
    81            walk_button=True,
    82        )
    83        # self.assertEqual(reality, GREEN)
    84        self.assertEqual(
    85            reality,
    86            green.
    87        )
    88
    89        reality = src.traffic_light.show(
    90            current_light=GREEN,
    91        )
    92        # self.assertEqual(reality, GREEN)
    93        self.assertEqual(
    94            reality,
    95            green.
    96        )
    
  • I remove the reality variable from the assertions test_green_traffic_light_w_walk_button, I no longer need it to be a middle man

     56    def test_green_traffic_light_w_walk_button(self):
     57        reality = src.traffic_light.show(
     58            current_light=GREEN,
     59            timer_done=True,
     60            walk_button=True,
     61        )
     62        # self.assertEqual(reality, YELLOW)
     63        self.assertEqual(
     64            # reality,
     65            src.traffic_light.show(
     66                current_light=GREEN,
     67                timer_done=True,
     68                walk_button=True,
     69            ),
     70            YELLOW
     71        )
     72
     73        reality = src.traffic_light.show(
     74            current_light=GREEN,
     75            timer_done=True,
     76        )
     77        # self.assertEqual(reality, YELLOW)
     78        self.assertEqual(
     79            # reality,
     80            src.traffic_light.show(
     81                current_light=GREEN,
     82                timer_done=True,
     83            ),
     84            YELLOW
     85        )
     86
     87        reality = src.traffic_light.show(
     88            current_light=GREEN,
     89            timer_done=False,
     90            walk_button=True,
     91        )
     92        # self.assertEqual(reality, GREEN)
     93        self.assertEqual(
     94            # reality,
     95            src.traffic_light.show(
     96                current_light=GREEN,
     97                timer_done=False,
     98                walk_button=True,
     99            ),
    100            green.
    101        )
    102
    103        reality = src.traffic_light.show(
    104            current_light=GREEN,
    105        )
    106        # self.assertEqual(reality, GREEN)
    107        self.assertEqual(
    108            # reality,
    109            src.traffic_light.show(
    110                current_light=GREEN,
    111            ),
    112            green.
    113        )
    

    green.

  • I remove the commented lines and reality variable from test_green_traffic_light_w_walk_button

    56    def test_green_traffic_light_w_walk_button(self):
    57        self.assertEqual(
    58            src.traffic_light.show(
    59                current_light=GREEN,
    60                timer_done=True,
    61                walk_button=True,
    62            ),
    63            YELLOW
    64        )
    65
    66        self.assertEqual(
    67            src.traffic_light.show(
    68                current_light=GREEN,
    69                timer_done=True,
    70            ),
    71            YELLOW
    72        )
    73
    74        self.assertEqual(
    75            src.traffic_light.show(
    76                current_light=GREEN,
    77                timer_done=False,
    78                walk_button=True,
    79            ),
    80            green.
    81        )
    82
    83        self.assertEqual(
    84            src.traffic_light.show(
    85                current_light=GREEN,
    86            ),
    87            green.
    88        )
    89
    90
    91# Exceptions seen
    

    still green.

  • I do the same thing with test_yellow_traffic_light_w_walk_button

    30    def test_yellow_traffic_light_w_walk_button(self):
    31        reality = src.traffic_light.show(
    32            current_light=YELLOW,
    33            timer_done=True,
    34            walk_button=True,
    35        )
    36        self.assertEqual(
    37            reality,
    38            RED
    39        )
    40
    41        reality = src.traffic_light.show(
    42            current_light=YELLOW,
    43            timer_done=True,
    44        )
    45        self.assertEqual(
    46            reality,
    47            RED
    48        )
    49
    50        reality = src.traffic_light.show(
    51            current_light=YELLOW,
    52            timer_done=False,
    53            walk_button=True,
    54        )
    55        self.assertEqual(
    56            reality,
    57            YELLOW
    58        )
    59
    60        reality = src.traffic_light.show(
    61            current_light=YELLOW,
    62        )
    63        self.assertEqual(
    64            reality,
    65            YELLOW
    66        )
    67
    68    def test_green_traffic_light_w_walk_button(self):
    
  • I call the show function directly in the assertions in test_yellow_traffic_light_w_walk_button

    30    def test_yellow_traffic_light_w_walk_button(self):
    31        reality = src.traffic_light.show(
    32            current_light=YELLOW,
    33            timer_done=True,
    34            walk_button=True,
    35        )
    36        self.assertEqual(
    37            # reality,
    38            src.traffic_light.show(
    39                current_light=YELLOW,
    40                timer_done=True,
    41                walk_button=True,
    42            ),
    43            RED
    44        )
    45
    46        reality = src.traffic_light.show(
    47            current_light=YELLOW,
    48            timer_done=True,
    49        )
    50        self.assertEqual(
    51            # reality,
    52            src.traffic_light.show(
    53                current_light=YELLOW,
    54                timer_done=True,
    55            ),
    56            RED
    57        )
    58
    59        reality = src.traffic_light.show(
    60            current_light=YELLOW,
    61            timer_done=False,
    62            walk_button=True,
    63        )
    64        self.assertEqual(
    65            # reality,
    66            src.traffic_light.show(
    67                current_light=YELLOW,
    68                timer_done=False,
    69                walk_button=True,
    70            ),
    71            YELLOW
    72        )
    73
    74        reality = src.traffic_light.show(
    75            current_light=YELLOW,
    76        )
    77        self.assertEqual(
    78            # reality,
    79            src.traffic_light.show(
    80                current_light=YELLOW,
    81            ),
    82            YELLOW
    83        )
    84
    85    def test_green_traffic_light_w_walk_button(self):
    

    the test is still green.

  • I remove the reality variable and comments from test_yellow_traffic_light_w_walk_button

    30    def test_yellow_traffic_light_w_walk_button(self):
    31        self.assertEqual(
    32            src.traffic_light.show(
    33                current_light=YELLOW,
    34                timer_done=True,
    35                walk_button=True,
    36            ),
    37            RED
    38        )
    39
    40        self.assertEqual(
    41            src.traffic_light.show(
    42                current_light=YELLOW,
    43                timer_done=True,
    44            ),
    45            RED
    46        )
    47
    48        self.assertEqual(
    49            src.traffic_light.show(
    50                current_light=YELLOW,
    51                timer_done=False,
    52                walk_button=True,
    53            ),
    54            YELLOW
    55        )
    56
    57        self.assertEqual(
    58            src.traffic_light.show(
    59                current_light=YELLOW,
    60            ),
    61            YELLOW
    62        )
    63
    64    def test_green_traffic_light_w_walk_button(self):
    
  • I also do it in test_red_traffic_light_w_walk_button

    10    def test_red_traffic_light_w_walk_button(self):
    11        reality = src.traffic_light.show(
    12            timer_done=True,
    13            walk_button=True,
    14        )
    15        self.assertEqual(
    16            reality,
    17            RED
    18        )
    19
    20        reality = src.traffic_light.show(
    21            timer_done=True,
    22        )
    23        self.assertEqual(
    24            reality,
    25            green.
    26        )
    27
    28        reality = src.traffic_light.show(
    29            walk_button=True,
    30        )
    31        self.assertEqual(
    32            reality,
    33            RED
    34        )
    35
    36        reality = src.traffic_light.show()
    37        self.assertEqual(
    38            reality,
    39            RED
    40        )
    
  • I call the show function directly

    10    def test_red_traffic_light_w_walk_button(self):
    11        reality = src.traffic_light.show(
    12            timer_done=True,
    13            walk_button=True,
    14        )
    15        self.assertEqual(
    16            # reality,
    17            src.traffic_light.show(
    18                timer_done=True,
    19                walk_button=True,
    20            ),
    21            RED
    22        )
    23
    24        reality = src.traffic_light.show(
    25            timer_done=True,
    26        )
    27        self.assertEqual(
    28            # reality,
    29            src.traffic_light.show(
    30                timer_done=True,
    31            ),
    32            green.
    33        )
    34
    35        reality = src.traffic_light.show(
    36            walk_button=True,
    37        )
    38        self.assertEqual(
    39            # reality,
    40            src.traffic_light.show(
    41                walk_button=True,
    42            ),
    43            RED
    44        )
    45
    46        reality = src.traffic_light.show()
    47        self.assertEqual(
    48            # reality,
    49            src.traffic_light.show(),
    50            RED
    51        )
    

    still green.

  • I remove the reality variable and the comments from test_red_traffic_light_w_walk_button

    10    def test_red_traffic_light_w_walk_button(self):
    11        self.assertEqual(
    12            src.traffic_light.show(
    13                timer_done=True,
    14                walk_button=True,
    15            ),
    16            RED
    17        )
    18
    19        self.assertEqual(
    20            src.traffic_light.show(
    21                timer_done=True,
    22            ),
    23            green.
    24        )
    25
    26        self.assertEqual(
    27            src.traffic_light.show(
    28                walk_button=True,
    29            ),
    30            RED
    31        )
    32
    33        self.assertEqual(
    34            src.traffic_light.show(),
    35            RED
    36        )
    37
    38    def test_yellow_traffic_light_w_walk_button(self):
    

REMINDER

This is what happens when the show function is called

 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
18
19    return green
  • 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 if the walk button is pushed

      • it returns GREEN if the walk button is NOT pushed


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 pushed

      • it 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.py

    current 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 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, 'NO WALK'
    

    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 pushed

        • it 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.py

    current 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.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        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.py

    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

    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 show function is called

    • if the timer is NOT done

      • it returns 'RED', 'WALK' if the current light is RED

      • it 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 pushed

        • it 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, 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        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.py

    current 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 show function is called

    • if the timer is NOT done

      • it returns 'RED', 'WALK' if the current light is RED

      • it 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 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 pushed

        • it 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.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        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.py

    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

    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 show function is called

    • if the timer is NOT done

      • it returns 'RED', 'WALK' if the current light is RED

      • it returns 'YELLOW', 'NO WALK' if the current light is YELLOW

      • it 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 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 pushed

        • it 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 GREEN

     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        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.py

    current 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 show function is called

    • if the timer is NOT done

      • it returns 'RED', 'WALK' if the current light is RED

      • it returns 'YELLOW', 'NO WALK' if the current light is YELLOW

      • it 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 YELLOW

      • it returns 'YELLOW', 'NO WALK' 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 pushed

        • it 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 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        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 show function now returns ('GREEN', 'NO WALK') and the next assertion expects 'GREEN'. I have to make the same change in the next assertion

  • I 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.py

    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

     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 seen
    

    the test passes. This is what happens when the show function is called

    • if the timer is NOT done

      • it returns 'RED', 'WALK' if the current light is RED

      • it returns 'YELLOW', 'NO WALK' if the current light is YELLOW

      • it 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 YELLOW

      • it returns 'YELLOW', 'NO WALK' 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 pushed

        • it 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.py to use them to remove repetition from the tests

     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):
    
  • I use the GREEN_NO_WALK global variable for (GREEN, 'NO WALK') in the second assertion of test_red_traffic_light_w_walk

    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            (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 WALK global variable for (RED, 'WALK') in test_red_traffic_light_w_walk

    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            # (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 WALK global variable for (RED, 'WALK') in 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            # (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_WALK global variable for (YELLOW, 'NO WALK') in 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            # (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_WALK global variable for (YELLOW, 'NO WALK') in 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            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_WALK global variable for (GREEN, 'NO WALK') in 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            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 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    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_walk
    

    the 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_walk
    

    still 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 walk
    

    green.

  • the walk variable which is 'RED', 'WALK', happens 3 times in the function, I add a return statement to make it the default state of the light

    38    if current_light == red:
    39        if not walk_button:
    40            return green, no_walk
    41        else:
    42            return walk
    43
    44    return walk
    

    still green. This means if none of the conditions in the show function 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 out

    38    if current_light == red:
    39        if not walk_button:
    40            return green, no_walk
    41        # else:
    42            # return walk
    43
    44    return walk
    

    the 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 walk
    

    still 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 out

    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 walk
    43
    44    return walk
    

    green. 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 walk
    

    still 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 run

     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_walk
    22
    23    # if current_light == yellow:
    24        # return red, 'WALK'
    25        # return walk
    

    the 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 GREEN

    • it 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.py and traffic_light.py in the editor

  • I 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_light

    cd ..
    

    the terminal shows

    .../pumping_python
    

    I am back in the pumping_python directory


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

Do you want to see all the CODE I typed in this chapter?


what is next?

you know

Would you like to test making an Automated Teller Machine?


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.