Car

I want to make a Car that can be turned on with the push of a button, if the inputs are

  • is the key close to the starter?

  • was the start button pressed?

this is the truth table I get for the Car Starter

key

start

output

close

pressed

ON

close

NOT pressed

OFF

far

pressed

OFF

far

NOT pressed

OFF

preview

These are the tests I have at the end of the chapter

  1import src.car
  2import unittest
  3
  4
  5OFF = 'OFF'
  6
  7
  8class TestCar(unittest.TestCase):
  9
 10    def test_key_close_brake_pressed_w_gear(self):
 11        self.assertEqual(
 12            src.car.starter(
 13                key_is_close=True,
 14                brake_is_pressed=True,
 15                start_is_pushed=True,
 16                in_park=True,
 17            ),
 18            'ON'
 19        )
 20
 21        self.assertEqual(
 22            src.car.starter(
 23                key_is_close=True,
 24                brake_is_pressed=True,
 25                start_is_pushed=True,
 26                in_park=False,
 27            ),
 28            OFF
 29        )
 30
 31        self.assertEqual(
 32            src.car.starter(
 33                key_is_close=True,
 34                brake_is_pressed=True,
 35                start_is_pushed=False,
 36                in_park=True,
 37            ),
 38            OFF
 39        )
 40
 41        self.assertEqual(
 42            src.car.starter(
 43                key_is_close=True,
 44                brake_is_pressed=True,
 45                start_is_pushed=False,
 46                in_park=False,
 47            ),
 48            OFF
 49        )
 50
 51    def test_key_close_brake_not_pressed_w_gear(self):
 52        self.assertEqual(
 53            src.car.starter(
 54                key_is_close=True,
 55                brake_is_pressed=False,
 56                start_is_pushed=True,
 57                in_park=True,
 58            ),
 59            OFF
 60        )
 61
 62        self.assertEqual(
 63            src.car.starter(
 64                key_is_close=True,
 65                brake_is_pressed=False,
 66                start_is_pushed=True,
 67                in_park=False,
 68            ),
 69            OFF
 70        )
 71
 72        self.assertEqual(
 73            src.car.starter(
 74                key_is_close=True,
 75                brake_is_pressed=False,
 76                start_is_pushed=False,
 77                in_park=True,
 78            ),
 79            OFF
 80        )
 81
 82        self.assertEqual(
 83            src.car.starter(
 84                key_is_close=True,
 85                brake_is_pressed=False,
 86                start_is_pushed=False,
 87                in_park=False,
 88            ),
 89            OFF
 90        )
 91
 92    def test_key_far_brake_pressed_w_gear(self):
 93        self.assertEqual(
 94            src.car.starter(
 95                key_is_close=False,
 96                brake_is_pressed=True,
 97                start_is_pushed=True,
 98                in_park=True,
 99            ),
100            OFF
101        )
102
103        self.assertEqual(
104            src.car.starter(
105                key_is_close=False,
106                brake_is_pressed=True,
107                start_is_pushed=True,
108                in_park=False,
109            ),
110            OFF
111        )
112
113        self.assertEqual(
114            src.car.starter(
115                key_is_close=False,
116                brake_is_pressed=True,
117                start_is_pushed=False,
118                in_park=True,
119            ),
120            OFF
121        )
122
123        self.assertEqual(
124            src.car.starter(
125                key_is_close=False,
126                brake_is_pressed=True,
127                start_is_pushed=False,
128                in_park=False,
129            ),
130            OFF
131        )
132
133    def test_key_far_brake_not_pressed_w_gear(self):
134        self.assertEqual(
135            src.car.starter(
136                key_is_close=False,
137                brake_is_pressed=False,
138                start_is_pushed=True,
139                in_park=True,
140            ),
141            OFF
142        )
143
144        self.assertEqual(
145            src.car.starter(
146                key_is_close=False,
147                brake_is_pressed=False,
148                start_is_pushed=True,
149                in_park=False,
150            ),
151            OFF
152        )
153
154        self.assertEqual(
155            src.car.starter(
156                key_is_close=False,
157                brake_is_pressed=False,
158                start_is_pushed=False,
159                in_park=True,
160            ),
161            OFF
162        )
163
164        self.assertEqual(
165            src.car.starter(
166                key_is_close=False,
167                brake_is_pressed=False,
168                start_is_pushed=False,
169                in_park=False,
170            ),
171            OFF
172        )
173
174
175# Exceptions seen
176# AssertionError
177# NameError
178# AttributeError
179# TypeError
180# SyntaxError

requirements


start the project

  • I name this project car

  • I open a terminal

  • I use uv to make a directory for the project

    uv init car
    

    the terminal shows

    Initialized project `car` at `.../pumping_python/car`
    

    then goes back to the command line

  • I change directory to the project

    cd car
    

    the terminal shows I am in the car folder

    .../pumping_python/car
    
  • I remove main.py from the project because I do not use it

    rm main.py
    

    the terminal 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 make a Python file to hold the source code in the src directory

    touch src/car.py
    
    New-Item src/car.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_car.py
    
    New-Item tests/test_car.py
    

    the terminal goes back to the command line

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

    Visual Studio Code opens test_car.py in the editor

  • I add the first failing test to test_car.py

    1import unittest
    2
    3
    4class TestCar(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
       └── car.py
    ├── tests
       ├── __init__.py
       └── test_car.py
    └── uv.lock
    

    if you do not see uv.lock in your tree, do not worry, run the tests next

  • I use pytest-watcher to run the tests automatically

    uv run pytest-watcher . --now
    

    the terminal is my friend, and shows AssertionError

    ======================== FAILURES ========================
    _________________ TestCar.test_failure ___________________
    
    self = <tests.test_car.TestCar testMethod=test_failure>
    
        def test_failure(self):
    >       self.assertFalse(True)
    E       AssertionError: True is not false
    
    tests/test_car.py:7: AssertionError
    ================ short test summary info =================
    FAILED tests/test_car.py::TestCar::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 have 2 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 then try to run uv run pytest-watcher . --now again

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

     4class TestCar(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_key_close

The truth table for when the key is close to the starter is

key

start

output

close

pressed

ON

close

NOT pressed

OFF


RED: make it fail


I change test_failure to test_key_close, then add an assertion for when the key is close and the start button is pressed

key

start

output

close

pressed

ON

 4class TestCar(unittest.TestCase):
 5
 6    def test_key_close(self):
 7        my_expectation = 'ON'
 8        reality = src.car.starter(
 9            key_is_close=True,
10            start_is_pressed=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

    1import src.car
    2import unittest
    3
    4
    5class TestCar(unittest.TestCase):
    

    the terminal is my friend, and shows AttributeError

    AttributeError: module 'src.car' has no attribute 'starter'
    

    because car.py in the src folder does not have anything named starter 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

  • I add AttributeError to the list of Exceptions seen

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

  • I add a function named starter to car.py

    1def starter():
    2    return None
    

    the terminal is my friend, and shows TypeError

    TypeError: starter() got an unexpected keyword argument 'key_is_close'
    

    because the test called the starter function with 2 keyword arguments (key_is_close and start_is_pressed) and this definition only allows calls with 0 arguments

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

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

    1def starter(key_is_close):
    2    return None
    

    the terminal is my friend, and shows TypeError

    TypeError: starter() got an unexpected keyword argument 'start_is_pressed'
    

    because the test called the starter function with 2 keyword arguments (key_is_close and start_is_pressed) and this definition only allows calls with 1 input

  • I add start_is_pressed to the function signature

    1def starter(key_is_close, start_is_pressed):
    2    return None
    

    the terminal is my friend, and shows AssertionError

    AssertionError: None != 'ON'
    

    the starter function returned None and the test expects ‘ON’

  • I change the return statement to give the test what it wants

    1def starter(key_is_close, start_is_pressed):
    2    return 'ON'
    

    the test passes. The starter function always returns ON, it does not care about the inputs. Is this Tautology?


REFACTOR: make it better


  • I add an assertion for when the key is close and the start button is NOT pressed, in test_car.py

    key

    start

    output

    close

    pressed

    ON

    close

    NOT pressed

    OFF

     7    def test_key_close(self):
     8        my_expectation = 'ON'
     9        reality = src.car.starter(
    10            key_is_close=True,
    11            start_is_pressed=True,
    12        )
    13        self.assertEqual(reality, my_expectation)
    14
    15        my_expectation = 'OFF'
    16        reality = src.car.starter(
    17            key_is_close=True,
    18            start_is_pressed=False,
    19        )
    20        self.assertEqual(reality, my_expectation)
    21
    22
    23# Exceptions seen
    

    the terminal is my friend, and shows AssertionError

    AssertionError: 'ON' != 'OFF'
    

    because the starter function returns ‘ON’ and the test expects ‘OFF’

  • I add an if statement to the starter function in car.py

    1def starter(key_is_close, start_is_pressed):
    2    if start_is_pressed == False:
    3        return 'OFF'
    4
    5    return 'ON'
    

    the test passes

  • I use Logical Negation (NOT) to write it in terms of True

    1def starter(key_is_close, start_is_pressed):
    2    # if start_is_pressed == False:
    3    if not start_is_pressed == True:
    4        return 'OFF'
    5
    6    return 'ON'
    

    the test is still green

  • I remove == True

    1def starter(key_is_close, start_is_pressed):
    2    # if start_is_pressed == False:
    3    # if not start_is_pressed == True:
    4    if not start_is_pressed:
    5        return 'OFF'
    6
    7    return 'ON'
    

    still green, because if something == False is the same as if not something == True is the same as if not something

  • I remove the commented lines

    1def starter(key_is_close, start_is_pressed):
    2    if not start_is_pressed:
    3        return 'OFF'
    4
    5    return 'ON'
    

    this is what happens when the starter function is called

    • it returns ‘OFF’ if the start button is NOT pressed

    • it returns ‘ON’ if the above condition is not met


test_key_far

The truth table for when the key is far from the starter is

key

start

output

far

pressed

OFF

far

NOT pressed

OFF


RED: make it fail


I add a test with an assertion for when the key is far from the starter and the start button is pressed, in test_car.py

key

start

output

far

pressed

OFF

15          my_expectation = 'OFF'
16          reality = src.car.starter(
17              key_is_close=True,
18              start_is_pressed=False,
19          )
20          self.assertEqual(reality, my_expectation)
21
22      def test_key_far(self):
23          my_expectation = 'OFF'
24          reality = src.car.starter(
25              key_is_close=False,
26              start_is_pressed=True,
27          )
28          self.assertEqual(reality, my_expectation)
29
30
31  # Exceptions seen

the terminal is my friend, and shows AssertionError

AssertionError: 'ON' != 'OFF'

because the starter function returns ‘ON’ and the test expects ‘OFF’


GREEN: make it pass


I add an if statement to car.py

1def starter(key_is_close, start_is_pressed):
2    if key_is_close == False:
3        return 'OFF'
4
5    if not start_is_pressed:
6        return 'OFF'
7
8    return 'ON'

the test passes


REFACTOR: make it better


  • I use Logical Negation (NOT) to write the new if statement in terms of True

    1def starter(key_is_close, start_is_pressed):
    2    # if key_is_close == False:
    3    if not key_is_close == True:
    4        return 'OFF'
    5
    6    if not start_is_pressed:
    7        return 'OFF'
    8
    9    return 'ON'
    

    the test is still green

  • I remove == True

     1def starter(key_is_close, start_is_pressed):
     2    # if key_is_close == False:
     3    # if not key_is_close == True:
     4    if not key_is_close:
     5        return 'OFF'
     6
     7    if not start_is_pressed:
     8        return 'OFF'
     9
    10    return 'ON'
    

    still green, because if something == False is the same as if not something == True is the same as if not something

  • I use Logical Disjunction (OR) to put the two if statements together because they both return the same thing ('OFF')

     1def starter(key_is_close, start_is_pressed):
     2    # if key_is_close == False:
     3    # if not key_is_close == True:
     4    # if not key_is_close:
     5    #     return 'OFF'
     6
     7    # if not start_is_pressed:
     8    if not key_is_close or not start_is_pressed:
     9        return 'OFF'
    10
    11    return 'ON'
    

    the test is still green

  • I rewrite the statement in terms of Logical Negation (NOT) because it happens two times

     1def starter(key_is_close, start_is_pressed):
     2    # if key_is_close == False:
     3    # if not key_is_close == True:
     4    # if not key_is_close:
     5    #     return 'OFF'
     6    # if not start_is_pressed:
     7    # if not key_is_close or not start_is_pressed:
     8    if (
     9        (not key_is_close)
    10        (not and)
    11        (not start_is_pressed)
    12    ):
    13        return 'OFF'
    14
    15    return 'ON'
    

    the terminal is my friend, and shows SyntaxError

    SyntaxError: invalid syntax
    

    because I cannot negate and this way

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

    31# Exceptions seen
    32# AssertionError
    33# NameError
    34# AttributeError
    35# TypeError
    36# SyntaxError
    
  • I “factor” out the nots in the starter function in car.py

     1def starter(key_is_close, start_is_pressed):
     2    # if key_is_close == False:
     3    # if not key_is_close == True:
     4    # if not key_is_close:
     5    #     return 'OFF'
     6    # if not start_is_pressed:
     7    # if not key_is_close or not start_is_pressed:
     8    # if (
     9    #     (not key_is_close)
    10    #     (not and)
    11    #     (not start_is_pressed)
    12    # ):
    13    if not (key_is_close and start_is_pressed):
    14        return 'OFF'
    15
    16    return 'ON'
    

    the test is green again

  • I remove the commented lines

    1def starter(key_is_close, start_is_pressed):
    2    if not (key_is_close and start_is_pressed):
    3        return 'OFF'
    4
    5    return 'ON'
    

    this is what happens when the starter function is called

    • it returns ‘OFF’ if the key is far from the starter OR the start button is NOT pressed

    • it returns ‘ON’ if the above conditions are not met

    is this Logical Conjunction?

  • I add an assertion for when the key is far from the starter and the start button is NOT pressed to test_key_far in test_car.py

    key

    start

    output

    far

    pressed

    OFF

    far

    NOT pressed

    OFF

    22    def test_key_far(self):
    23        my_expectation = 'OFF'
    24        reality = src.car.starter(
    25            key_is_close=False,
    26            start_is_pressed=True,
    27        )
    28        self.assertEqual(reality, my_expectation)
    29
    30        reality = src.car.starter(
    31            key_is_close=False,
    32            start_is_pressed=False,
    33        )
    34        self.assertEqual(reality, my_expectation)
    35
    36
    37# Exceptions seen
    

    the test is 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 (‘OFF’)

  • I make a global variable to remove repetition from the tests

    1import src.car
    2import unittest
    3
    4
    5OFF = 'OFF'
    6
    7
    8class TestCar(unittest.TestCase):
    

    this way all the tests can use the same global variable and I do not have to make one for each test

  • I use the new global variable to remove 'OFF' from test_key_close

    10    def test_key_close(self):
    11        my_expectation = 'ON'
    12        reality = src.car.starter(
    13            key_is_close=True,
    14            start_is_pressed=True,
    15        )
    16        self.assertEqual(reality, my_expectation)
    17
    18        # my_expectation = 'OFF'
    19        reality = src.car.starter(
    20            key_is_close=True,
    21            start_is_pressed=False,
    22        )
    23        # self.assertEqual(reality, my_expectation)
    24        self.assertEqual(reality, OFF)
    

    still green

  • I remove the commented lines

    10    def test_key_close(self):
    11        my_expectation = 'ON'
    12        reality = src.car.starter(
    13            key_is_close=True,
    14            start_is_pressed=True,
    15        )
    16        self.assertEqual(reality, my_expectation)
    17
    18        reality = src.car.starter(
    19            key_is_close=True,
    20            start_is_pressed=False,
    21        )
    22        self.assertEqual(reality, OFF)
    23
    24    def test_key_far(self):
    
  • I use the new global variable to remove 'OFF' from test_key_far

    24    def test_key_far(self):
    25        # my_expectation = 'OFF'
    26        reality = src.car.starter(
    27            key_is_close=False,
    28            start_is_pressed=True,
    29        )
    30        # self.assertEqual(reality, my_expectation)
    31        self.assertEqual(reality, OFF)
    32
    33        reality = src.car.starter(
    34            key_is_close=False,
    35            start_is_pressed=False,
    36        )
    37        # self.assertEqual(reality, my_expectation)
    38        self.assertEqual(reality, OFF)
    39
    40
    41# Exceptions seen
    

    green

  • I remove the commented lines

    24    def test_key_far(self):
    25        reality = src.car.starter(
    26            key_is_close=False,
    27            start_is_pressed=True,
    28        )
    29        self.assertEqual(reality, OFF)
    30
    31        reality = src.car.starter(
    32            key_is_close=False,
    33            start_is_pressed=False,
    34        )
    35        self.assertEqual(reality, OFF)
    36
    37
    38# Exceptions seen
    

test_key_close_brake_pressed

So far, the truth table for the car starter is

key

start

output

close

pressed

ON

close

NOT pressed

OFF

far

pressed

OFF

far

NOT pressed

OFF

I want the car to start only when the brake pedal is pressed, the inputs for the car will then be

  • is the key close to the starter?

  • is the brake being pressed?

  • was the start button pressed?

and the truth table for when the key is close and the brake is being pressed, is:

key

brake

start

output

close

pressed

pressed

ON

close

pressed

NOT pressed

OFF


RED: make it fail


I add a value for brake_is_pressed to the first assertion in test_key_close, for when the key is close, the brake is being pressed and the start button is pressed

key

brake

start

output

close

pressed

pressed

ON

 7    def test_key_close(self):
 8        my_expectation = 'ON'
 9        reality = src.car.starter(
10            key_is_close=True,
11            brake_is_pressed=True,
12            start_is_pressed=True,
13        )
14        self.assertEqual(reality, my_expectation)

the terminal is my friend, and shows TypeError

TypeError: starter() got an unexpected keyword argument 'brake_is_pressed'. Did you mean 'start_is_pressed'?

because the test called the starter function with 3 keyword arguments (key_is_close, brake_is_pressed and start_is_pressed) and the function only allows calls with 2 arguments (key_is_close and start_is_pressed)


GREEN: make it pass


  • I add brake_is_pressed to the function signature in car.py

    1def starter(
    2        key_is_close, start_is_pressed,
    3        brake_is_pressed,
    4    ):
    5    if not (key_is_close and start_is_pressed):
    6        return 'OFF'
    7
    8    return 'ON'
    

    the terminal is my friend, and shows TypeError

    FAILED ...test_key_close - TypeError: starter() missing 1 required positional argument: 'brake_is_pressed'
    FAILED ...test_key_far - TypeError: starter() missing 1 required positional argument: 'brake_is_pressed'
    

    because the tests call the starter function with 2 arguments (key_is_close and start_is_pressed) and I just changed the function signature to make it take 3 required arguments (key_is_close, start_is_pressed and brake_is_pressed). I have to make brake_is_pressed a choice.

  • I add a default value to make brake_is_pressed a choice

    1def starter(
    2        key_is_close, start_is_pressed,
    3        brake_is_pressed=False,
    4    ):
    

    the test passes because

    src.car.starter(
        key_is_close=True,
        start_is_pressed=False,
    )
    

    is now the same as

    src.car.starter(
        key_is_close=True,
        start_is_pressed=False,
        brake_is_pressed=False,
    )
    

    a function uses the default value for a parameter when it is called without a value for the parameter.


REFACTOR: make it better


  • I add a value for brake_is_pressed to the next assertion for when the key is close, the brake is being pressed and the start button is NOT pressed

    key

    brake

    start

    output

    close

    pressed

    pressed

    ON

    close

    pressed

    NOT pressed

    OFF

     7    def test_key_close(self):
     8        my_expectation = 'ON'
     9        reality = src.car.starter(
    10            key_is_close=True,
    11            brake_is_pressed=True,
    12            start_is_pressed=True,
    13        )
    14        self.assertEqual(reality, my_expectation)
    15
    16        reality = src.car.starter(
    17            key_is_close=True,
    18            brake_is_pressed=True,
    19            start_is_pressed=False,
    20        )
    21        self.assertEqual(reality, OFF)
    22
    23    def test_key_far(self):
    

    the test is still green

  • I change the name of the test from test_key_close to test_key_close_brake_pressed

    5class TestCar(unittest.TestCase):
    6
    7    def test_key_close_brake_pressed(self):
    8        my_expectation = 'OFF'
    

test_key_close_brake_not_pressed

The truth table for when the key is close and the brake is NOT pressed is

key

brake

start

output

close

NOT pressed

pressed

OFF

close

NOT pressed

NOT pressed

OFF

  • I add a new test with an assertion for when the key is close, the brake is NOT pressed and the start button is pressed

    key

    brake

    start

    output

    close

    NOT pressed

    pressed

    OFF

    19        reality = src.car.starter(
    20            key_is_close=True,
    21            brake_is_pressed=True,
    22            start_is_pressed=False,
    23        )
    24        self.assertEqual(reality, OFF)
    25
    26    def test_key_close_brake_not_pressed(self):
    27        reality = src.car.starter(
    28            key_is_close=True,
    29            brake_is_pressed=False,
    30            start_is_pressed=True,
    31        )
    32        self.assertEqual(reality, OFF)
    33
    34    def test_key_far(self):
    

    the terminal is my friend, and shows AssertionError

    AssertionError: 'ON' != 'OFF'
    

    because the starter function returned ‘ON’ and the test expects ‘OFF’

  • I add an if statement to the starter function in car.py

     1def starter(
     2        key_is_close, start_is_pressed,
     3        brake_is_pressed=False,
     4    ):
     5    if brake_is_pressed == False:
     6        return 'OFF'
     7
     8    if not (key_is_close and start_is_pressed):
     9        return 'OFF'
    10
    11    return 'ON'
    

    the test passes

  • I use Logical Negation (NOT) to write the new if statement in terms of True

     1def starter(
     2        key_is_close, start_is_pressed,
     3        brake_is_pressed=False,
     4    ):
     5    # if brake_is_pressed == False:
     6    if not brake_is_pressed == True:
     7        return 'OFF'
     8
     9    if not (key_is_close and start_is_pressed):
    10        return 'OFF'
    11
    12    return 'ON'
    

    the test is still green

  • I remove == True

     1def starter(
     2        key_is_close, start_is_pressed,
     3        brake_is_pressed=False,
     4    ):
     5    # if brake_is_pressed == False:
     6    # if not brake_is_pressed == True:
     7    if not brake_is_pressed:
     8        return 'OFF'
     9
    10    if not (key_is_close and start_is_pressed):
    11        return 'OFF'
    12
    13    return 'ON'
    

    still green, because if something == False is the same as if not something == True is the same as if not something

  • I use Logical Disjunction to put the two if statements together because they return the same thing

     1def starter(
     2        key_is_close, start_is_pressed,
     3        brake_is_pressed=False,
     4    ):
     5    # if brake_is_pressed == False:
     6    # if not brake_is_pressed == True:
     7    # if not brake_is_pressed:
     8    #     return 'OFF'
     9
    10    # if not (key_is_close and start_is_pressed):
    11    if (
    12        not (key_is_close and start_is_pressed)
    13        or
    14        not brake_is_pressed
    15    ):
    16        return 'OFF'
    17
    18    return 'ON'
    

    green

  • I write the statement in terms of NOT

     1def starter(
     2        key_is_close, start_is_pressed,
     3        brake_is_pressed=False,
     4    ):
     5    # if brake_is_pressed == False:
     6    # if not brake_is_pressed == True:
     7    # if not brake_is_pressed:
     8    #     return 'OFF'
     9
    10    # if not (key_is_close and start_is_pressed):
    11    # if (
    12    #     not (key_is_close and start_is_pressed)
    13    #     or
    14    #     not brake_is_pressed
    15    # ):
    16    if (
    17        (not (key_is_close and start_is_pressed))
    18        (not and)
    19        (not brake_is_pressed)
    20    ):
    21        return 'OFF'
    22
    23    return 'ON'
    

    the terminal is my friend, and shows SyntaxError

    SyntaxError: invalid syntax
    

    I cannot negate and this way

  • I “factor” out the nots

     1def starter(
     2        key_is_close, start_is_pressed,
     3        brake_is_pressed=False,
     4    ):
     5    # if brake_is_pressed == False:
     6    # if not brake_is_pressed == True:
     7    # if not brake_is_pressed:
     8    #     return 'OFF'
     9
    10    # if not (key_is_close and start_is_pressed):
    11    # if (
    12    #     not (key_is_close and start_is_pressed)
    13    #     or
    14    #     not brake_is_pressed
    15    # ):
    16    # if (
    17    #     (not (key_is_close and start_is_pressed))
    18    #     (not and)
    19    #     (not brake_is_pressed)
    20    # ):
    21    if not (
    22        (key_is_close and start_is_pressed)
    23        and
    24        (brake_is_pressed)
    25    ):
    26        return 'OFF'
    27
    28    return 'ON'
    

    the test is green again

  • I remove the commented lines

     1def starter(
     2        key_is_close, start_is_pressed,
     3        brake_is_pressed=False,
     4    ):
     5    if not (
     6        key_is_close
     7        and start_is_pressed
     8        and brake_is_pressed
     9    ):
    10        return 'OFF'
    11
    12    return 'ON'
    

    this is what happens when the starter function is called

    • it returns ‘OFF’ if the key is far from the starter OR the start button is NOT pressed OR the brake is NOT pressed

    • it returns ‘ON’ if none of the conditions are met

  • I add an assertion for when the key is close, the brake is NOT pressed and the start button is NOT pressed, in test_key_close_brake_not_pressed in test_car.py

    key

    brake

    start

    output

    close

    NOT pressed

    pressed

    OFF

    close

    NOT pressed

    NOT pressed

    OFF

    26    def test_key_close_brake_not_pressed(self):
    27        reality = src.car.starter(
    28            key_is_close=True,
    29            brake_is_pressed=False,
    30            start_is_pressed=True,
    31        )
    32        self.assertEqual(reality, OFF)
    33
    34        reality = src.car.starter(
    35            key_is_close=True,
    36            brake_is_pressed=False,
    37            start_is_pressed=False,
    38        )
    39        self.assertEqual(reality, OFF)
    40
    41    def test_key_far(self):
    

    the test is still green


test_key_far_brake_pressed

The truth table for when the key is far from the starter and the brake is being pressed, is:

key

brake

start

output

far

pressed

pressed

OFF

far

pressed

NOT pressed

OFF

  • I add a value for the brake_is_pressed parameter to the first assertion in test_key_close for the case where the key is far from the starter, the brake is being pressed and the start button is pressed

    key

    brake

    start

    output

    far

    pressed

    pressed

    OFF

    34        reality = src.car.starter(
    35            key_is_close=True,
    36            brake_is_pressed=False,
    37            start_is_pressed=False,
    38        )
    39        self.assertEqual(reality, OFF)
    40
    41    def test_key_far(self):
    42        reality = src.car.starter(
    43            key_is_close=False,
    44            brake_is_pressed=True,
    45            start_is_pressed=True,
    46        )
    47        self.assertEqual(reality, OFF)
    

    the test is still green

  • I add a value for brake_is_pressed to the next assertion, for when the key is far from the starter, the brake is being pressed and the start button is NOT pressed

    key

    brake

    start

    output

    far

    pressed

    pressed

    OFF

    far

    pressed

    NOT pressed

    OFF

    40    def test_key_far(self):
    41        reality = src.car.starter(
    42            key_is_close=False,
    43            brake_is_pressed=True,
    44            start_is_pressed=True,
    45        )
    46        self.assertEqual(reality, OFF)
    47
    48        reality = src.car.starter(
    49            key_is_close=False,
    50            brake_is_pressed=True,
    51            start_is_pressed=False,
    52        )
    53        self.assertEqual(reality, OFF)
    54
    55
    56# Exceptions seen
    

    still green

  • I change the name of the test from test_key_far to test_key_far_brake_pressed

    34        reality = src.car.starter(
    35            key_is_close=True,
    36            brake_is_pressed=False,
    37            start_is_pressed=False,
    38        )
    39        self.assertEqual(reality, OFF)
    40
    41    def test_key_far_brake_pressed(self):
    42        reality = src.car.starter(
    43            key_is_close=False,
    44            brake_is_pressed=True,
    45            start_is_pressed=True,
    46        )
    47        self.assertEqual(reality, OFF)
    

test_key_far_brake_not_pressed

The truth table for when the key is far from the starter and the brake is NOT pressed is

key

brake

start

output

far

NOT pressed

pressed

OFF

far

NOT pressed

NOT pressed

OFF

  • I add a new test with an assertion for when the key is far from the starter, the brake is NOT pressed and the start button is pressed

    key

    brake

    start

    output

    far

    NOT pressed

    pressed

    OFF

    48        reality = src.car.starter(
    49            key_is_close=False,
    50            brake_is_pressed=True,
    51            start_is_pressed=False,
    52        )
    53        self.assertEqual(reality, OFF)
    54
    55    def test_key_far_brake_not_pressed(self):
    56        reality = src.car.starter(
    57            key_is_close=False,
    58            brake_is_pressed=False,
    59            start_is_pressed=True,
    60        )
    61        self.assertEqual(reality, OFF)
    62
    63
    64# Exceptions seen
    

    green

  • I add an assertion for when the key is far from the starter, the brake is NOT pressed and the start button is NOT pressed

    key

    brake

    start

    output

    far

    NOT pressed

    pressed

    OFF

    far

    NOT pressed

    NOT pressed

    OFF

    56    def test_key_far_brake_not_pressed(self):
    57        reality = src.car.starter(
    58            key_is_close=False,
    59            brake_is_pressed=False,
    60            start_is_pressed=True,
    61        )
    62        self.assertEqual(reality, OFF)
    63
    64        reality = src.car.starter(
    65            key_is_close=False,
    66            brake_is_pressed=False,
    67            start_is_pressed=False,
    68        )
    69        self.assertEqual(reality, OFF)
    70
    71
    72# Exceptions seen
    

    still green

  • I call the starter function directly in test_key_far_brake_not_pressed, I do not need the reality variable because it is only used once in each assertion

    56    def test_key_far_brake_not_pressed(self):
    57        reality = src.car.starter(
    58            key_is_close=False,
    59            brake_is_pressed=False,
    60            start_is_pressed=True,
    61        )
    62        # self.assertEqual(reality, OFF)
    63        self.assertEqual(
    64            src.car.starter(
    65                key_is_close=False,
    66                brake_is_pressed=False,
    67                start_is_pressed=True,
    68            ),
    69            OFF
    70        )
    71
    72        reality = src.car.starter(
    73            key_is_close=False,
    74            brake_is_pressed=False,
    75            start_is_pressed=False,
    76        )
    77        # self.assertEqual(reality, OFF)
    78        self.assertEqual(
    79            src.car.starter(
    80                key_is_close=False,
    81                brake_is_pressed=False,
    82                start_is_pressed=False,
    83            ),
    84            OFF
    85        )
    

    the test is still green

  • I remove the commented lines and reality variables

    56    def test_key_far_brake_not_pressed(self):
    57        self.assertEqual(
    58            src.car.starter(
    59                key_is_close=False,
    60                brake_is_pressed=False,
    61                start_is_pressed=True,
    62            ),
    63            OFF
    64        )
    65
    66        self.assertEqual(
    67            src.car.starter(
    68                key_is_close=False,
    69                brake_is_pressed=False,
    70                start_is_pressed=False,
    71            ),
    72            OFF
    73        )
    74
    75
    76# Exceptions seen
    
  • I do the same thing in test_key_far_brake_pressed

    41    def test_key_far_brake_pressed(self):
    42        reality = src.car.starter(
    43            key_is_close=False,
    44            brake_is_pressed=True,
    45            start_is_pressed=True,
    46        )
    47        # self.assertEqual(reality, OFF)
    48        self.assertEqual(
    49                src.car.starter(
    50                key_is_close=False,
    51                brake_is_pressed=True,
    52                start_is_pressed=True,
    53            ),
    54            OFF
    55        )
    56
    57        reality = src.car.starter(
    58            key_is_close=False,
    59            brake_is_pressed=True,
    60            start_is_pressed=False,
    61        )
    62        # self.assertEqual(reality, OFF)
    63        self.assertEqual(
    64            src.car.starter(
    65                key_is_close=False,
    66                brake_is_pressed=True,
    67                start_is_pressed=False,
    68            ),
    69            OFF
    70        )
    71
    72    def test_key_far_brake_not_pressed(self):
    

    still green

  • I remove the commented lines and reality variables from test_key_far_brake_pressed

    41    def test_key_far_brake_pressed(self):
    42        self.assertEqual(
    43                src.car.starter(
    44                key_is_close=False,
    45                brake_is_pressed=True,
    46                start_is_pressed=True,
    47            ),
    48            OFF
    49        )
    50
    51        self.assertEqual(
    52            src.car.starter(
    53                key_is_close=False,
    54                brake_is_pressed=True,
    55                start_is_pressed=False,
    56            ),
    57            OFF
    58        )
    59
    60    def test_key_far_brake_not_pressed(self):
    
  • on to test_key_close_brake_not_pressed

    26    def test_key_close_brake_not_pressed(self):
    27        reality = src.car.starter(
    28            key_is_close=True,
    29            brake_is_pressed=False,
    30            start_is_pressed=True,
    31        )
    32        # self.assertEqual(reality, OFF)
    33        self.assertEqual(
    34            src.car.starter(
    35                key_is_close=True,
    36                brake_is_pressed=False,
    37                start_is_pressed=True,
    38            ),
    39            OFF
    40        )
    41
    42        reality = src.car.starter(
    43            key_is_close=True,
    44            brake_is_pressed=False,
    45            start_is_pressed=False,
    46        )
    47        # self.assertEqual(reality, OFF)
    48        self.assertEqual(
    49            src.car.starter(
    50                key_is_close=True,
    51                brake_is_pressed=False,
    52                start_is_pressed=False,
    53            ),
    54            OFF
    55        )
    56
    57    def test_key_far_brake_pressed(self):
    

    green

  • I remove the commented lines and reality variables from test_key_close_brake_not_pressed

    26    def test_key_close_brake_not_pressed(self):
    27        self.assertEqual(
    28            src.car.starter(
    29                key_is_close=True,
    30                brake_is_pressed=False,
    31                start_is_pressed=True,
    32            ),
    33            OFF
    34        )
    35
    36        self.assertEqual(
    37            src.car.starter(
    38                key_is_close=True,
    39                brake_is_pressed=False,
    40                start_is_pressed=False,
    41            ),
    42            OFF
    43        )
    44
    45    def test_key_far_brake_pressed(self):
    
  • I call the starter function directly in test_key_close_brake_pressed

    10    def test_key_close_brake_pressed(self):
    11        my_expectation = 'ON'
    12        reality = src.car.starter(
    13            key_is_close=True,
    14            brake_is_pressed=True,
    15            start_is_pressed=True,
    16        )
    17        # self.assertEqual(reality, my_expectation)
    18        self.assertEqual(
    19            src.car.starter(
    20                key_is_close=True,
    21                brake_is_pressed=True,
    22                start_is_pressed=True,
    23            ),
    24            'ON'
    25        )
    26
    27        reality = src.car.starter(
    28            key_is_close=True,
    29            brake_is_pressed=True,
    30            start_is_pressed=False,
    31        )
    32        # self.assertEqual(reality, OFF)
    33        self.assertEqual(
    34            src.car.starter(
    35                key_is_close=True,
    36                brake_is_pressed=True,
    37                start_is_pressed=False,
    38            ),
    39            OFF
    40        )
    41
    42    def test_key_close_brake_not_pressed(self):
    

    still green

  • I remove the commented lines and unused variables from test_key_close_brake_pressed

    10    def test_key_close_brake_pressed(self):
    11        self.assertEqual(
    12            src.car.starter(
    13                key_is_close=True,
    14                brake_is_pressed=True,
    15                start_is_pressed=True,
    16            ),
    17            'ON'
    18        )
    19
    20        self.assertEqual(
    21            src.car.starter(
    22                key_is_close=True,
    23                brake_is_pressed=True,
    24                start_is_pressed=False,
    25            ),
    26            OFF
    27        )
    28
    29    def test_key_close_brake_not_pressed(self):
    

test_key_close_brake_pressed_w_gear

the truth table for the car starter is

key

brake

start

output

close

pressed

pressed

ON

close

pressed

NOT pressed

OFF

close

NOT pressed

pressed

OFF

close

NOT pressed

NOT pressed

OFF

key

brake

start

output

far

pressed

pressed

OFF

far

pressed

NOT pressed

OFF

far

NOT pressed

pressed

OFF

far

NOT pressed

NOT pressed

OFF

I want to make sure the car is in park before it can start, so it does not immediately move when it is turned on (that would be a problem). The inputs will then be

  • is the key close to the starter?

  • is the brake being pressed?

  • was the start button pressed?

  • is the gear in park?

and the truth table for when the key is close and the brake is being pressed, is:

key

brake

start

gear

output

close

pressed

pressed

in park

ON

close

pressed

pressed

NOT in park

OFF

close

pressed

NOT pressed

in park

OFF

close

pressed

NOT pressed

NOT in park

OFF


RED: make it fail


I add a value for in_park to the assertion for the case where the key is close, the brake is being pressed, the start button is pressed and the car gear is in park, to test_key_close_brake_pressed

key

brake

start

gear

output

close

pressed

pressed

in park

ON

10      def test_key_close_brake_pressed(self):
11          self.assertEqual(
12              src.car.starter(
13                  key_is_close=True,
14                  brake_is_pressed=True,
15                  start_is_pressed=True,
16                  in_park=True,
17              ),
18              'ON'
19          )

the terminal shows TypeError

TypeError: starter() got an unexpected keyword argument 'in_park'

because the test called the starter function with 4 keyword arguments (key_is_close, brake_is_pressed, start_is_pressed and in_park) and the definition only allows calls with 2 required arguments (key_is_close and start_is_pressed) and 1 optional argument (brake_is_pressed)


GREEN: make it pass



REFACTOR: make it better


  • I add an assertion for when the key is close, the brake is being pressed, the start button is pressed and the car gear is NOT in park

    key

    brake

    start

    gear

    output

    close

    pressed

    pressed

    in park

    ON

    close

    pressed

    pressed

    NOT in park

    OFF

    10    def test_key_close_brake_pressed(self):
    11        self.assertEqual(
    12            src.car.starter(
    13                key_is_close=True,
    14                brake_is_pressed=True,
    15                start_is_pressed=True,
    16                in_park=True,
    17            ),
    18            'ON'
    19        )
    20
    21        self.assertEqual(
    22            src.car.starter(
    23                key_is_close=True,
    24                brake_is_pressed=True,
    25                start_is_pressed=True,
    26                in_park=False,
    27            ),
    28            OFF
    29        )
    30
    31        self.assertEqual(
    32            src.car.starter(
    33                key_is_close=True,
    34                brake_is_pressed=True,
    35                start_is_pressed=False,
    36            ),
    37            OFF
    38        )
    

    the terminal is my friend, and shows AssertionError

    AssertionError: 'ON' != 'OFF'
    

    because the starter function returns ‘ON’ and the test expects ‘OFF’

  • I add an if statement to the starter function in car.py

     1def starter(
     2        key_is_close, start_is_pressed,
     3        brake_is_pressed=False, in_park=False,
     4    ):
     5    if in_park == False:
     6        return 'OFF'
     7
     8    if not (
     9        key_is_close
    10        and start_is_pressed
    11        and brake_is_pressed
    12    ):
    13        return 'OFF'
    14
    15    return 'ON'
    

    the test passes

  • I use Logical Negation (NOT) to write it in terms of True

    5    # if in_park == False:
    6    if not in_park == True:
    7        return 'OFF'
    

    the test is still green

  • I remove == True

    5    # if in_park == False:
    6    # if not in_park == True:
    7    if not in_park:
    8        return 'OFF'
    

    still green, because if something == False is the same as if not something == True is the same as if not something

  • I use Logical Disjunction (OR) to put the two if statements together because they both return ‘OFF’

     1def starter(
     2        key_is_close, start_is_pressed,
     3        brake_is_pressed=False, in_park=False,
     4    ):
     5    # if in_park == False:
     6    # if not in_park == True:
     7    # if not in_park:
     8    #     return 'OFF'
     9
    10    # if not (
    11    #     key_is_close
    12    #     and start_is_pressed
    13    #     and brake_is_pressed
    14    # ):
    15    if (
    16        not (
    17            key_is_close
    18            and start_is_pressed
    19            and brake_is_pressed
    20        ) or not in_park
    21    ):
    22        return 'OFF'
    23
    24    return 'ON'
    

    that is one long confusing statement

  • I write the new if statement in terms of not

    10    # if not (
    11    #     key_is_close
    12    #     and start_is_pressed
    13    #     and brake_is_pressed
    14    # ):
    15    # if (
    16    #     not (
    17    #         key_is_close
    18    #         and start_is_pressed
    19    #         and brake_is_pressed
    20    #     ) or not in_park
    21    # ):
    22    if (
    23        (not (
    24            key_is_close
    25            and start_is_pressed
    26            and brake_is_pressed
    27        ))
    28        (not and)
    29        (not in_park)
    30    ):
    31        return 'OFF'
    32
    33    return 'ON'
    

    the terminal is my friend, and shows SyntaxError

    SyntaxError: invalid syntax
    

    I cannot negate and this way

  • I factor out the nots

    10    # if not (
    11    #     key_is_close
    12    #     and start_is_pressed
    13    #     and brake_is_pressed
    14    # ):
    15    # if (
    16    #     not (
    17    #         key_is_close
    18    #         and start_is_pressed
    19    #         and brake_is_pressed
    20    #     ) or not in_park
    21    # ):
    22    # if (
    23    #     (not (
    24    #         key_is_close
    25    #         and start_is_pressed
    26    #         and brake_is_pressed
    27    #     ))
    28    #     (not and)
    29    #     (not in_park)
    30    # ):
    31    if not (
    32        (
    33            key_is_close
    34            and start_is_pressed
    35            and brake_is_pressed
    36        )
    37        and
    38        in_park
    39    ):
    40        return 'OFF'
    41
    42    return 'ON'
    

    the test is green again

  • I remove the commented lines

     1def starter(
     2        key_is_close, start_is_pressed,
     3        brake_is_pressed=False, in_park=False,
     4    ):
     5    if not (
     6        key_is_close
     7        and start_is_pressed
     8        and brake_is_pressed
     9        and in_park
    10    ):
    11        return 'OFF'
    12
    13    return 'ON'
    

    this is what happens when the starter function is called

    • it returns ‘OFF’ if the key is far from the starter OR the start button is NOT pressed OR the brake is NOT pressed OR the car gear is NOT in park

    • it returns ‘ON’ if none of the conditions are met

  • I add a value for the in_park parameter in the next assertion for when the key is close, the brake is being pressed, the start button is NOT pressed and the car gear is in park, in test_key_close_brake_pressed in test_car.py

    key

    brake

    start

    gear

    output

    close

    pressed

    pressed

    in park

    ON

    close

    pressed

    pressed

    NOT in park

    OFF

    close

    pressed

    NOT pressed

    in park

    OFF

    10    def test_key_close_brake_pressed(self):
    11        self.assertEqual(
    12            src.car.starter(
    13                key_is_close=True,
    14                brake_is_pressed=True,
    15                start_is_pressed=True,
    16                in_park=True,
    17            ),
    18            'ON'
    19        )
    20
    21        self.assertEqual(
    22            src.car.starter(
    23                key_is_close=True,
    24                brake_is_pressed=True,
    25                start_is_pressed=True,
    26                in_park=False,
    27            ),
    28            OFF
    29        )
    30
    31        self.assertEqual(
    32            src.car.starter(
    33                key_is_close=True,
    34                brake_is_pressed=True,
    35                start_is_pressed=False,
    36                in_park=True,
    37            ),
    38            OFF
    39        )
    40
    41    def test_key_close_brake_not_pressed(self):
    

    still green

  • I add an assertion for when the key is close, the brake is being pressed, the start button is NOT pressed and the car gear is NOT in park

    key

    brake

    start

    gear

    output

    close

    pressed

    pressed

    in park

    ON

    close

    pressed

    pressed

    NOT in park

    OFF

    close

    pressed

    NOT pressed

    in park

    OFF

    close

    pressed

    NOT pressed

    NOT in park

    OFF

    10    def test_key_close_brake_pressed(self):
    11        self.assertEqual(
    12            src.car.starter(
    13                key_is_close=True,
    14                brake_is_pressed=True,
    15                start_is_pressed=True,
    16                in_park=True,
    17            ),
    18            'ON'
    19        )
    20
    21        self.assertEqual(
    22            src.car.starter(
    23                key_is_close=True,
    24                brake_is_pressed=True,
    25                start_is_pressed=True,
    26                in_park=False,
    27            ),
    28            OFF
    29        )
    30
    31        self.assertEqual(
    32            src.car.starter(
    33                key_is_close=True,
    34                brake_is_pressed=True,
    35                start_is_pressed=False,
    36                in_park=True,
    37            ),
    38            OFF
    39        )
    40
    41        self.assertEqual(
    42            src.car.starter(
    43                key_is_close=True,
    44                brake_is_pressed=True,
    45                start_is_pressed=False,
    46                in_park=False,
    47            ),
    48            OFF
    49        )
    50
    51    def test_key_close_brake_not_pressed(self):
    

    green

  • I change the name of the test from test_key_close_brake_pressed to test_key_close_brake_pressed_w_gear

     8class TestCar(unittest.TestCase):
     9
    10    def test_key_close_brake_pressed_w_gear(self):
    11        self.assertEqual(
    12            src.car.starter(
    13                key_is_close=True,
    14                brake_is_pressed=True,
    15                start_is_pressed=True,
    16                in_park=True,
    17            ),
    18            'ON'
    19        )
    

test_key_close_brake_not_pressed_w_gear

The truth table for when the key is close and the brake is NOT pressed is

key

brake

start

gear

output

close

NOT pressed

pressed

in park

OFF

close

NOT pressed

pressed

NOT in park

OFF

close

NOT pressed

NOT pressed

in park

OFF

close

NOT pressed

NOT pressed

NOT in park

OFF

  • I add a value for the in_park parameter to the first assertion in test_key_close_brake_not_pressed for when the key is close, the brake is NOT pressed, the start button is pressed and the car gear is in park

    key

    brake

    start

    gear

    output

    close

    NOT pressed

    pressed

    in park

    OFF

    51    def test_key_close_brake_not_pressed(self):
    52        self.assertEqual(
    53            src.car.starter(
    54                key_is_close=True,
    55                brake_is_pressed=False,
    56                start_is_pressed=True,
    57                in_park=True,
    58            ),
    59            OFF
    60        )
    

    still green

  • I add an assertion for when the key is close, the brake is NOT pressed, the start button is pressed and the car gear is NOT in park

    key

    brake

    start

    gear

    output

    close

    NOT pressed

    pressed

    in park

    OFF

    close

    NOT pressed

    pressed

    NOT in park

    OFF

    51    def test_key_close_brake_not_pressed(self):
    52        self.assertEqual(
    53            src.car.starter(
    54                key_is_close=True,
    55                brake_is_pressed=False,
    56                start_is_pressed=True,
    57                in_park=True,
    58            ),
    59            OFF
    60        )
    61
    62        self.assertEqual(
    63            src.car.starter(
    64                key_is_close=True,
    65                brake_is_pressed=False,
    66                start_is_pressed=True,
    67                in_park=False,
    68            ),
    69            OFF
    70        )
    71
    72        self.assertEqual(
    73            src.car.starter(
    74                key_is_close=True,
    75                brake_is_pressed=False,
    76                start_is_pressed=False,
    77            ),
    78            OFF
    79        )
    80
    81    def test_key_far_brake_pressed(self):
    

    the test is still green

  • I add a value for in_park to the next assertion, for when the key is close, the brake is NOT pressed, the start button is NOT pressed and the car gear is in park

    key

    brake

    start

    gear

    output

    close

    NOT pressed

    pressed

    in park

    OFF

    close

    NOT pressed

    pressed

    NOT in park

    OFF

    close

    NOT pressed

    NOT pressed

    in park

    OFF

    51    def test_key_close_brake_not_pressed(self):
    52        self.assertEqual(
    53            src.car.starter(
    54                key_is_close=True,
    55                brake_is_pressed=False,
    56                start_is_pressed=True,
    57                in_park=True,
    58            ),
    59            OFF
    60        )
    61
    62        self.assertEqual(
    63            src.car.starter(
    64                key_is_close=True,
    65                brake_is_pressed=False,
    66                start_is_pressed=True,
    67                in_park=False,
    68            ),
    69            OFF
    70        )
    71
    72        self.assertEqual(
    73            src.car.starter(
    74                key_is_close=True,
    75                brake_is_pressed=False,
    76                start_is_pressed=False,
    77                in_park=True,
    78            ),
    79            OFF
    80        )
    81
    82    def test_key_far_brake_pressed(self):
    

    still green

  • I add an assertion for when the key is close, the brake is NOT pressed, the start button is NOT pressed and the car gear is NOT in park

    key

    brake

    start

    gear

    output

    close

    NOT pressed

    pressed

    in park

    OFF

    close

    NOT pressed

    pressed

    NOT in park

    OFF

    close

    NOT pressed

    NOT pressed

    in park

    OFF

    close

    NOT pressed

    NOT pressed

    NOT in park

    OFF

    51    def test_key_close_brake_not_pressed(self):
    52        self.assertEqual(
    53            src.car.starter(
    54                key_is_close=True,
    55                brake_is_pressed=False,
    56                start_is_pressed=True,
    57                in_park=True,
    58            ),
    59            OFF
    60        )
    61
    62        self.assertEqual(
    63            src.car.starter(
    64                key_is_close=True,
    65                brake_is_pressed=False,
    66                start_is_pressed=True,
    67                in_park=False,
    68            ),
    69            OFF
    70        )
    71
    72        self.assertEqual(
    73            src.car.starter(
    74                key_is_close=True,
    75                brake_is_pressed=False,
    76                start_is_pressed=False,
    77                in_park=True,
    78            ),
    79            OFF
    80        )
    81
    82        self.assertEqual(
    83            src.car.starter(
    84                key_is_close=True,
    85                brake_is_pressed=False,
    86                start_is_pressed=False,
    87                in_park=False,
    88            ),
    89            OFF
    90        )
    91
    92    def test_key_far_brake_pressed(self):
    

    green

  • I change the name of the test from test_key_close_brake_not_pressed to test_key_close_brake_not_pressed_w_gear

    41        self.assertEqual(
    42            src.car.starter(
    43                key_is_close=True,
    44                brake_is_pressed=True,
    45                start_is_pressed=False,
    46                in_park=False,
    47            ),
    48            OFF
    49        )
    50
    51    def test_key_close_brake_not_pressed_w_gear(self):
    52        self.assertEqual(
    53            src.car.starter(
    54                key_is_close=True,
    55                brake_is_pressed=False,
    56                start_is_pressed=True,
    57                in_park=True,
    58            ),
    59            OFF
    60        )
    

test_key_far_brake_pressed_w_gear

The truth table for when the key is far from the starter and the brake is being pressed is

key

brake

start

gear

output

far

pressed

pressed

in park

OFF

far

pressed

pressed

NOT in park

OFF

far

pressed

NOT pressed

in park

OFF

far

pressed

NOT pressed

NOT in park

OFF

  • I add a value for the in_park parameter in the first assertion of test_key_far_brake_pressed, for when the key is far from the starter, the brake is being pressed, the start button is pressed, and the car gear is in park

    key

    brake

    start

    gear

    output

    far

    pressed

    pressed

    in park

    OFF

     92    def test_key_far_brake_pressed(self):
     93        self.assertEqual(
     94            src.car.starter(
     95                key_is_close=False,
     96                brake_is_pressed=True,
     97                start_is_pressed=True,
     98                in_park=True,
     99            ),
    100            OFF
    101        )
    

    still green

  • I add an assertion for when the key is far from the starter, the brake is being pressed, the start button is pressed and the car gear is NOT in park

    key

    brake

    start

    gear

    output

    far

    pressed

    pressed

    in park

    OFF

    far

    pressed

    pressed

    NOT in park

    OFF

     92    def test_key_far_brake_pressed(self):
     93        self.assertEqual(
     94            src.car.starter(
     95                key_is_close=False,
     96                brake_is_pressed=True,
     97                start_is_pressed=True,
     98                in_park=True,
     99            ),
    100            OFF
    101        )
    102
    103        self.assertEqual(
    104            src.car.starter(
    105                key_is_close=False,
    106                brake_is_pressed=True,
    107                start_is_pressed=True,
    108                in_park=False,
    109            ),
    110            OFF
    111        )
    112
    113        self.assertEqual(
    114            src.car.starter(
    115                key_is_close=False,
    116                brake_is_pressed=True,
    117                start_is_pressed=False,
    118            ),
    119            OFF
    120        )
    121
    122    def test_key_far_brake_not_pressed(self):
    

    still green

  • I add a value for the in_park parameter to the next assertion for when the key is far from the starter, the brake is being pressed, the start button is NOT pressed, and the car gear is in park

    key

    brake

    start

    gear

    output

    far

    pressed

    pressed

    in park

    OFF

    far

    pressed

    pressed

    NOT in park

    OFF

    far

    pressed

    NOT pressed

    in park

    OFF

     92    def test_key_far_brake_pressed(self):
     93        self.assertEqual(
     94            src.car.starter(
     95                key_is_close=False,
     96                brake_is_pressed=True,
     97                start_is_pressed=True,
     98                in_park=True,
     99            ),
    100            OFF
    101        )
    102
    103        self.assertEqual(
    104            src.car.starter(
    105                key_is_close=False,
    106                brake_is_pressed=True,
    107                start_is_pressed=True,
    108                in_park=False,
    109            ),
    110            OFF
    111        )
    112
    113        self.assertEqual(
    114            src.car.starter(
    115                key_is_close=False,
    116                brake_is_pressed=True,
    117                start_is_pressed=False,
    118                in_park=True,
    119            ),
    120            OFF
    121        )
    122
    123    def test_key_far_brake_not_pressed(self):
    

    the test is still green

  • I add an assertion for when the key is far from the starter, the brake is being pressed, the start button is NOT pressed, and the car gear is NOT in park

    key

    brake

    start

    gear

    output

    far

    pressed

    pressed

    in park

    OFF

    far

    pressed

    pressed

    NOT in park

    OFF

    far

    pressed

    NOT pressed

    in park

    OFF

    far

    pressed

    NOT pressed

    NOT in park

    OFF

     92    def test_key_far_brake_pressed(self):
     93        self.assertEqual(
     94            src.car.starter(
     95                key_is_close=False,
     96                brake_is_pressed=True,
     97                start_is_pressed=True,
     98                in_park=True,
     99            ),
    100            OFF
    101        )
    102
    103        self.assertEqual(
    104            src.car.starter(
    105                key_is_close=False,
    106                brake_is_pressed=True,
    107                start_is_pressed=True,
    108                in_park=False,
    109            ),
    110            OFF
    111        )
    112
    113        self.assertEqual(
    114            src.car.starter(
    115                key_is_close=False,
    116                brake_is_pressed=True,
    117                start_is_pressed=False,
    118                in_park=True,
    119            ),
    120            OFF
    121        )
    122
    123        self.assertEqual(
    124            src.car.starter(
    125                key_is_close=False,
    126                brake_is_pressed=True,
    127                start_is_pressed=False,
    128                in_park=False,
    129            ),
    130            OFF
    131        )
    132
    133    def test_key_far_brake_not_pressed(self):
    

    still green

  • I change the name of the test from test_key_far_brake_pressed to test_key_far_brake_pressed_w_gear

     82        self.assertEqual(
     83            src.car.starter(
     84                key_is_close=True,
     85                brake_is_pressed=False,
     86                start_is_pressed=False,
     87                in_park=False,
     88            ),
     89            OFF
     90        )
     91
     92    def test_key_far_brake_pressed_w_gear(self):
     93        self.assertEqual(
     94            src.car.starter(
     95                key_is_close=False,
     96                brake_is_pressed=True,
     97                start_is_pressed=True,
     98                in_park=True,
     99            ),
    100            OFF
    101        )
    

test_key_far_brake_not_pressed_w_gear

The truth table for when the key is far from the starter and the brake is NOT pressed is

key

brake

start

gear

output

far

NOT pressed

pressed

in park

OFF

far

NOT pressed

pressed

NOT in park

OFF

far

NOT pressed

NOT pressed

in park

OFF

far

NOT pressed

NOT pressed

NOT in park

OFF

  • I add a value for the in_park parameter to the first assertion in test_key_far_brake_not_pressed, for when the key is far from the starter, the brake is NOT pressed, the start button is pressed, and the car gear is in park

    key

    brake

    start

    gear

    output

    far

    NOT pressed

    pressed

    in park

    OFF

    133    def test_key_far_brake_not_pressed(self):
    134        self.assertEqual(
    135            src.car.starter(
    136                key_is_close=False,
    137                brake_is_pressed=False,
    138                start_is_pressed=True,
    139                in_park=True,
    140            ),
    141            OFF
    142        )
    

    the test is still green

  • I add an assertion for when the key is far from the starter, the brake is NOT pressed, the start button is pressed, and the car gear is NOT in park

    key

    brake

    start

    gear

    output

    far

    NOT pressed

    pressed

    in park

    OFF

    far

    NOT pressed

    pressed

    NOT in park

    OFF

    133    def test_key_far_brake_not_pressed(self):
    134        self.assertEqual(
    135            src.car.starter(
    136                key_is_close=False,
    137                brake_is_pressed=False,
    138                start_is_pressed=True,
    139                in_park=True,
    140            ),
    141            OFF
    142        )
    143
    144        self.assertEqual(
    145            src.car.starter(
    146                key_is_close=False,
    147                brake_is_pressed=False,
    148                start_is_pressed=True,
    149                in_park=False,
    150            ),
    151            OFF
    152        )
    153
    154        self.assertEqual(
    155            src.car.starter(
    156                key_is_close=False,
    157                brake_is_pressed=False,
    158                start_is_pressed=False,
    159            ),
    160            OFF
    161        )
    162
    163
    164# Exceptions seen
    

    still green

  • I add a value for the in_park parameter to the next assertion, for when the key is far from the starter, the brake is NOT pressed, the start button is NOT pressed, and the car gear is in park

    key

    brake

    start

    gear

    output

    far

    NOT pressed

    pressed

    in park

    OFF

    far

    NOT pressed

    pressed

    NOT in park

    OFF

    far

    NOT pressed

    NOT pressed

    in park

    OFF

    133    def test_key_far_brake_not_pressed(self):
    134        self.assertEqual(
    135            src.car.starter(
    136                key_is_close=False,
    137                brake_is_pressed=False,
    138                start_is_pressed=True,
    139                in_park=True,
    140            ),
    141            OFF
    142        )
    143
    144        self.assertEqual(
    145            src.car.starter(
    146                key_is_close=False,
    147                brake_is_pressed=False,
    148                start_is_pressed=True,
    149                in_park=False,
    150            ),
    151            OFF
    152        )
    153
    154        self.assertEqual(
    155            src.car.starter(
    156                key_is_close=False,
    157                brake_is_pressed=False,
    158                start_is_pressed=False,
    159                in_park=True,
    160            ),
    161            OFF
    162        )
    

    green

  • I add an assertion for when the key is far from the starter, the brake is NOT pressed, the start button is NOT pressed, and the car gear is NOT in park

    key

    brake

    start

    gear

    output

    far

    NOT pressed

    pressed

    in park

    OFF

    far

    NOT pressed

    pressed

    NOT in park

    OFF

    far

    NOT pressed

    NOT pressed

    in park

    OFF

    far

    NOT pressed

    NOT pressed

    NOT in park

    OFF

    133    def test_key_far_brake_not_pressed(self):
    134        self.assertEqual(
    135            src.car.starter(
    136                key_is_close=False,
    137                brake_is_pressed=False,
    138                start_is_pressed=True,
    139                in_park=True,
    140            ),
    141            OFF
    142        )
    143
    144        self.assertEqual(
    145            src.car.starter(
    146                key_is_close=False,
    147                brake_is_pressed=False,
    148                start_is_pressed=True,
    149                in_park=False,
    150            ),
    151            OFF
    152        )
    153
    154        self.assertEqual(
    155            src.car.starter(
    156                key_is_close=False,
    157                brake_is_pressed=False,
    158                start_is_pressed=False,
    159                in_park=True,
    160            ),
    161            OFF
    162        )
    163
    164        self.assertEqual(
    165            src.car.starter(
    166                key_is_close=False,
    167                brake_is_pressed=False,
    168                start_is_pressed=False,
    169                in_park=False,
    170            ),
    171            OFF
    172        )
    173
    174
    175# Exceptions seen
    

    all the tests are still green

  • I change the name of the test from test_key_far_brake_not_pressed to test_key_far_brake_not_pressed_w_gear

    123        self.assertEqual(
    124            src.car.starter(
    125                key_is_close=False,
    126                brake_is_pressed=True,
    127                start_is_pressed=False,
    128                in_park=False,
    129            ),
    130            OFF
    131        )
    132
    133    def test_key_far_brake_not_pressed_w_gear(self):
    134        self.assertEqual(
    135            src.car.starter(
    136                key_is_close=False,
    137                brake_is_pressed=False,
    138                start_is_pressed=True,
    139                in_park=True,
    140            ),
    141            OFF
    142        )
    

close the project

  • I close test_car.py and car.py in the editor

  • I click in the terminal, 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 car

    cd ..
    

    the terminal shows

    .../pumping_python
    

    I am back in the pumping_python directory


review

I ran tests for a car with these inputs:

  • is the key close to the starter?

  • is the brake being pressed?

  • was the start button pressed?

  • is the car in park?

the inputs gave me this truth table

key

brake

start

gear

output

close

pressed

pressed

in park

ON

close

pressed

pressed

NOT in park

OFF

close

pressed

NOT pressed

in park

OFF

close

pressed

NOT pressed

NOT in park

OFF

key

brake

start

gear

output

close

NOT pressed

pressed

in park

OFF

close

NOT pressed

pressed

NOT in park

OFF

close

NOT pressed

NOT pressed

in park

OFF

close

NOT pressed

NOT pressed

NOT in park

OFF

key

brake

start

gear

output

far

pressed

pressed

in park

OFF

far

pressed

pressed

NOT in park

OFF

far

pressed

NOT pressed

in park

OFF

far

pressed

NOT pressed

NOT in park

OFF

key

brake

start

gear

output

far

NOT pressed

pressed

in park

OFF

far

NOT pressed

pressed

NOT in park

OFF

far

NOT pressed

NOT pressed

in park

OFF

far

NOT pressed

NOT pressed

NOT in park

OFF

the only time I can start this car is when the key is close to the starter, the brake is being pressed, the start button is pressed and the car gear is in park.


code from the chapter

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


what is next?

you now know

Would you like to test making a calculator?


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