elevator

I want to make a elevator that heats up food or stays off, if the inputs are

  • is the door open?

  • was the start button pushed?

this is the truth table I get

door

start button

output

open

pushed

OFF

open

NOT pushed

OFF

closed

pushed

HEATING

closed

NOT pushed

OFF

preview

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

1

requirements


start the project

  • I name this project elevator

  • I open a terminal

  • I use uv to make a directory for the project

    uv init elevator
    

    the terminal shows

    Initialized project `elevator` at `.../pumping_python/elevator`
    

    then goes back to the command line

  • I change directory to the project

    cd elevator
    

    the terminal shows I am in the elevator folder

    .../pumping_python/elevator
    
  • 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/elevator.py
    
    New-Item src/elevator.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_elevator.py
    
    New-Item tests/test_elevator.py
    

    the terminal goes back to the command line

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

    Visual Studio Code opens test_elevator.py in the editor

  • I add the first failing test to test_elevator.py

    1import unittest
    2
    3
    4class Testelevator(unittest.TestCase):
    5
    6    def test_failure(self):
    7        self.assertFalse(True)
    
  • I go back to the terminal to make a requirements file for the Python packages I need

    echo "pytest" > requirements.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
       └── elevator.py
    ├── tests
       ├── __init__.py
       └── test_elevator.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 ================================
    ______________________ Testelevator.test_failure ________________________
    
    self = <tests.test_elevator.Testelevator testMethod=test_failure>
    
        def test_failure(self):
    >       self.assertFalse(True)
    E       AssertionError: True is not false
    
    tests/test_elevator.py:7: AssertionError
    ======================== short test summary info =========================
    FAILED tests/test_elevator.py::Testelevator::test_failure - AssertionError: True is not false
    =========================== 1 failed in X.YZs ============================
    

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

     4class Testelevator(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_open_door

The truth table for if the door is open is

door

start button

output

open

pushed

OFF

open

NOT pushed

OFF


RED: make it fail


I change test_failure to test_open_door, then add an assertion for when the door is open and the start button is pushed

door

start button

output

open

start

OFF

 4class Testelevator(unittest.TestCase):
 5
 6    def test_open_door(self):
 7        my_expectation = 'OFF'
 8
 9        reality = src.elevator.elevator(
10            door_is_open=True,
11            start_is_pushed=True,
12        )
13        self.assertEqual(reality, my_expectation)
14
15
16# Exceptions seen
17# 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.elevator
    2import unittest
    3
    4
    5class Testelevator(unittest.TestCase):
    

    the terminal is my friend, and shows AttributeError

    AttributeError: module 'src.elevator' has no attribute 'elevator'
    

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

  • I add a function named elevator to elevator.py

    1def elevator():
    2    return None
    

    the terminal is my friend, and shows TypeError

    TypeError: elevator() got an unexpected keyword argument 'door_is_open'
    

    because the test called the elevator function with 2 keyword arguments and this definition only allows calls with 0 arguments

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

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

    1def elevator(door_is_open):
    2    return None
    

    the terminal is my friend, and shows TypeError

    TypeError: elevator() got an unexpected keyword argument 'start_is_pushed'
    

    because the test called the elevator function with 2 keyword arguments and this definition only allows calls with 1 input

  • I add start_is_pushed to the function signature

    1def elevator(door_is_open, start_is_pushed):
    2    return None
    

    the terminal is my friend, and shows AssertionError

    AssertionError: None != 'OFF'
    

    the elevator function returned None and the test expects ‘OFF’

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

    1def elevator(door_is_open, start_is_pushed):
    2    return 'OFF'
    

    the test passes. The elevator function always returns OFF, it does not care about the inputs. Is this Contradiction?


REFACTOR: make it better


  • I add an assertion for when the door is open and the start button is NOT pushed, in test_elevator.py

    door

    start button

    output

    open

    pushed

    OFF

    open

    NOT pushed

    OFF

     7    def test_open_door(self):
     8        my_expectation = 'OFF'
     9
    10        reality = src.elevator.elevator(
    11            door_is_open=True,
    12            start_is_pushed=True,
    13        )
    14        self.assertEqual(reality, my_expectation)
    15
    16        reality = src.elevator.elevator(
    17            door_is_open=True,
    18            start_is_pushed=False,
    19        )
    20        self.assertEqual(reality, my_expectation)
    21
    22
    23# Exceptions seen
    

    the test is still green


test_closed_door

The truth table for if the door is closed is

door

start button

output

closed

pushed

HEATING

closed

NOT pushed

OFF


RED: make it fail


I add a test with an assertion for when the door is closed and the start button is pushed

door

start button

output

closed

pushed

HEATING

16          reality = src.elevator.elevator(
17              door_is_open=True,
18              start_is_pushed=False,
19          )
20          self.assertEqual(reality, my_expectation)
21
22      def test_closed_door(self):
23          my_expectation = 'HEATING'
24          reality = src.elevator.elevator(
25              door_is_open=False,
26              start_is_pushed=True,
27          )
28          self.assertEqual(reality, my_expectation)
29
30
31  # Exceptions seen

the terminal is my friend, and shows AssertionError

AssertionError: 'OFF' != 'HEATING'

because the elevator function returns ‘OFF’ and the test expects ‘HEATING’


GREEN: make it pass


I add an if statement to elevator.py

1def elevator(door_is_open, start_is_pushed):
2    if door_is_open == False:
3        if start_is_pushed == True:
4            return 'HEATING'
5    return 'OFF'

the test passes


REFACTOR: make it better


  • I add the bool built-in function

    1def elevator(door_is_open, start_is_pushed):
    2    # if door_is_open == False:
    3    if bool(door_is_open) == False:
    4        # if start_is_pushed == True:
    5        if bool(start_is_pushed) == True:
    6            return 'HEATING'
    7    return 'OFF'
    

    the test is still green

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

    1def elevator(door_is_open, start_is_pushed):
    2    # if door_is_open == False:
    3    # if bool(door_is_open) == False:
    4    if not bool(door_is_open) == True:
    5        # if start_is_pushed == True:
    6        if bool(start_is_pushed) == True:
    7            return 'HEATING'
    8    return 'OFF'
    

    still green

  • I remove == True

     1def elevator(door_is_open, start_is_pushed):
     2    # if door_is_open == False:
     3    # if bool(door_is_open) == False:
     4    # if not bool(door_is_open) == True:
     5    if not bool(door_is_open):
     6        # if start_is_pushed == True:
     7        # if bool(start_is_pushed) == True:
     8        if bool(start_is_pushed):
     9            return 'HEATING'
    10    return 'OFF'
    

    green

  • I remove bool

     1def elevator(door_is_open, start_is_pushed):
     2    # if door_is_open == False:
     3    # if bool(door_is_open) == False:
     4    # if not bool(door_is_open) == True:
     5    # if not bool(door_is_open):
     6    if not door_is_open:
     7        # if start_is_pushed == True:
     8        # if bool(start_is_pushed) == True:
     9        # if bool(start_is_pushed):
    10        if start_is_pushed:
    11            return 'HEATING'
    12    return 'OFF'
    

    still green, because

    • if bool(something) == False is the same as if not bool(something) == True is the same as if not something

    • if bool(something) == True is the same as if something

  • I use Logical Conjunction (AND) to put the two if statements together

     1def elevator(door_is_open, start_is_pushed):
     2    # if door_is_open == False:
     3    # if bool(door_is_open) == False:
     4    # if not bool(door_is_open) == True:
     5    # if not bool(door_is_open):
     6    # if not door_is_open:
     7        # if start_is_pushed == True:
     8        # if bool(start_is_pushed) == True:
     9        # if bool(start_is_pushed):
    10        # if start_is_pushed:
    11    if not door_is_open and start_is_pushed:
    12        return 'HEATING'
    13    return 'OFF'
    

    the test is still green

  • I remove the commented lines

    1def elevator(door_is_open, start_is_pushed):
    2    if not door_is_open and start_is_pushed:
    3        return 'HEATING'
    4    return 'OFF'
    

    This is what happens when the elevator function is called

    • it returns ‘HEATING’ if the door is closed AND the start button is pushed

    • it returns ‘OFF’ if the condition is not met

    is this Converse NonImplication?

  • I add an assertion for when the door is closed and the start button is NOT pushed to test_closed_door in test_elevator.py

    door

    start button

    output

    closed

    pushed

    HEATING

    closed

    NOT pushed

    OFF

    22    def test_closed_door(self):
    23        my_expectation = 'HEATING'
    24        reality = src.elevator.elevator(
    25            door_is_open=False,
    26            start_is_pushed=True,
    27        )
    28        self.assertEqual(reality, my_expectation)
    29
    30        my_expectation = 'OFF'
    31
    32        reality = src.elevator.elevator(
    33            door_is_open=False,
    34            start_is_pushed=False,
    35        )
    36        self.assertEqual(reality, my_expectation)
    37
    38
    39# Exceptions seen
    

    the test is still green


test_open_door_timer_set

So far, the truth table for the elevator is

door

start button

output

open

pushed

OFF

open

NOT pushed

OFF

closed

pushed

HEATING

closed

NOT pushed

OFF

I want the elevator to only heat up food when the timer is set, the inputs for the elevator will then be

  • is the door open?

  • is the timer set?

  • was the start button pushed?

and the truth table for when the door is open and the timer is set, will be

door

timer

start button

output

open

set

pushed

OFF

open

set

NOT pushed

OFF


RED: make it fail


I add a value for timer_is_set to the first assertion in test_open_door, for when the door is open, the timer is set and the start button is pushed

door

timer

start button

output

open

set

pushed

OFF

 7    def test_open_door(self):
 8        my_expectation = 'OFF'
 9
10        reality = src.elevator.elevator(
11            door_is_open=True,
12            timer_is_set=True,
13            start_is_pushed=True,
14        )
15        self.assertEqual(reality, my_expectation)

the terminal is my friend, and shows TypeError

TypeError: elevator() got an unexpected keyword argument 'timer_is_set'

because the test called the elevator function with 3 keyword arguments (door_is_open, timer_is_set and start_is_pushed) and the function only allows calls with 2 arguments (door_is_open and start_is_pushed)


GREEN: make it pass


  • I add timer_is_set to the function signature in elevator.py

    1def elevator(
    2        door_is_open, start_is_pushed,
    3        timer_is_set,
    4    ):
    5    if not door_is_open and start_is_pushed:
    6        return 'HEATING'
    7    return 'OFF'
    

    the terminal is my friend, and shows TypeError

    FAILED ...test_closed_door - TypeError: elevator() missing 1 required positional argument:...
    FAILED ...test_open_door - TypeError: elevator() missing 1 required positional argument:...
    

    because the tests call the elevator function with 2 arguments (door_is_open and start_is_pushed) and I just changed the function signature to make it take 3 required arguments (door_is_open, start_is_pushed and timer_is_set). I have to make timer_is_set a choice.

  • I add a default value to make timer_is_set a choice

    1def elevator(
    2        door_is_open, start_is_pushed,
    3        timer_is_set=False,
    4    ):
    

    the test passes because

    src.elevator.elevator(
        door_is_open=True,
        start_is_pushed=False,
    )
    

    is now the same as

    src.elevator.elevator(
        door_is_open=True,
        start_is_pushed=False,
        timer_is_set=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 timer_is_set to the next assertion for when the door is open, the timer is set and the start button is NOT pushed

    door

    timer

    start button

    output

    open

    set

    pushed

    OFF

    open

    set

    NOT pushed

    OFF

     7    def test_open_door(self):
     8        my_expectation = 'OFF'
     9
    10        reality = src.elevator.elevator(
    11            door_is_open=True,
    12            timer_is_set=True,
    13            start_is_pushed=True,
    14        )
    15        self.assertEqual(reality, my_expectation)
    16
    17        reality = src.elevator.elevator(
    18            door_is_open=True,
    19            timer_is_set=True,
    20            start_is_pushed=False,
    21        )
    22        self.assertEqual(reality, my_expectation)
    23
    24    def test_closed_door(self):
    

    the test is still green

  • I change the name of the test from test_open_door to test_open_door_timer_set

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

test_open_door_timer_not_set

The truth table for when the door is open and the timer is NOT set is

door

timer

start button

output

open

NOT set

pushed

OFF

open

NOT set

NOT pushed

OFF

  • I add a new test with an assertion for when the door is open, the timer is NOT set and the start button is pushed

    door

    timer

    start button

    output

    open

    NOT set

    pushed

    OFF

    17        reality = src.elevator.elevator(
    18            door_is_open=True,
    19            timer_is_set=True,
    20            start_is_pushed=False,
    21        )
    22        self.assertEqual(reality, my_expectation)
    23
    24    def test_open_door_timer_not_set(self):
    25        my_expectation = 'OFF'
    26
    27        reality = src.elevator.elevator(
    28            door_is_open=True,
    29            timer_is_set=False,
    30            start_is_pushed=True,
    31        )
    32        self.assertEqual(reality, my_expectation)
    33
    34    def test_closed_door(self):
    

    still green

  • I add an assertion for when the door is open, the timer is NOT set and the start button is NOT pushed

    door

    timer

    start button

    output

    open

    NOT set

    pushed

    OFF

    open

    NOT set

    NOT pushed

    OFF

    24    def test_open_door_timer_not_set(self):
    25        my_expectation = 'OFF'
    26
    27        reality = src.elevator.elevator(
    28            door_is_open=True,
    29            timer_is_set=False,
    30            start_is_pushed=True,
    31        )
    32        self.assertEqual(reality, my_expectation)
    33
    34        reality = src.elevator.elevator(
    35            door_is_open=True,
    36            timer_is_set=False,
    37            start_is_pushed=False,
    38        )
    39        self.assertEqual(reality, my_expectation)
    40
    41    def test_closed_door(self):
    

    green


test_closed_door_timer_set

The truth table for when the door is closed and is the timer is set

door

timer

start button

output

closed

set

pushed

HEATING

closed

set

NOT pushed

OFF

  • I add a value for the timer_is_set parameter to the first assertion in test_closed_door for the case where the door is closed, the timer is set and the start button is pushed

    door

    timer

    start button

    output

    closed

    set

    pushed

    HEATING

    41    def test_closed_door(self):
    42        my_expectation = 'HEATING'
    43        reality = src.elevator.elevator(
    44            door_is_open=False,
    45            timer_is_set=True,
    46            start_is_pushed=True,
    47        )
    48        self.assertEqual(reality, my_expectation)
    49
    50        my_expectation = 'OFF'
    51
    52        reality = src.elevator.elevator(
    53            door_is_open=False,
    54            start_is_pushed=False,
    55        )
    56        self.assertEqual(reality, my_expectation)
    

    the test is still green

  • I do not need to add a value for timer_is_set to the next assertion for when the door is closed, the timer is set and the start button is NOT pushed

    door

    timer

    start button

    output

    closed

    set

    pushed

    HEATING

    closed

    set

    NOT pushed

    OFF

    because

    src.elevator.elevator(
        door_is_open=False,
        start_is_pushed=False,
    )
    

    is the same as

    src.elevator.elevator(
        door_is_open=False,
        start_is_pushed=False,
        timer_is_set=False,
    )
    

    the default value for timer_is_set is False

  • I change the name of the test from test_closed_door to test_closed_door_timer_set

    34        reality = src.elevator.elevator(
    35            door_is_open=True,
    36            timer_is_set=False,
    37            start_is_pushed=False,
    38        )
    39        self.assertEqual(reality, my_expectation)
    40
    41    def test_closed_door_timer_set(self):
    42        my_expectation = 'HEATING'
    43        reality = src.elevator.elevator(
    44            door_is_open=False,
    45            timer_is_set=True,
    46            start_is_pushed=True,
    47        )
    48        self.assertEqual(reality, my_expectation)
    

test_closed_door_timer_not_set

The truth table for when the door is closed and the timer is NOT set is

door

timer

start button

output

closed

NOT set

pushed

OFF

closed

NOT set

NOT pushed

OFF


RED: make it fail


  • I add a new test with an assertion for when the door is closed, the timer is NOT set and the start button is pushed

    door

    timer

    start button

    output

    closed

    NOT set

    pushed

    OFF

    52        reality = src.elevator.elevator(
    53            door_is_open=False,
    54            start_is_pushed=False,
    55        )
    56        self.assertEqual(reality, my_expectation)
    57
    58    def test_closed_door_timer_not_set(self):
    59        my_expectation = 'OFF'
    60
    61        reality = src.elevator.elevator(
    62            door_is_open=False,
    63            timer_is_set=False,
    64            start_is_pushed=True,
    65        )
    66        self.assertEqual(reality, my_expectation)
    67
    68
    69# Exceptions seen
    

    the terminal is my friend, and shows AssertionError

    AssertionError: 'HEATING' != 'OFF'
    

    because the elevator function returns ‘HEATING’ and the test expects ‘OFF’


GREEN: make it pass


I add a if statement to the elevator function in elevator.py

1def elevator(
2        door_is_open, start_is_pushed,
3        timer_is_set=False
4    ):
5    if timer_is_set == False:
6        return 'OFF'
7    if not door_is_open and start_is_pushed:
8        return 'HEATING'
9    return 'OFF'

the test passes


REFACTOR: make it better


  • I use the bool built-in function

     1def elevator(
     2        door_is_open, start_is_pushed,
     3        timer_is_set=False
     4    ):
     5    # if timer_is_set == False:
     6    if bool(timer_is_set) == False:
     7        return 'OFF'
     8    if not door_is_open and start_is_pushed:
     9        return 'HEATING'
    10    return 'OFF'
    

    the test is still green

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

     1def elevator(
     2        door_is_open, start_is_pushed,
     3        timer_is_set=False
     4    ):
     5    # if timer_is_set == False:
     6    # if bool(timer_is_set) == False:
     7    if not bool(timer_is_set) == True:
     8        return 'OFF'
     9    if not door_is_open and start_is_pushed:
    10        return 'HEATING'
    11    return 'OFF'
    

    still green

  • I remove == True

     1def elevator(
     2        door_is_open, start_is_pushed,
     3        timer_is_set=False
     4    ):
     5    # if timer_is_set == False:
     6    # if bool(timer_is_set) == False:
     7    # if not bool(timer_is_set) == True:
     8    if not bool(timer_is_set):
     9        return 'OFF'
    10    if not door_is_open and start_is_pushed:
    11        return 'HEATING'
    12    return 'OFF'
    

    green

  • I remove bool

     1def elevator(
     2        door_is_open, start_is_pushed,
     3        timer_is_set=False
     4    ):
     5    # if timer_is_set == False:
     6    # if bool(timer_is_set) == False:
     7    # if not bool(timer_is_set) == True:
     8    # if not bool(timer_is_set):
     9    if not timer_is_set:
    10        return 'OFF'
    11    if not door_is_open and start_is_pushed:
    12        return 'HEATING'
    13    return 'OFF'
    

    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 elevator(
    2        door_is_open, start_is_pushed,
    3        timer_is_set=False,
    4    ):
    5    if not timer_is_set:
    6        return 'OFF'
    7    if not door_is_open and start_is_pushed:
    8        return 'HEATING'
    9    return 'OFF'
    

    This is what happens when the elevator function is called

    • it returns ‘OFF’ if the timer is NOT set

    • if the timer is set

      • it returns ‘HEATING’ if the door is closed AND the start button is pushed

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

  • I add an assertion for when the door is closed, the timer is NOT set and the start button is NOT pushed

    58    def test_closed_door_timer_not_set(self):
    59        my_expectation = 'OFF'
    60
    61        reality = src.elevator.elevator(
    62            door_is_open=False,
    63            timer_is_set=False,
    64            start_is_pushed=True,
    65        )
    66        self.assertEqual(reality, my_expectation)
    67
    68        reality = src.elevator.elevator(
    69            door_is_open=False,
    70            timer_is_set=False,
    71            start_is_pushed=False,
    72        )
    73        self.assertEqual(reality, my_expectation)
    74
    75
    76# Exceptions seen
    

    the test is still green

  • I add another clause to the if statement for when the timer is set, in the elevator function in elevator.py

     1def elevator(
     2        door_is_open, start_is_pushed,
     3        timer_is_set=False
     4    ):
     5    if not timer_is_set:
     6        return 'OFF'
     7    if (
     8        not door_is_open
     9        and start_is_pushed
    10        and timer_is_set
    11    ):
    12        return 'HEATING'
    13    return 'OFF'
    

    the test is still green

  • I remove the if statement for when the timer is NOT set because I do not need it anymore

     1def elevator(
     2        door_is_open, start_is_pushed,
     3        timer_is_set=False
     4    ):
     5    if (
     6        not door_is_open
     7        and start_is_pushed
     8        and timer_is_set
     9    ):
    10        return 'HEATING'
    11    return 'OFF'
    

    still green. This is what happens when the elevator function is called

    • it returns ‘HEATING’ if the door is closed AND the start button is pushed AND the timer is set

    • it returns ‘OFF’ in every other case


test_too_hot_open_door_timer_set

the truth table for the elevator is

door

timer

start button

output

open

set

pushed

OFF

open

set

NOT pushed

OFF

open

NOT set

pushed

OFF

open

NOT set

NOT pushed

OFF

door

timer

start button

output

closed

set

pushed

HEATING

closed

set

NOT pushed

OFF

closed

NOT set

pushed

OFF

closed

NOT set

NOT pushed

OFF

I want to add a failsafe to stop the elevator if it gets too hot. The inputs will then be

  • is the door open?

  • is the timer set?

  • was the start button pushed?

  • is the elevator too hot?

and the truth table for when the door is open and the timer is set will be

door

timer

start button

too hot

output

open

set

pushed

too hot

OFF

open

set

pushed

NOT too hot

OFF

open

set

NOT pushed

too hot

OFF

open

set

NOT pushed

NOT too hot

OFF


RED: make it fail


I add a value for too_hot to the assertion for the case where the door is open, the timer is set, the start button is pushed and the elevator temperature is too hot, to test_open_door_timer_set in test_elevator.py

door

timer

start button

too hot

output

open

set

pushed

too hot

OFF

 7      def test_open_door_timer_set(self):
 8          my_expectation = 'OFF'
 9
10          reality = src.elevator.elevator(
11              door_is_open=True,
12              timer_is_set=True,
13              start_is_pushed=True,
14              too_hot=True,
15          )
16          self.assertEqual(reality, my_expectation)

the terminal shows TypeError

TypeError: elevator() got an unexpected keyword argument 'too_hot'

because the test called the elevator function with 4 keyword arguments (door_is_open, timer_is_set, start_is_pushed and too_hot) and the definition only allows calls with 2 required arguments (door_is_open and start_is_pushed) and 1 optional argument (timer_is_set)


GREEN: make it pass



REFACTOR: make it better


  • I add an assertion for when the door is open, the timer is set, the start button is pushed and the elevator temperature is NOT too hot

    door

    timer

    start button

    too hot

    output

    open

    set

    pushed

    too hot

    OFF

    open

    set

    pushed

    NOT too hot

    OFF

     7    def test_open_door_timer_set(self):
     8        my_expectation = 'OFF'
     9
    10        reality = src.elevator.elevator(
    11            door_is_open=True,
    12            timer_is_set=True,
    13            start_is_pushed=True,
    14            too_hot=True,
    15        )
    16        self.assertEqual(reality, my_expectation)
    17
    18        reality = src.elevator.elevator(
    19            door_is_open=True,
    20            timer_is_set=True,
    21            start_is_pushed=True,
    22            too_hot=False,
    23        )
    24        self.assertEqual(reality, my_expectation)
    25
    26        reality = src.elevator.elevator(
    27            door_is_open=True,
    28            timer_is_set=True,
    29            start_is_pushed=False,
    30        )
    31        self.assertEqual(reality, my_expectation)
    

    the test is still green

  • I add a value for the too_hot parameter in the next assertion for when the door is open, the timer is set, the start button is NOT pushed and the elevator temperature is too hot

    door

    timer

    start button

    too hot

    output

    open

    set

    pushed

    too hot

    OFF

    open

    set

    pushed

    NOT too hot

    OFF

    open

    set

    NOT pushed

    too hot

    OFF

     7    def test_open_door_timer_set(self):
     8        my_expectation = 'OFF'
     9
    10        reality = src.elevator.elevator(
    11            door_is_open=True,
    12            timer_is_set=True,
    13            start_is_pushed=True,
    14            too_hot=True,
    15        )
    16        self.assertEqual(reality, my_expectation)
    17
    18        reality = src.elevator.elevator(
    19            door_is_open=True,
    20            timer_is_set=True,
    21            start_is_pushed=True,
    22            too_hot=False,
    23        )
    24        self.assertEqual(reality, my_expectation)
    25
    26        reality = src.elevator.elevator(
    27            door_is_open=True,
    28            timer_is_set=True,
    29            start_is_pushed=False,
    30            too_hot=True
    31        )
    32        self.assertEqual(reality, my_expectation)
    33
    34    def test_open_door_timer_not_set(self):
    

    still green

  • I add an assertion for when the door is open, the timer is set, the start button is NOT pushed and the elevator temperature is NOT too hot

    door

    timer

    start button

    too hot

    output

    open

    set

    pushed

    too hot

    OFF

    open

    set

    pushed

    NOT too hot

    OFF

    open

    set

    NOT pushed

    too hot

    OFF

    open

    set

    NOT pushed

    NOT too hot

    OFF

     7    def test_open_door_timer_set(self):
     8        my_expectation = 'OFF'
     9
    10        reality = src.elevator.elevator(
    11            door_is_open=True,
    12            timer_is_set=True,
    13            start_is_pushed=True,
    14            too_hot=True,
    15        )
    16        self.assertEqual(reality, my_expectation)
    17
    18        reality = src.elevator.elevator(
    19            door_is_open=True,
    20            timer_is_set=True,
    21            start_is_pushed=True,
    22            too_hot=False,
    23        )
    24        self.assertEqual(reality, my_expectation)
    25
    26        reality = src.elevator.elevator(
    27            door_is_open=True,
    28            timer_is_set=True,
    29            start_is_pushed=False,
    30            too_hot=True,
    31        )
    32        self.assertEqual(reality, my_expectation)
    33
    34        reality = src.elevator.elevator(
    35            door_is_open=True,
    36            timer_is_set=True,
    37            start_is_pushed=False,
    38            too_hot=False,
    39        )
    40        self.assertEqual(reality, my_expectation)
    41
    42    def test_open_door_timer_not_set(self):
    

    green

  • I change the name of the test from test_open_door_timer_set to test_too_hot_open_door_timer_set

    5class Testelevator(unittest.TestCase):
    6
    7    def test_too_hot_open_door_timer_set(self):
    8        my_expectation = 'OFF'
    
  • I add a global variable for ‘OFF’. I want to use it to remove repetition from the tests

     1import src.elevator
     2import unittest
     3
     4
     5OFF = 'OFF'
     6
     7
     8class Testelevator(unittest.TestCase):
     9
    10    def test_too_hot_open_door_timer_set(self):
    
  • I use the global variable for my_expectation in test_too_hot_open_door_timer_set

    10    def test_too_hot_open_door_timer_set(self):
    11        # my_expectation = 'OFF'
    12
    13        reality = src.elevator.elevator(
    14            door_is_open=True,
    15            timer_is_set=True,
    16            start_is_pushed=True,
    17            too_hot=True,
    18        )
    19        # self.assertEqual(reality, my_expectation)
    20        self.assertEqual(reality, OFF)
    21
    22        reality = src.elevator.elevator(
    23            door_is_open=True,
    24            timer_is_set=True,
    25            start_is_pushed=True,
    26            too_hot=False,
    27        )
    28        # self.assertEqual(reality, my_expectation)
    29        self.assertEqual(reality, OFF)
    30
    31        reality = src.elevator.elevator(
    32            door_is_open=True,
    33            timer_is_set=True,
    34            start_is_pushed=False,
    35            too_hot=True,
    36        )
    37        # self.assertEqual(reality, my_expectation)
    38        self.assertEqual(reality, OFF)
    39
    40        reality = src.elevator.elevator(
    41            door_is_open=True,
    42            timer_is_set=True,
    43            start_is_pushed=False,
    44            too_hot=False,
    45        )
    46        # self.assertEqual(reality, my_expectation)
    47        self.assertEqual(reality, OFF)
    

    still green

  • I remove the reality variables, I do not need them because they are called only once in every assertion, I can call the elevator function directly without the middle man

    10    def test_too_hot_open_door_timer_set(self):
    11        # my_expectation = 'OFF'
    12
    13        reality = src.elevator.elevator(
    14            door_is_open=True,
    15            timer_is_set=True,
    16            start_is_pushed=True,
    17            too_hot=True,
    18        )
    19        # self.assertEqual(reality, my_expectation)
    20        # self.assertEqual(reality, OFF)
    21        self.assertEqual(
    22            src.elevator.elevator(
    23                door_is_open=True,
    24                timer_is_set=True,
    25                start_is_pushed=True,
    26                too_hot=True,
    27            ),
    28            OFF
    29        )
    30
    31        reality = src.elevator.elevator(
    32            door_is_open=True,
    33            timer_is_set=True,
    34            start_is_pushed=True,
    35            too_hot=False,
    36        )
    37        # self.assertEqual(reality, my_expectation)
    38        # self.assertEqual(reality, OFF)
    39        self.assertEqual(
    40            src.elevator.elevator(
    41                door_is_open=True,
    42                timer_is_set=True,
    43                start_is_pushed=True,
    44                too_hot=False,
    45            ),
    46            OFF
    47        )
    48
    49        reality = src.elevator.elevator(
    50            door_is_open=True,
    51            timer_is_set=True,
    52            start_is_pushed=False,
    53            too_hot=True,
    54        )
    55        # self.assertEqual(reality, my_expectation)
    56        # self.assertEqual(reality, OFF)
    57        self.assertEqual(
    58            src.elevator.elevator(
    59                door_is_open=True,
    60                timer_is_set=True,
    61                start_is_pushed=False,
    62                too_hot=True,
    63            ),
    64            OFF
    65        )
    66
    67        reality = src.elevator.elevator(
    68            door_is_open=True,
    69            timer_is_set=True,
    70            start_is_pushed=False,
    71            too_hot=False,
    72        )
    73        # self.assertEqual(reality, my_expectation)
    74        # self.assertEqual(reality, OFF)
    75        self.assertEqual(
    76            src.elevator.elevator(
    77                door_is_open=True,
    78                timer_is_set=True,
    79                start_is_pushed=False,
    80                too_hot=False,
    81            ),
    82            OFF
    83        )
    
  • I remove the commented lines and reality variables

    10    def test_too_hot_open_door_timer_set(self):
    11        self.assertEqual(
    12            src.elevator.elevator(
    13                door_is_open=True,
    14                timer_is_set=True,
    15                start_is_pushed=True,
    16                too_hot=True,
    17            ),
    18            OFF
    19        )
    20
    21        self.assertEqual(
    22            src.elevator.elevator(
    23                door_is_open=True,
    24                timer_is_set=True,
    25                start_is_pushed=True,
    26                too_hot=False,
    27            ),
    28            OFF
    29        )
    30
    31        self.assertEqual(
    32            src.elevator.elevator(
    33                door_is_open=True,
    34                timer_is_set=True,
    35                start_is_pushed=False,
    36                too_hot=True,
    37            ),
    38            OFF
    39        )
    40
    41        self.assertEqual(
    42            src.elevator.elevator(
    43                door_is_open=True,
    44                timer_is_set=True,
    45                start_is_pushed=False,
    46                too_hot=False,
    47            ),
    48            OFF
    49        )
    50
    51    def test_open_door_timer_not_set(self):
    

test_too_hot_open_door_timer_not_set

The truth table for when the door is open and the timer is NOT set is

door

timer

start button

too hot

output

open

NOT set

pushed

too hot

OFF

open

NOT set

pushed

NOT too hot

OFF

open

NOT set

NOT pushed

too hot

OFF

open

NOT set

NOT pushed

NOT too hot

OFF

  • I add a value for the too_hot parameter to the first assertion in test_open_door_timer_not_set for when the door is open, the timer is NOT set, the start button is pushed and the elevator temperature is too hot

    door

    timer

    start button

    too hot

    output

    open

    NOT set

    pushed

    too hot

    OFF

    51    def test_open_door_timer_not_set(self):
    52        my_expectation = 'OFF'
    53
    54        reality = src.elevator.elevator(
    55            door_is_open=True,
    56            timer_is_set=False,
    57            start_is_pushed=True,
    58            too_hot=True,
    59        )
    60        self.assertEqual(reality, my_expectation)
    

    still green

  • I add an assertion for when the door is open, the timer is NOT set, the start button is pushed and the elevator temperature is NOT too hot

    door

    timer

    start button

    too hot

    output

    open

    NOT set

    pushed

    too hot

    OFF

    open

    NOT set

    pushed

    NOT too hot

    OFF

    51    def test_open_door_timer_not_set(self):
    52        my_expectation = 'OFF'
    53
    54        reality = src.elevator.elevator(
    55            door_is_open=True,
    56            timer_is_set=False,
    57            start_is_pushed=True,
    58            too_hot=True,
    59        )
    60        self.assertEqual(reality, my_expectation)
    61
    62        reality = src.elevator.elevator(
    63            door_is_open=True,
    64            timer_is_set=False,
    65            start_is_pushed=True,
    66            too_hot=False,
    67        )
    68        self.assertEqual(reality, my_expectation)
    69
    70        reality = src.elevator.elevator(
    71            door_is_open=True,
    72            timer_is_set=False,
    73            start_is_pushed=False,
    74        )
    75        self.assertEqual(reality, my_expectation)
    76
    77    def test_closed_door_timer_set(self):
    

    the test is still green

  • I add a value for too_hot to the next assertion, for when the door is open, the timer is NOT set, the start button is NOT pushed and the elevator temperature is too hot

    door

    timer

    start button

    too hot

    output

    open

    NOT set

    pushed

    too hot

    OFF

    open

    NOT set

    pushed

    NOT too hot

    OFF

    open

    NOT set

    NOT pushed

    too hot

    OFF

    51    def test_open_door_timer_not_set(self):
    52        my_expectation = 'OFF'
    53
    54        reality = src.elevator.elevator(
    55            door_is_open=True,
    56            timer_is_set=False,
    57            start_is_pushed=True,
    58            too_hot=True,
    59        )
    60        self.assertEqual(reality, my_expectation)
    61
    62        reality = src.elevator.elevator(
    63            door_is_open=True,
    64            timer_is_set=False,
    65            start_is_pushed=True,
    66            too_hot=False,
    67        )
    68        self.assertEqual(reality, my_expectation)
    69
    70        reality = src.elevator.elevator(
    71            door_is_open=True,
    72            timer_is_set=False,
    73            start_is_pushed=False,
    74            too_hot=True
    75        )
    76        self.assertEqual(reality, my_expectation)
    77
    78    def test_closed_door_timer_set(self):
    

    still green

  • I add an assertion for when the door is open, the timer is NOT set, the start button is NOT pushed and the elevator temperature is NOT too hot

    door

    timer

    start button

    too hot

    output

    open

    NOT set

    pushed

    too hot

    OFF

    open

    NOT set

    pushed

    NOT too hot

    OFF

    open

    NOT set

    NOT pushed

    too hot

    OFF

    open

    NOT set

    NOT pushed

    NOT too hot

    OFF

    51    def test_open_door_timer_not_set(self):
    52        my_expectation = 'OFF'
    53
    54        reality = src.elevator.elevator(
    55            door_is_open=True,
    56            timer_is_set=False,
    57            start_is_pushed=True,
    58            too_hot=True,
    59        )
    60        self.assertEqual(reality, my_expectation)
    61
    62        reality = src.elevator.elevator(
    63            door_is_open=True,
    64            timer_is_set=False,
    65            start_is_pushed=True,
    66            too_hot=False,
    67        )
    68        self.assertEqual(reality, my_expectation)
    69
    70        reality = src.elevator.elevator(
    71            door_is_open=True,
    72            timer_is_set=False,
    73            start_is_pushed=False,
    74            too_hot=True,
    75        )
    76        self.assertEqual(reality, my_expectation)
    77
    78        reality = src.elevator.elevator(
    79            door_is_open=True,
    80            timer_is_set=False,
    81            start_is_pushed=False,
    82            too_hot=False,
    83        )
    84        self.assertEqual(reality, my_expectation)
    85
    86    def test_closed_door_timer_set(self):
    

    green

  • I change the name of the test from test_open_door_timer_not_set to test_too_hot_open_door_timer_not_set

    41        self.assertEqual(
    42            src.elevator.elevator(
    43                door_is_open=True,
    44                timer_is_set=True,
    45                start_is_pushed=False,
    46                too_hot=False,
    47            ),
    48            OFF
    49        )
    50
    51    def test_too_hot_open_door_timer_not_set(self):
    52        my_expectation = 'OFF'
    
  • I use the OFF global variable to remove repetition from test_too_hot_open_door_timer_not_set

    51    def test_too_hot_open_door_timer_not_set(self):
    52        # my_expectation = 'OFF'
    53
    54        reality = src.elevator.elevator(
    55            door_is_open=True,
    56            timer_is_set=False,
    57            start_is_pushed=True,
    58            too_hot=True,
    59        )
    60        # self.assertEqual(reality, my_expectation)
    61        self.assertEqual(reality, OFF)
    62
    63        reality = src.elevator.elevator(
    64            door_is_open=True,
    65            timer_is_set=False,
    66            start_is_pushed=True,
    67            too_hot=False,
    68        )
    69        # self.assertEqual(reality, my_expectation)
    70        self.assertEqual(reality, OFF)
    71
    72        reality = src.elevator.elevator(
    73            door_is_open=True,
    74            timer_is_set=False,
    75            start_is_pushed=False,
    76            too_hot=True,
    77        )
    78        # self.assertEqual(reality, my_expectation)
    79        self.assertEqual(reality, OFF)
    80
    81        reality = src.elevator.elevator(
    82            door_is_open=True,
    83            timer_is_set=False,
    84            start_is_pushed=False,
    85            too_hot=False,
    86        )
    87        # self.assertEqual(reality, my_expectation)
    88        self.assertEqual(reality, OFF)
    

    still green

  • I call the elevator function directly in the assertion because I only use the reality variable once for each assertion

     51    def test_too_hot_open_door_timer_not_set(self):
     52        # my_expectation = 'OFF'
     53
     54        reality = src.elevator.elevator(
     55            door_is_open=True,
     56            timer_is_set=False,
     57            start_is_pushed=True,
     58            too_hot=True,
     59        )
     60        # self.assertEqual(reality, my_expectation)
     61        self.assertEqual(
     62            src.elevator.elevator(
     63                door_is_open=True,
     64                timer_is_set=False,
     65                start_is_pushed=True,
     66                too_hot=True,
     67            ),
     68            OFF
     69        )
     70
     71        reality = src.elevator.elevator(
     72            door_is_open=True,
     73            timer_is_set=False,
     74            start_is_pushed=True,
     75            too_hot=False,
     76        )
     77        # self.assertEqual(reality, my_expectation)
     78        self.assertEqual(
     79            src.elevator.elevator(
     80                door_is_open=True,
     81                timer_is_set=False,
     82                start_is_pushed=True,
     83                too_hot=False,
     84            ),
     85            OFF
     86        )
     87
     88        reality = src.elevator.elevator(
     89            door_is_open=True,
     90            timer_is_set=False,
     91            start_is_pushed=False,
     92            too_hot=True,
     93        )
     94        # self.assertEqual(reality, my_expectation)
     95        self.assertEqual(
     96            src.elevator.elevator(
     97                door_is_open=True,
     98                timer_is_set=False,
     99                start_is_pushed=False,
    100                too_hot=True,
    101            ),
    102            OFF
    103        )
    104
    105        reality = src.elevator.elevator(
    106            door_is_open=True,
    107            timer_is_set=False,
    108            start_is_pushed=False,
    109            too_hot=False,
    110        )
    111        # self.assertEqual(reality, my_expectation)
    112        self.assertEqual(
    113            src.elevator.elevator(
    114                door_is_open=True,
    115                timer_is_set=False,
    116                start_is_pushed=False,
    117                too_hot=False,
    118            ),
    119            OFF
    120        )
    
  • I remove the commented lines and reality variables

    51    def test_too_hot_open_door_timer_not_set(self):
    52        self.assertEqual(
    53            src.elevator.elevator(
    54                door_is_open=True,
    55                timer_is_set=False,
    56                start_is_pushed=True,
    57                too_hot=True,
    58            ),
    59            OFF
    60        )
    61
    62        self.assertEqual(
    63            src.elevator.elevator(
    64                door_is_open=True,
    65                timer_is_set=False,
    66                start_is_pushed=True,
    67                too_hot=False,
    68            ),
    69            OFF
    70        )
    71
    72        self.assertEqual(
    73            src.elevator.elevator(
    74                door_is_open=True,
    75                timer_is_set=False,
    76                start_is_pushed=False,
    77                too_hot=True,
    78            ),
    79            OFF
    80        )
    81
    82        self.assertEqual(
    83            src.elevator.elevator(
    84                door_is_open=True,
    85                timer_is_set=False,
    86                start_is_pushed=False,
    87                too_hot=False,
    88            ),
    89            OFF
    90        )
    91
    92    def test_closed_door_timer_set(self):
    

test_too_hot_closed_door_timer_set

The truth table for when the door is closed and the timer is set is

door

timer

start button

too hot

output

closed

set

pushed

too hot

OFF

closed

set

pushed

NOT too hot

HEATING

closed

set

NOT pushed

too hot

OFF

closed

set

NOT pushed

NOT too hot

OFF

  • I use the OFF global variable for my_expectation when the value is ‘OFF’ in test_closed_door_timer_set

     92    def test_closed_door_timer_set(self):
     93        my_expectation = 'HEATING'
     94        reality = src.elevator.elevator(
     95            door_is_open=False,
     96            timer_is_set=True,
     97            start_is_pushed=True,
     98        )
     99        self.assertEqual(reality, my_expectation)
    100
    101        # my_expectation = 'OFF'
    102
    103        reality = src.elevator.elevator(
    104            door_is_open=False,
    105            start_is_pushed=False,
    106        )
    107        # self.assertEqual(reality, my_expectation)
    108        self.assertEqual(reality, OFF)
    

    the test is still green

  • I call the elevator function directly without the reality variables

     92    def test_closed_door_timer_set(self):
     93        my_expectation = 'HEATING'
     94        reality = src.elevator.elevator(
     95            door_is_open=False,
     96            timer_is_set=True,
     97            start_is_pushed=True,
     98        )
     99        self.assertEqual(
    100            src.elevator.elevator(
    101                door_is_open=False,
    102                timer_is_set=True,
    103                start_is_pushed=True,
    104            ),
    105            'HEATING'
    106        )
    107
    108        # my_expectation = 'OFF'
    109
    110        reality = src.elevator.elevator(
    111            door_is_open=False,
    112            start_is_pushed=False,
    113        )
    114        # self.assertEqual(reality, my_expectation)
    115        self.assertEqual(
    116            src.elevator.elevator(
    117                door_is_open=False,
    118                start_is_pushed=False,
    119            ),
    120            OFF
    121        )
    

    still green

  • I remove the commented lines and variables that are not used anymore

     92    def test_closed_door_timer_set(self):
     93        self.assertEqual(
     94            src.elevator.elevator(
     95                door_is_open=False,
     96                timer_is_set=True,
     97                start_is_pushed=True,
     98            ),
     99            'HEATING'
    100        )
    101
    102        self.assertEqual(
    103            src.elevator.elevator(
    104                door_is_open=False,
    105                start_is_pushed=False,
    106            ),
    107            OFF
    108        )
    109
    110    def test_closed_door_timer_not_set(self):
    
  • I add a value for the too_hot and timer_is_set parameters in the second assertion, for when the door is closed, the timer is set, the start button is pushed, and the elevator temperature is too hot

    door

    timer

    start button

    too hot

    output

    closed

    set

    pushed

    too hot

    OFF

     92    def test_closed_door_timer_set(self):
     93        self.assertEqual(
     94            src.elevator.elevator(
     95                door_is_open=False,
     96                timer_is_set=True,
     97                start_is_pushed=True,
     98            ),
     99            'HEATING'
    100        )
    101
    102        self.assertEqual(
    103            src.elevator.elevator(
    104                door_is_open=False,
    105                timer_is_set=True,
    106                start_is_pushed=False,
    107                too_hot=True,
    108            ),
    109            OFF
    110        )
    

    green

  • I add a value for the too_hot parameter to the first assertion, for when the door is closed, the timer is set, the start button is pushed and the elevator temperature is NOT too hot

    door

    timer

    start button

    too hot

    output

    closed

    set

    pushed

    too hot

    OFF

    closed

    set

    pushed

    NOT too hot

    HEATING

     92    def test_closed_door_timer_set(self):
     93        self.assertEqual(
     94            src.elevator.elevator(
     95                door_is_open=False,
     96                timer_is_set=True,
     97                start_is_pushed=True,
     98                too_hot=False,
     99            ),
    100            'HEATING'
    101        )
    102
    103        self.assertEqual(
    104            src.elevator.elevator(
    105                door_is_open=False,
    106                timer_is_set=True,
    107                start_is_pushed=False,
    108                too_hot=True,
    109            ),
    110            OFF
    111        )
    

    still green

  • I add an assertion for when the door is closed, the timer is set, the start button is NOT pushed, and the elevator temperature is too hot

    door

    timer

    start button

    too hot

    output

    closed

    set

    pushed

    too hot

    OFF

    closed

    set

    pushed

    NOT too hot

    HEATING

    closed

    set

    NOT pushed

    too hot

    OFF

     92    def test_closed_door_timer_set(self):
     93        self.assertEqual(
     94            src.elevator.elevator(
     95                door_is_open=False,
     96                timer_is_set=True,
     97                start_is_pushed=True,
     98                too_hot=False,
     99            ),
    100            'HEATING'
    101        )
    102
    103        self.assertEqual(
    104            src.elevator.elevator(
    105                door_is_open=False,
    106                timer_is_set=True,
    107                start_is_pushed=False,
    108                too_hot=True,
    109            ),
    110            OFF
    111        )
    112
    113        self.assertEqual(
    114            src.elevator.elevator(
    115                door_is_open=False,
    116                timer_is_set=True,
    117                start_is_pushed=False,
    118                too_hot=True,
    119            ),
    120            OFF
    121        )
    

    the test is still green

  • I add an assertion for when the door is closed, the timer is set, the start button is NOT pushed, and the elevator temperature is NOT too hot

    door

    timer

    start button

    too hot

    output

    closed

    set

    pushed

    too hot

    OFF

    closed

    set

    pushed

    NOT too hot

    HEATING

    closed

    set

    NOT pushed

    too hot

    OFF

    closed

    set

    NOT pushed

    NOT too hot

    OFF

     92    def test_closed_door_timer_set(self):
     93        self.assertEqual(
     94            src.elevator.elevator(
     95                door_is_open=False,
     96                timer_is_set=True,
     97                start_is_pushed=True,
     98                too_hot=False,
     99            ),
    100            'HEATING'
    101        )
    102
    103        self.assertEqual(
    104            src.elevator.elevator(
    105                door_is_open=False,
    106                timer_is_set=True,
    107                start_is_pushed=False,
    108                too_hot=True,
    109            ),
    110            OFF
    111        )
    112
    113        self.assertEqual(
    114            src.elevator.elevator(
    115                door_is_open=False,
    116                timer_is_set=True,
    117                start_is_pushed=False,
    118                too_hot=True,
    119            ),
    120            OFF
    121        )
    122
    123        self.assertEqual(
    124            src.elevator.elevator(
    125                door_is_open=False,
    126                timer_is_set=True,
    127                start_is_pushed=False,
    128                too_hot=False,
    129            ),
    130            OFF
    131        )
    132
    133    def test_closed_door_timer_not_set(self):
    

    the test is still green

  • I change the name of the test from test_closed_door_timer_set to test_too_hot_closed_door_timer_set

     82        self.assertEqual(
     83            src.elevator.elevator(
     84                door_is_open=True,
     85                timer_is_set=False,
     86                start_is_pushed=False,
     87                too_hot=False,
     88            ),
     89            OFF
     90        )
     91
     92    def test_too_hot_closed_door_timer_set(self):
     93        self.assertEqual(
     94            src.elevator.elevator(
     95                door_is_open=False,
     96                timer_is_set=True,
     97                start_is_pushed=True,
     98                too_hot=False,
     99            ),
    100            'HEATING'
    101        )
    

test_too_hot_closed_door_timer_not_set

The truth table for when the door is closed and the timer is NOT set is

door

timer

start button

too hot

output

closed

NOT set

pushed

too hot

OFF

closed

NOT set

pushed

NOT too hot

OFF

closed

NOT set

NOT pushed

too hot

OFF

closed

NOT set

NOT pushed

NOT too hot

OFF

  • I use the OFF global variable to remove repetition from test_closed_door_timer_not_set

    133    def test_closed_door_timer_not_set(self):
    134        # my_expectation = 'OFF'
    135
    136        reality = src.elevator.elevator(
    137            door_is_open=False,
    138            timer_is_set=False,
    139            start_is_pushed=True,
    140        )
    141        # self.assertEqual(reality, my_expectation)
    142        self.assertEqual(reality, OFF)
    143
    144        reality = src.elevator.elevator(
    145            door_is_open=False,
    146            timer_is_set=False,
    147            start_is_pushed=False,
    148        )
    149        # self.assertEqual(reality, my_expectation)
    150        self.assertEqual(reality, OFF)
    

    still green

  • I call the elevator function directly in the assertion, I do not need the reality variables because they are only used once in each assertion

    133    def test_closed_door_timer_not_set(self):
    134        # my_expectation = 'OFF'
    135
    136        reality = src.elevator.elevator(
    137            door_is_open=False,
    138            timer_is_set=False,
    139            start_is_pushed=True,
    140        )
    141        # self.assertEqual(reality, my_expectation)
    142        self.assertEqual(
    143            src.elevator.elevator(
    144                door_is_open=False,
    145                timer_is_set=False,
    146                start_is_pushed=True,
    147            ),
    148            OFF
    149        )
    150
    151        reality = src.elevator.elevator(
    152            door_is_open=False,
    153            timer_is_set=False,
    154            start_is_pushed=False,
    155        )
    156        # self.assertEqual(reality, my_expectation)
    157        self.assertEqual(
    158            src.elevator.elevator(
    159                door_is_open=False,
    160                timer_is_set=False,
    161                start_is_pushed=False,
    162            ),
    163            OFF
    164        )
    
  • I remove the commented lines and variables that are not used

    133    def test_closed_door_timer_not_set(self):
    134        self.assertEqual(
    135            src.elevator.elevator(
    136                door_is_open=False,
    137                timer_is_set=False,
    138                start_is_pushed=True,
    139            ),
    140            OFF
    141        )
    142
    143        self.assertEqual(
    144            src.elevator.elevator(
    145                door_is_open=False,
    146                timer_is_set=False,
    147                start_is_pushed=False,
    148            ),
    149            OFF
    150        )
    151
    152
    153# Exceptions seen
    
  • I change the name of the test from test_closed_door_timer_not_set to test_too_hot_closed_door_timer_not_set

    123        self.assertEqual(
    124            src.elevator.elevator(
    125                door_is_open=False,
    126                timer_is_set=True,
    127                start_is_pushed=False,
    128                too_hot=False,
    129            ),
    130            OFF
    131        )
    132
    133    def test_too_hot_closed_door_timer_not_set(self):
    134        self.assertEqual(
    135            src.elevator.elevator(
    136                door_is_open=False,
    137                timer_is_set=False,
    138                start_is_pushed=True,
    139            ),
    140            OFF
    141        )
    
  • I add a value for the too_hot parameter to the first assertion in test_too_hot_closed_door_timer_not_set, for when the door is closed, the timer is NOT set, the start button is pushed, and the elevator temperature is too hot

    door

    timer

    start button

    too hot

    output

    closed

    NOT set

    pushed

    too hot

    OFF

    110    def test_too_hot_closed_door_timer_not_set(self):
    111        self.assertEqual(
    112            src.elevator.elevator(
    113                door_is_open=False,
    114                timer_is_set=False,
    115                start_is_pushed=True,
    116                too_hot=True,
    117            ),
    118            OFF
    119        )
    120
    121        self.assertEqual(
    122            src.elevator.elevator(
    123                door_is_open=False,
    124                timer_is_set=False,
    125                start_is_pushed=True,
    126            ),
    127            OFF
    128        )
    

    the test is still green

  • I add an assertion for when the door is closed, the timer is NOT set, the start button is pushed, and the elevator temperature is NOT too hot

    door

    timer

    start button

    too hot

    output

    closed

    NOT set

    pushed

    too hot

    OFF

    closed

    NOT set

    pushed

    NOT too hot

    OFF

    133    def test_too_hot_closed_door_timer_not_set(self):
    134        self.assertEqual(
    135            src.elevator.elevator(
    136                door_is_open=False,
    137                timer_is_set=False,
    138                start_is_pushed=True,
    139                too_hot=True,
    140            ),
    141            OFF
    142        )
    143
    144        self.assertEqual(
    145            src.elevator.elevator(
    146                door_is_open=False,
    147                timer_is_set=False,
    148                start_is_pushed=True,
    149                too_hot=False,
    150            ),
    151            OFF
    152        )
    153
    154        self.assertEqual(
    155            src.elevator.elevator(
    156                door_is_open=False,
    157                timer_is_set=False,
    158                start_is_pushed=False,
    159            ),
    160            OFF
    161        )
    

    still green

  • I add a value for the too_hot parameter to the next assertion, for when the door is closed, the timer is NOT set, the start button is NOT pushed, and the elevator temperature is too hot

    door

    timer

    start button

    too hot

    output

    closed

    NOT set

    pushed

    too hot

    OFF

    closed

    NOT set

    pushed

    NOT too hot

    OFF

    closed

    NOT set

    NOT pushed

    too hot

    OFF

    133    def test_too_hot_closed_door_timer_not_set(self):
    134        self.assertEqual(
    135            src.elevator.elevator(
    136                door_is_open=False,
    137                timer_is_set=False,
    138                start_is_pushed=True,
    139                too_hot=True,
    140            ),
    141            OFF
    142        )
    143
    144        self.assertEqual(
    145            src.elevator.elevator(
    146                door_is_open=False,
    147                timer_is_set=False,
    148                start_is_pushed=True,
    149                too_hot=False,
    150            ),
    151            OFF
    152        )
    153
    154        self.assertEqual(
    155            src.elevator.elevator(
    156                door_is_open=False,
    157                timer_is_set=False,
    158                start_is_pushed=False,
    159                too_hot=True,
    160            ),
    161            OFF
    162        )
    

    green

  • I add an assertion for when the door is closed, the timer is NOT set, the start button is NOT pushed, and the elevator temperature is NOT too hot

    door

    timer

    start button

    too hot

    output

    closed

    NOT set

    pushed

    too hot

    OFF

    closed

    NOT set

    pushed

    NOT too hot

    OFF

    closed

    NOT set

    NOT pushed

    too hot

    OFF

    closed

    NOT set

    NOT pushed

    NOT too hot

    OFF

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

    all the tests are still green

close the project

  • I close test_elevator.py and elevator.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 elevator

    cd ..
    

    the terminal shows

    .../pumping_python
    

    I am back in the pumping_python directory


review

I ran tests for a elevator with these inputs:

  • is the door open?

  • is the timer set?

  • was the start button pushed?

  • is the elevator too hot?

the inputs gave me this truth table

door

timer

start button

too hot

output

open

set

pushed

too hot

OFF

open

set

pushed

NOT too hot

OFF

open

set

NOT pushed

too hot

OFF

open

set

NOT pushed

NOT too hot

OFF

door

timer

start button

too hot

output

open

NOT set

pushed

too hot

OFF

open

NOT set

pushed

NOT too hot

OFF

open

NOT set

NOT pushed

too hot

OFF

open

NOT set

NOT pushed

NOT too hot

OFF

door

timer

start button

too hot

output

closed

set

pushed

too hot

OFF

closed

set

pushed

NOT too hot

HEATING

closed

set

NOT pushed

too hot

OFF

closed

set

NOT pushed

NOT too hot

OFF

door

timer

start button

too hot

output

closed

NOT set

pushed

too hot

OFF

closed

NOT set

pushed

NOT too hot

OFF

closed

NOT set

NOT pushed

too hot

OFF

closed

NOT set

NOT pushed

NOT too hot

OFF

the only time this elevator heats food is when the door is closed, the timer is set, the start button is pushed and the elevator temperature is NOT too hot.


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