Elevator

I want to make an Elevator that goes up and down when I push a button, if the inputs are

  • are the doors clear?

  • was the number for a floor pushed?

I get this truth table for the Elevator

doors

floor button

output

clear

pushed

MOVE

clear

NOT pushed

NOT MOVE

NOT clear

pushed

NOT MOVE

NOT clear

NOT pushed

NOT MOVE

preview

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

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

requirements


number the project

  • I name this project elevator

  • I open a terminal

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

    uv init elevator
    

    the terminal shows

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

    then goes back to the command line.

  • I make a directory for the source code

    mkdir src
    

    the terminal goes back to the command line.

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

    mv main.py src/elevator.py
    
    Move-Item main.py 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

  • 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 use uv to install pytest-watcher with the requirements file

    uv add --requirement requirements.txt
    

    the terminal shows that it installed pytest-watcher and its dependencies.

  • 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
    

    if you do not see uv.lock in your tree, make sure you ran uv add --requirement requirements.txt, then 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 ========================
    _________________ 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 has two underscores (__) before and after init for __init__.py not _init_.py

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

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

  • I add AssertionError to the list of Exceptions seen in test_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_doors_clear_number_pushed


RED: make it fail


I change test_failure to test_doors_clear_number_pushed, then add an assertion for when the doors are clear and the button for a floor is pushed

doors

floor button

output

clear

pushed

MOVE

 4class TestElevator(unittest.TestCase):
 5
 6    def test_doors_clear_number_pushed(self):
 7        my_expectation = 'MOVE'
 8        reality = src.elevator.elevator(
 9            doors_clear=True,
10            number_pushed=True,
11        )
12        self.assertEqual(reality, my_expectation)
13
14
15# Exceptions seen
16# AssertionError

the terminal is my friend, and shows NameError

NameError: name 'src' is not defined

because I do not have a definition for src in this file


GREEN: make it pass


  • I add NameError to the list of Exceptions seen

    15# Exceptions seen
    16# AssertionError
    17# 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, then add ModuleNotFoundError to the list of Exceptions seen

  • I add AttributeError to the list of Exceptions seen

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

  • 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 'doors_clear'
    

    because the test called the elevator function with two keyword arguments (doors_clear and number_pushed) and this definition only takes calls with 0 arguments

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

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

    1def elevator(doors_clear):
    2    return None
    

    the terminal is my friend, and shows TypeError

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

    because the test called the elevator function with two keyword arguments (doors_clear and number_pushed) and this definition only takes calls with 1 input

  • I add number_pushed to the function signature

    1def elevator(doors_clear, number_pushed):
    2    return None
    

    the terminal is my friend, and shows AssertionError

    AssertionError: None != 'MOVE'
    

    the elevator function returned None and the assertion expects ‘MOVE’

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

    1def elevator(doors_clear, number_pushed):
    2    return 'MOVE'
    

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


test_doors_clear_number_not_pushed


RED: make it fail


I add a test named test_doors_clear_number_not_pushed with an assertion for when the doors are clear and the button for a floor is NOT pushed, in test_elevator.py

doors

floor button

output

clear

NOT pushed

NOT MOVE

 7    def test_doors_clear_number_pushed(self):
 8        my_expectation = 'MOVE'
 9        reality = src.elevator.elevator(
10            doors_clear=True,
11            number_pushed=True,
12        )
13        self.assertEqual(reality, my_expectation)
14
15    def test_doors_clear_number_not_pushed(self):
16        my_expectation = 'NOT MOVE'
17        reality = src.elevator.elevator(
18            doors_clear=True,
19            number_pushed=False,
20        )
21        self.assertEqual(reality, my_expectation)
22
23
24# Exceptions seen

the terminal is my friend, and shows AssertionError

AssertionError: 'MOVE' != 'NOT MOVE'

because the elevator function returns ‘MOVE’ and the assertion expects ‘NOT MOVE’


GREEN: make it pass


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

1def elevator(doors_clear, number_pushed):
2    if number_pushed == False:
3        return 'NOT MOVE'
4
5    return 'MOVE'

the test passes.


REFACTOR: make it better


  • I use the bool built-in function

    1def elevator(doors_clear, number_pushed):
    2    # if number_pushed == False:
    3    if bool(number_pushed) == False:
    4        return 'NOT MOVE'
    5
    6    return 'MOVE'
    

    the test is still green.

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

    1def elevator(doors_clear, number_pushed):
    2    # if number_pushed == False:
    3    # if bool(number_pushed) == False:
    4    if bool(not number_pushed) == True:
    5        return 'NOT MOVE'
    6
    7    return 'MOVE'
    

    still green.

  • I remove == True

    1def elevator(doors_clear, number_pushed):
    2    # if number_pushed == False:
    3    # if bool(number_pushed) == False:
    4    # if bool(not number_pushed) == True:
    5    if bool(not number_pushed):
    6        return 'NOT MOVE'
    7
    8    return 'MOVE'
    

    green.

  • I remove bool

    1def elevator(doors_clear, number_pushed):
    2    # if number_pushed == False:
    3    # if bool(number_pushed) == False:
    4    # if bool(not number_pushed) == True:
    5    # if bool(not number_pushed):
    6    if not number_pushed:
    7        return 'NOT MOVE'
    8
    9    return 'MOVE'
    

    still green, because if bool(something) == False is the same as if bool(not something) == True is the same as if bool(not something) is the same as if not something.

  • I remove the commented lines

    1def elevator(doors_clear, number_pushed):
    2    if not number_pushed:
    3        return 'NOT MOVE'
    4
    5    return 'MOVE'
    

    this is what happens when the elevator function is called

    • it returns ‘NOT MOVE’ if the button for the floor is NOT pushed

    • it returns ‘MOVE’ if the above condition is NOT met


test_doors_not_clear_number_pushed


RED: make it fail


I add a test with an assertion for when the doors are NOT clear and the button for a floor is pushed, in test_elevator.py

doors

floor button

output

NOT clear

pushed

NOT MOVE

15    def test_doors_clear_number_not_pushed(self):
16        my_expectation = 'NOT MOVE'
17        reality = src.elevator.elevator(
18            doors_clear=True,
19            number_pushed=False,
20        )
21        self.assertEqual(reality, my_expectation)
22
23    def test_doors_not_clear_number_pushed(self):
24        my_expectation = 'NOT MOVE'
25        reality = src.elevator.elevator(
26            doors_clear=False,
27            number_pushed=True,
28        )
29        self.assertEqual(reality, my_expectation)
30
31
32# Exceptions seen

the terminal is my friend, and shows AssertionError

AssertionError: 'MOVE' != 'NOT MOVE'

because the elevator function returns ‘MOVE’ and the assertion expects ‘NOT MOVE’


GREEN: make it pass


I add an if statement to elevator.py

1def elevator(doors_clear, number_pushed):
2    if doors_clear == False:
3        return 'NOT MOVE'
4
5    if not number_pushed:
6        return 'NOT MOVE'
7
8    return 'MOVE'

the test passes.


REFACTOR: make it better


  • I use the bool built-in function

    1def elevator(doors_clear, number_pushed):
    2    # if doors_clear == False:
    3    if bool(doors_clear) == False:
    4        return 'NOT MOVE'
    5
    6    if not number_pushed:
    7        return 'NOT MOVE'
    8
    9    return 'MOVE'
    

    the test is still green.

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

     1def elevator(doors_clear, number_pushed):
     2# if doors_clear == False:
     3# if bool(doors_clear) == False:
     4if bool(not doors_clear) == True:
     5    return 'NOT MOVE'
     6
     7if not number_pushed:
     8    return 'NOT MOVE'
     9
    10return 'MOVE'
    

    still green.

  • I remove == True

     1def elevator(doors_clear, number_pushed):
     2    # if doors_clear == False:
     3    # if bool(doors_clear) == False:
     4    # if bool(not doors_clear) == True:
     5    if bool(not doors_clear):
     6        return 'NOT MOVE'
     7
     8    if not number_pushed:
     9        return 'NOT MOVE'
    10
    11    return 'MOVE'
    

    green.

  • I remove bool

     1def elevator(doors_clear, number_pushed):
     2    # if doors_clear == False:
     3    # if bool(doors_clear) == False:
     4    # if bool(not doors_clear) == True:
     5    # if bool(not doors_clear):
     6    if not doors_clear:
     7        return 'NOT MOVE'
     8
     9    if not number_pushed:
    10        return 'NOT MOVE'
    11
    12    return 'MOVE'
    

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

  • I add a variable

    1def elevator(doors_clear, number_pushed):
    2    not_move = 'NOT MOVE'
    3    # if doors_clear == False:
    4    # if bool(doors_clear) == False:
    5    # if bool(not doors_clear) == True:
    
  • I use the variable to remove repetition of ‘NOT MOVE’ from the function

     1def elevator(doors_clear, number_pushed):
     2    not_move = 'NOT MOVE'
     3    # if doors_clear == False:
     4    # if bool(doors_clear) == False:
     5    # if bool(not doors_clear) == True:
     6    # if bool(not doors_clear):
     7    if not doors_clear:
     8        # return 'NOT MOVE'
     9        return not_move
    10
    11    if not number_pushed:
    12        # return 'NOT MOVE'
    13        return not_move
    14
    15    return 'MOVE'
    

    still green.

  • I remove the commented lines

     1def elevator(doors_clear, number_pushed):
     2    not_move = 'NOT MOVE'
     3
     4    if not doors_clear:
     5        return not_move
     6
     7    if not number_pushed:
     8        return not_move
     9
    10    return 'MOVE'
    

    this is what happens when the elevator function is called

    • it returns ‘NOT MOVE’ if the button for the floor is NOT pushed

    • it returns ‘NOT MOVE’ if the doors are NOT clear

    • it returns ‘MOVE’ if the above conditions are NOT met


test_doors_not_clear_number_not_pushed


I add a test with an assertion for when the doors are NOT clear and the button for the floor is NOT pushed to test_elevator.py

doors

floor button

output

NOT clear

NOT pushed

NOT MOVE

23    def test_doors_not_clear_number_pushed(self):
24        my_expectation = 'NOT MOVE'
25        reality = src.elevator.elevator(
26            doors_clear=False,
27            number_pushed=True,
28        )
29        self.assertEqual(reality, my_expectation)
30
31    def test_doors_not_clear_number_not_pushed(self):
32        my_expectation = 'NOT MOVE'
33        reality = src.elevator.elevator(
34            doors_clear=False,
35            number_pushed=False,
36        )
37        self.assertEqual(reality, my_expectation)
38
39
40# Exceptions seen

the test is still green.


REFACTOR: make it better


  • ‘NOT MOVE’ happens in 3 of the 4 tests, I make a global variable to remove repetition of the variables from the tests

    1import src.elevator
    2import unittest
    3
    4
    5NOT_MOVE = 'NOT MOVE'
    6
    7
    8class TestElevator(unittest.TestCase):
    

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

  • I use the new global variable to remove ‘NOT_MOVE’ from test_doors_clear_number_not_pushed

    18    def test_doors_clear_number_not_pushed(self):
    19        # my_expectation = 'NOT MOVE'
    20        reality = src.elevator.elevator(
    21            doors_clear=True,
    22            number_pushed=False,
    23        )
    24        # self.assertEqual(reality, my_expectation)
    25        self.assertEqual(reality, NOT_MOVE)
    26
    27    def test_doors_not_clear_number_pushed(self):
    

    still green.

  • I remove the commented lines

    18    def test_doors_clear_number_not_pushed(self):
    19        reality = src.elevator.elevator(
    20            doors_clear=True,
    21            number_pushed=False,
    22        )
    23        self.assertEqual(reality, NOT_MOVE)
    24
    25    def test_doors_not_clear_number_pushed(self):
    
  • I use the new global variable to remove ‘NOT_MOVE’ from test_doors_not_clear_number_pushed

    25    def test_doors_not_clear_number_pushed(self):
    26        # my_expectation = 'NOT MOVE'
    27        reality = src.elevator.elevator(
    28            doors_clear=False,
    29            number_pushed=True,
    30        )
    31        # self.assertEqual(reality, my_expectation)
    32        self.assertEqual(reality, NOT_MOVE)
    33
    34    def test_doors_not_clear_number_not_pushed(self):
    

    green.

  • I remove the commented lines

    25    def test_doors_not_clear_number_pushed(self):
    26        reality = src.elevator.elevator(
    27            doors_clear=False,
    28            number_pushed=True,
    29        )
    30        self.assertEqual(reality, NOT_MOVE)
    31
    32    def test_doors_not_clear_number_not_pushed(self):
    
  • I use the new global variable to remove ‘NOT_MOVE’ from test_doors_not_clear_number_not_pushed

    32    def test_doors_not_clear_number_not_pushed(self):
    33        # my_expectation = 'NOT MOVE'
    34        reality = src.elevator.elevator(
    35            doors_clear=False,
    36            number_pushed=False,
    37        )
    38        # self.assertEqual(reality, my_expectation)
    39        self.assertEqual(reality, NOT_MOVE)
    40
    41
    42# Exceptions seen
    

    still green.

  • I remove the commented lines

    32    def test_doors_not_clear_number_not_pushed(self):
    33        reality = src.elevator.elevator(
    34            doors_clear=False,
    35            number_pushed=False,
    36        )
    37        self.assertEqual(reality, NOT_MOVE)
    38
    39
    40# Exceptions seen
    

test_weight_w_doors_clear_number_pushed

So far, the truth table for the elevator is

doors

floor button

output

clear

pushed

MOVE

clear

NOT pushed

NOT MOVE

NOT clear

pushed

NOT MOVE

NOT clear

NOT pushed

NOT MOVE

I want the elevator to move only when it is NOT above a weight limit, the inputs for the elevator will then be

  • are the doors clear?

  • was the number for a floor pushed?

  • is the elevator above the weight limit?

The truth table for when the doors are clear and the button for a floor is pushed, is:

doors

floor number

weight limit

output

clear

pushed

above

NOT MOVE

clear

pushed

NOT above

MOVE


RED: make it fail


I add an assertion with a value for above_weight_limit to test_doors_clear_number_pushed, for when the doors are clear, the button for a floor is pushed and the elevator is above the weight limit

doors

floor number

weight limit

output

clear

pushed

above

NOT MOVE

10    def test_doors_clear_number_pushed(self):
11        reality = src.elevator.elevator(
12            doors_clear=True,
13            number_pushed=True,
14            above_weight_limit=True,
15        )
16        self.assertEqual(reality, NOT_MOVE)
17
18        my_expectation = 'MOVE'
19        reality = src.elevator.elevator(
20            doors_clear=True,
21            number_pushed=True,
22        )
23        self.assertEqual(reality, my_expectation)
24
25    def test_doors_clear_number_not_pushed(self):

the terminal is my friend, and shows TypeError

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

because the test called the elevator function with 3 keyword arguments (doors_clear, number_pushed and above_weight_limit) and the function only takes calls with 2 arguments (doors_clear and number_pushed)


GREEN: make it pass


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

     1def elevator(
     2        doors_clear, number_pushed,
     3        above_weight_limit,
     4    ):
     5    not_move = 'NOT MOVE'
     6
     7    if not doors_clear:
     8        return not_move
     9
    10    if not number_pushed:
    11        return not_move
    12
    13    return 'MOVE'
    
    • the terminal is my friend, and shows TypeError

      FAILED ...test_doors_clear_number_not_pushed - TypeError: elevator() missing 1 required positional argument: 'above_weight_limit'
      FAILED t...test_doors_not_clear_number_not_pushed - TypeError: elevator() missing 1 required positional argument: 'above_weight_limit'
      FAILED ...test_doors_not_clear_number_pushed - TypeError: elevator() missing 1 required positional argument: 'above_weight_limit'
      

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

    • the terminal also shows AssertionError

      AssertionError: 'MOVE' != 'NOT MOVE'
      

      because the elevator function returned ‘MOVE’ when it was called with the above_weight_limit parameter and the assertion expects ‘NOT MOVE’

  • I add a default value to make above_weight_limit a choice

    1def elevator(
    2        doors_clear, number_pushed,
    3        above_weight_limit=False,
    4    ):
    
    AssertionError: 'MOVE' != 'NOT MOVE'
    

    because the elevator function returned ‘MOVE’ and the assertion expects ‘NOT MOVE’

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

     1def elevator(
     2        doors_clear, number_pushed,
     3        above_weight_limit=False,
     4    ):
     5    not_move = 'NOT MOVE'
     6
     7    if above_weight_limit == True:
     8        return not_move
     9
    10    if not doors_clear:
    11        return not_move
    12
    13    if not number_pushed:
    14        return not_move
    15
    16    return 'MOVE'
    

    the test passes.


REFACTOR: make it better


  • I use the bool built-in function

    7    # if above_weight_limit == True:
    8    if bool(above_weight_limit) == True:
    9        return not_move
    

    the test is still green.

  • I remove == True

     7    # if above_weight_limit == True:
     8    # if bool(above_weight_limit) == True:
     9    if bool(above_weight_limit):
    10        return not_move
    

    still green.

  • I remove bool

     7    # if above_weight_limit == True:
     8    # if bool(above_weight_limit) == True:
     9    # if bool(above_weight_limit):
    10    if above_weight_limit:
    11        return not_move
    

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

  • I remove the commented lines

     1def elevator(
     2        doors_clear, number_pushed,
     3        above_weight_limit=False,
     4    ):
     5    not_move = 'NOT MOVE'
     6
     7    if above_weight_limit:
     8        return not_move
     9
    10    if not doors_clear:
    11        return not_move
    12
    13    if not number_pushed:
    14        return not_move
    15
    16    return 'MOVE'
    

    this is what happens when the elevator function is called

    • it returns ‘NOT MOVE’ if the elevator is above the weight limit

    • it returns ‘NOT MOVE’ if the button for the floor is NOT pushed

    • it returns ‘NOT MOVE’ if the doors are NOT clear

    • it returns ‘MOVE’ if the above conditions are NOT met

  • I do not need to add a value for the above_weight_limit parameter to the next assertion for when the doors are clear, the button for the floor is pushed and the elevator is NOT above the weight limit

    doors

    floor number

    weight limit

    output

    clear

    pushed

    NOT above

    MOVE

    because

    src.elevator.elevator(
        doors_clear=True,
        number_pushed=True,
    )
    

    is the same as

    src.elevator.elevator(
        doors_clear=True,
        number_pushed=True,
        above_weight_limit=False,
    )
    

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

  • I change the name of the test from test_doors_clear_number_pushed to test_weight_w_doors_clear_number_pushed

     5class TestElevator(unittest.TestCase):
     6
     7    def test_weight_w_doors_clear_number_pushed(self):
     8        reality = src.elevator.elevator(
     9            doors_clear=True,
    10            number_pushed=True,
    11            above_weight_limit=True,
    12        )
    13        self.assertEqual(reality, NOT_MOVE)
    

test_weight_w_doors_clear_number_not_pushed

The truth table for when the doors are clear and the button for a floor is NOT pushed, is:

doors

floor number

weight limit

output

clear

NOT pushed

above

NOT MOVE

clear

NOT pushed

NOT above

NOT MOVE

  • I add a value for the above_weight_limit parameter to the assertion for when the doors are clear, the button for a floor is NOT pushed and the elevator is above the weight limit, in test_doors_clear_number_not_pushed

    doors

    floor number

    weight limit

    output

    clear

    NOT pushed

    above

    NOT MOVE

    25    def test_doors_clear_number_not_pushed(self):
    26        reality = src.elevator.elevator(
    27            doors_clear=True,
    28            number_pushed=False,
    29            above_weight_limit=True,
    30        )
    31        self.assertEqual(reality, NOT_MOVE)
    32
    33    def test_doors_not_clear_number_pushed(self):
    

    the test is still green.

  • I add an assertion for when the doors are clear, the button for the floor is NOT pushed and the elevator is NOT above the weight limit

    doors

    floor number

    weight limit

    output

    clear

    NOT pushed

    NOT above

    NOT MOVE

    25    def test_doors_clear_number_not_pushed(self):
    26        reality = src.elevator.elevator(
    27            doors_clear=True,
    28            number_pushed=False,
    29            above_weight_limit=True,
    30        )
    31        self.assertEqual(reality, NOT_MOVE)
    32
    33        reality = src.elevator.elevator(
    34            doors_clear=True,
    35            number_pushed=False,
    36        )
    37        self.assertEqual(reality, NOT_MOVE)
    38
    39    def test_doors_not_clear_number_pushed(self):
    

    still green. I do not need to add a value for the above_weight_limit parameter because

    src.elevator.elevator(
        doors_clear=True,
        number_pushed=False,
    )
    

    is the same as

    src.elevator.elevator(
        doors_clear=True,
        number_pushed=False,
        above_weight_limit=False,
    )
    

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

  • I change the name of the test from test_doors_clear_number_not_pushed to test_weight_w_doors_clear_number_not_pushed

    18        my_expectation = 'MOVE'
    19        reality = src.elevator.elevator(
    20            doors_clear=True,
    21            number_pushed=True,
    22        )
    23        self.assertEqual(reality, my_expectation)
    24
    25    def test_weight_w_doors_clear_number_not_pushed(self):
    26        reality = src.elevator.elevator(
    27            doors_clear=True,
    28            number_pushed=False,
    29            above_weight_limit=True,
    30        )
    31        self.assertEqual(reality, NOT_MOVE)
    

test_weight_w_doors_not_clear_number_pushed

The truth table for when the doors are NOT clear and the button for a floor is pushed, is:

doors

floor number

weight limit

output

NOT clear

pushed

above

NOT MOVE

NOT clear

pushed

NOT above

NOT MOVE

  • I add a value for the above_weight_limit parameter to the assertion in test_doors_not_clear_number_pushed for the case where the doors are NOT clear, the button for a floor is pushed and the elevator is above the weight limit

    doors

    floor number

    weight limit

    output

    NOT clear

    pushed

    above

    NOT MOVE

    39    def test_doors_not_clear_number_pushed(self):
    40        reality = src.elevator.elevator(
    41            doors_clear=False,
    42            number_pushed=True,
    43            above_weight_limit=True,
    44        )
    45        self.assertEqual(reality, NOT_MOVE)
    46
    47    def test_doors_not_clear_number_not_pushed(self):
    

    the test is still green.

  • I add an assertion to test_doors_not_clear_number_pushed, for when the doors are NOT clear, the button for the floor is pushed and the elevator is NOT above the weight limit

    doors

    floor number

    weight limit

    output

    NOT clear

    pushed

    NOT above

    NOT MOVE

    39    def test_doors_not_clear_number_pushed(self):
    40        reality = src.elevator.elevator(
    41            doors_clear=False,
    42            number_pushed=True,
    43            above_weight_limit=True,
    44        )
    45        self.assertEqual(reality, NOT_MOVE)
    46
    47        reality = src.elevator.elevator(
    48            doors_clear=False,
    49            number_pushed=True,
    50        )
    51        self.assertEqual(reality, NOT_MOVE)
    52
    53    def test_doors_not_clear_number_not_pushed(self):
    

    still green. I do not need to add a value for the above_weight_limit parameter because

    src.elevator.elevator(
        doors_clear=False,
        number_pushed=True,
    )
    

    is the same as

    src.elevator.elevator(
        doors_clear=False,
        number_pushed=True,
        above_weight_limit=False,
    )
    

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

  • I change the name of the test from test_doors_not_clear_number_pushed to test_weight_w_doors_not_clear_number_pushed

    33        reality = src.elevator.elevator(
    34            doors_clear=True,
    35            number_pushed=False,
    36        )
    37        self.assertEqual(reality, NOT_MOVE)
    38
    39    def test_weight_w_doors_not_clear_number_pushed(self):
    40        reality = src.elevator.elevator(
    41            doors_clear=False,
    42            number_pushed=True,
    43            above_weight_limit=True,
    44        )
    45        self.assertEqual(reality, NOT_MOVE)
    

test_weight_w_doors_not_clear_number_not_pushed

The truth table for when the doors are NOT clear and the button for a floor is NOT pushed, is:

doors

floor number

weight limit

output

NOT clear

NOT pushed

above

NOT MOVE

NOT clear

NOT pushed

NOT above

NOT MOVE

  • I add a value for the above_weight_limit parameter to the assertion for when the doors are NOT clear, the button for a floor is NOT pushed and the elevator is above the weight , in test_doors_not_clear_number_not_pushed

    doors

    floor number

    weight limit

    output

    NOT clear

    NOT pushed

    above

    NOT MOVE

    53    def test_doors_not_clear_number_not_pushed(self):
    54        reality = src.elevator.elevator(
    55            doors_clear=False,
    56            number_pushed=False,
    57            above_weight_limit=True,
    58        )
    59        self.assertEqual(reality, NOT_MOVE)
    60
    61
    62# Exceptions seen
    

    green.

  • I add an assertion for when the doors are NOT clear, the button for the floor is NOT pushed and the elevator is NOT above the weight limit

    doors

    floor number

    weight limit

    output

    NOT clear

    NOT pushed

    NOT above

    NOT MOVE

    53    def test_doors_not_clear_number_not_pushed(self):
    54        reality = src.elevator.elevator(
    55            doors_clear=False,
    56            number_pushed=False,
    57            above_weight_limit=True,
    58        )
    59        self.assertEqual(reality, NOT_MOVE)
    60
    61        reality = src.elevator.elevator(
    62            doors_clear=False,
    63            number_pushed=False,
    64        )
    65        self.assertEqual(reality, NOT_MOVE)
    66
    67
    68# Exceptions seen
    

    still green. I do not need to add a value for the above_weight_limit parameter because

    src.elevator.elevator(
        doors_clear=False,
        number_pushed=False,
    )
    

    is the same as

    src.elevator.elevator(
        doors_clear=False,
        number_pushed=False,
        above_weight_limit=False,
    )
    

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

  • I change the name of the test from test_doors_not_clear_number_pushed to test_weight_w_doors_not_clear_number_pushed

    47        reality = src.elevator.elevator(
    48            doors_clear=False,
    49            number_pushed=True,
    50        )
    51        self.assertEqual(reality, NOT_MOVE)
    52
    53    def test_weight_w_doors_not_clear_number_not_pushed(self):
    54        reality = src.elevator.elevator(
    55            doors_clear=False,
    56            number_pushed=False,
    57            above_weight_limit=True,
    58        )
    59        self.assertEqual(reality, NOT_MOVE)
    
  • I call the elevator function directly in test_weight_w_doors_not_clear_number_not_pushed, I do not need the reality variable because it is only used once in each assertion

    56    def test_weight_w_doors_not_clear_number_not_pushed(self):
    57        reality = src.elevator.elevator(
    58            doors_clear=False,
    59            number_pushed=False,
    60            above_weight_limit=True,
    61        )
    62        # self.assertEqual(reality, NOT_MOVE)
    63        self.assertEqual(
    64            src.elevator.elevator(
    65                doors_clear=False,
    66                number_pushed=False,
    67                above_weight_limit=True,
    68            ),
    69            NOT_MOVE
    70        )
    71
    72        reality = src.elevator.elevator(
    73            doors_clear=False,
    74            number_pushed=False,
    75        )
    76        # self.assertEqual(reality, NOT_MOVE)
    77        self.assertEqual(
    78            src.elevator.elevator(
    79                doors_clear=False,
    80                number_pushed=False,
    81            ),
    82            NOT_MOVE
    83        )
    84
    85
    86# Exceptions seen
    

    the test is still green.

  • I remove the commented lines and reality variables

    56    def test_weight_w_doors_not_clear_number_not_pushed(self):
    57        self.assertEqual(
    58            src.elevator.elevator(
    59                doors_clear=False,
    60                above_weight_limit=False,
    61                number_pushed=True,
    62            ),
    63            NOT_MOVE
    64        )
    65
    66        self.assertEqual(
    67            src.elevator.elevator(
    68                doors_clear=False,
    69                above_weight_limit=False,
    70                number_pushed=False,
    71            ),
    72            NOT_MOVE
    73        )
    74
    75
    76# Exceptions seen
    
  • I do the same thing in test_weight_w_doors_not_clear_number_pushed

    39    def test_weight_w_doors_not_clear_number_pushed(self):
    40        reality = src.elevator.elevator(
    41            doors_clear=False,
    42            number_pushed=True,
    43            above_weight_limit=True,
    44        )
    45        # self.assertEqual(reality, NOT_MOVE)
    46        self.assertEqual(
    47            src.elevator.elevator(
    48                doors_clear=False,
    49                number_pushed=True,
    50                above_weight_limit=True,
    51            ),
    52            NOT_MOVE
    53        )
    54
    55        reality = src.elevator.elevator(
    56            doors_clear=False,
    57            number_pushed=True,
    58        )
    59        # self.assertEqual(reality, NOT_MOVE)
    60        self.assertEqual(
    61            src.elevator.elevator(
    62                doors_clear=False,
    63                number_pushed=True,
    64            ),
    65            NOT_MOVE
    66        )
    67
    68    def test_weight_w_doors_not_clear_number_not_pushed(self):
    

    still green.

  • I remove the commented lines and reality variables from test_weight_w_doors_not_clear_number_pushed

    39    def test_weight_w_doors_not_clear_number_pushed(self):
    40        self.assertEqual(
    41            src.elevator.elevator(
    42                doors_clear=False,
    43                number_pushed=True,
    44                above_weight_limit=True,
    45            ),
    46            NOT_MOVE
    47        )
    48
    49        self.assertEqual(
    50            src.elevator.elevator(
    51                doors_clear=False,
    52                number_pushed=True,
    53            ),
    54            NOT_MOVE
    55        )
    56
    57    def test_weight_w_doors_not_clear_number_not_pushed(self):
    
  • on to test_weight_w_doors_clear_number_not_pushed

    25    def test_weight_w_doors_clear_number_not_pushed(self):
    26        reality = src.elevator.elevator(
    27            doors_clear=True,
    28            number_pushed=False,
    29            above_weight_limit=True,
    30        )
    31        # self.assertEqual(reality, NOT_MOVE)
    32        self.assertEqual(
    33            src.elevator.elevator(
    34                doors_clear=True,
    35                number_pushed=False,
    36                above_weight_limit=True,
    37            ),
    38            NOT_MOVE
    39        )
    40
    41        reality = src.elevator.elevator(
    42            doors_clear=True,
    43            number_pushed=False,
    44        )
    45        # self.assertEqual(reality, NOT_MOVE)
    46        self.assertEqual(
    47            src.elevator.elevator(
    48                doors_clear=True,
    49                number_pushed=False,
    50            ),
    51            NOT_MOVE
    52        )
    53
    54    def test_weight_w_doors_not_clear_number_pushed(self):
    

    green.

  • I remove the commented lines and reality variables from test_weight_w_doors_clear_number_not_pushed

    25    def test_weight_w_doors_clear_number_not_pushed(self):
    26        self.assertEqual(
    27            src.elevator.elevator(
    28                doors_clear=True,
    29                number_pushed=False,
    30                above_weight_limit=True,
    31            ),
    32            NOT_MOVE
    33        )
    34
    35        self.assertEqual(
    36            src.elevator.elevator(
    37                doors_clear=True,
    38                number_pushed=False,
    39            ),
    40            NOT_MOVE
    41        )
    42
    43    def test_weight_w_doors_not_clear_number_pushed(self):
    
  • I call the elevator function directly then remove the commented lines and unused variables in test_weight_w_doors_clear_number_pushed

    10    def test_weight_w_doors_clear_number_pushed(self):
    11        self.assertEqual(
    12            src.elevator.elevator(
    13                doors_clear=True,
    14                number_pushed=True,
    15                above_weight_limit=True,
    16            ),
    17            NOT_MOVE
    18        )
    19
    20        self.assertEqual(
    21            src.elevator.elevator(
    22                doors_clear=True,
    23                number_pushed=True,
    24            ),
    25            'MOVE'
    26        )
    27
    28    def test_weight_w_doors_clear_number_not_pushed(self):
    

    still green.


test_doors_clear_number_pushed_w_emergency

The truth table for the elevator is

doors

floor number

weight limit

output

clear

pushed

above

NOT MOVE

clear

pushed

NOT above

MOVE

clear

NOT pushed

above

NOT MOVE

clear

NOT pushed

NOT above

NOT MOVE

doors

floor number

weight limit

output

NOT clear

pushed

above

NOT MOVE

NOT clear

pushed

NOT above

NOT MOVE

NOT clear

NOT pushed

above

NOT MOVE

NOT clear

NOT pushed

NOT above

NOT MOVE

I want to make sure the elevator can be stopped with a button in an emergency. The inputs will then be

  • are the doors clear?

  • was the number for a floor pushed?

  • is the elevator above the weight limit?

  • was the emergency button pushed?

and the truth table for when the doors are clear and the number for a floor is pushed, is

doors

floor number

weight limit

emergency button

output

clear

pushed

above

pushed

NOT MOVE

clear

pushed

above

NOT pushed

NOT MOVE

clear

pushed

NOT above

pushed

NOT MOVE

clear

pushed

NOT above

NOT pushed

MOVE


RED: make it fail


I add a value for emergency to the first assertion in test_weight_w_doors_clear_number_pushed for the case where the doors are clear, the button for a floor is pushed, the elevator is above the weight limit, and the emergency button is pushed

doors

floor number

weight limit

emergency button

output

clear

pushed

above

pushed

NOT MOVE

10    def test_weight_w_doors_clear_number_pushed(self):
11        self.assertEqual(
12            src.elevator.elevator(
13                doors_clear=True,
14                number_pushed=True,
15                above_weight_limit=True,
16                emergency=True,
17            ),
18            NOT_MOVE
19        )
20
21        self.assertEqual(
22            src.elevator.elevator(
23                doors_clear=True,
24                number_pushed=True,
25            ),
26            'MOVE'
27        )
28
29    def test_weight_w_doors_clear_number_not_pushed(self):

the terminal shows TypeError

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

because the test called the elevator function with 4 keyword arguments (doors_clear, number_pushed, above_weight_limit and emergency) and the definition only takes calls with 2 required arguments (doors_clear and number_pushed) and 1 optional argument (above_weight_limit)


GREEN: make it pass


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

     1def elevator(
     2        doors_clear, number_pushed,
     3        above_weight_limit=False, emergency,
     4    ):
     5    not_move = 'NOT MOVE'
     6
     7    if above_weight_limit:
     8        return not_move
     9
    10    if not doors_clear:
    11        return not_move
    12
    13    if not number_pushed:
    14        return not_move
    15
    16    return 'MOVE'
    

    the terminal is my friend, and shows SyntaxError

    SyntaxError: parameter without a default follows parameter with a default
    

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

  • I add a default value for the emergency parameter in the function signature to make it a choice

    1def elevator(
    2        doors_clear, number_pushed,
    3        above_weight_limit=False, emergency=False,
    4    ):
    

    the test passes.


REFACTOR: make it better


  • I add an assertion to test_weight_w_doors_clear_number_pushed for when the doors are clear, the button for a floor is pushed, the elevator is above the weight limit, and the emergency button is NOT pushed

    doors

    floor number

    weight limit

    emergency button

    output

    clear

    pushed

    above

    NOT pushed

    NOT MOVE

    10    def test_weight_w_doors_clear_number_pushed(self):
    11        self.assertEqual(
    12            src.elevator.elevator(
    13                doors_clear=True,
    14                number_pushed=True,
    15                above_weight_limit=True,
    16                emergency=True,
    17            ),
    18            NOT_MOVE
    19        )
    20
    21        self.assertEqual(
    22            src.elevator.elevator(
    23                doors_clear=True,
    24                number_pushed=True,
    25                above_weight_limit=True,
    26                emergency=False,
    27            ),
    28            NOT_MOVE
    29        )
    30
    31        self.assertEqual(
    32            src.elevator.elevator(
    33                doors_clear=True,
    34                number_pushed=True,
    35            ),
    36            'MOVE'
    37        )
    38
    39    def test_weight_w_doors_clear_number_not_pushed(self):
    

    the test is still green.

  • I add an assertion to test_weight_w_doors_clear_number_pushed for when the doors are clear, the button for the floor is pushed, the elevator is NOT above the weight limit and the emergency button is pushed, in test_weight_w_doors_clear_number_pushed in test_elevator.py

    doors

    floor number

    weight limit

    emergency button

    output

    clear

    pushed

    NOT above

    pushed

    NOT MOVE

    10    def test_weight_w_doors_clear_number_pushed(self):
    11        self.assertEqual(
    12            src.elevator.elevator(
    13                doors_clear=True,
    14                number_pushed=True,
    15                above_weight_limit=True,
    16                emergency=True,
    17            ),
    18            NOT_MOVE
    19        )
    20
    21        self.assertEqual(
    22            src.elevator.elevator(
    23                doors_clear=True,
    24                number_pushed=True,
    25                above_weight_limit=True,
    26                emergency=False,
    27            ),
    28            NOT_MOVE
    29        )
    30
    31        self.assertEqual(
    32            src.elevator.elevator(
    33                doors_clear=True,
    34                number_pushed=True,
    35                above_weight_limit=False,
    36                emergency=True,
    37            ),
    38            NOT_MOVE
    39        )
    40
    41        self.assertEqual(
    42            src.elevator.elevator(
    43                doors_clear=True,
    44                number_pushed=True,
    45            ),
    46            'MOVE'
    47        )
    48
    49    def test_weight_w_doors_clear_number_not_pushed(self):
    

    the terminal is my friend, and shows AssertionError

    AssertionError: 'MOVE' != 'NOT MOVE'
    

    because the elevator function returns ‘MOVE’ and the assertion expects ‘NOT MOVE’

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

     1def elevator(
     2        doors_clear, number_pushed,
     3        above_weight_limit=False, emergency=False,
     4    ):
     5    not_move = 'NOT MOVE'
     6
     7    if emergency == True:
     8        return not_move
     9
    10    if above_weight_limit:
    11        return not_move
    12
    13    if not doors_clear:
    14        return not_move
    15
    16    if not number_pushed:
    17        return not_move
    18
    19    return 'MOVE'
    

    the test passes.

  • I use the bool built-in function

    7    # if emergency == True:
    8    if bool(emergency) == True:
    9        return not_move
    

    the test is still green.

  • I remove == True

     7    # if emergency == True:
     8    # if bool(emergency) == True:
     9    if bool(emergency):
    10        return not_move
    

    still green.

  • I remove bool

     7    # if emergency == True:
     8    # if bool(emergency) == True:
     9    # if bool(emergency):
    10    if emergency:
    11        return not_move
    

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

  • I remove the commented lines

     1def elevator(
     2        doors_clear, number_pushed,
     3        above_weight_limit=False, emergency=False,
     4    ):
     5    not_move = 'NOT MOVE'
     6
     7    if emergency:
     8        return not_move
     9
    10    if above_weight_limit:
    11        return not_move
    12
    13    if not doors_clear:
    14        return not_move
    15
    16    if not number_pushed:
    17        return not_move
    18
    19    return 'MOVE'
    

    this is what happens when the elevator function is called

    • it returns ‘NOT MOVE’ if the emergency button is pushed

    • it returns ‘NOT MOVE’ if the elevator is above the weight limit

    • it returns ‘NOT MOVE’ if the button for the floor is NOT pushed

    • it returns ‘NOT MOVE’ if the doors are NOT clear

    • it returns ‘MOVE’ if the above conditions are NOT met

  • I add values for the above_weight_limit and emergency parameters to test_weight_w_doors_clear_number_pushed, even though I do not need to because they have default values. This will make things clearer in the last assertion which is for when the doors are clear, the button for the floor is pushed, the elevator is NOT above the weight limit, and the emergency button is NOT pushed, in test_elevator.py

    doors

    floor number

    weight limit

    emergency button

    output

    clear

    pushed

    NOT above

    NOT pushed

    MOVE

    10    def test_weight_w_doors_clear_number_pushed(self):
    11        self.assertEqual(
    12            src.elevator.elevator(
    13                doors_clear=True,
    14                number_pushed=True,
    15                above_weight_limit=True,
    16                emergency=True,
    17            ),
    18            NOT_MOVE
    19        )
    20
    21        self.assertEqual(
    22            src.elevator.elevator(
    23                doors_clear=True,
    24                number_pushed=True,
    25                above_weight_limit=True,
    26                emergency=False,
    27            ),
    28            NOT_MOVE
    29        )
    30
    31        self.assertEqual(
    32            src.elevator.elevator(
    33                doors_clear=True,
    34                number_pushed=True,
    35                above_weight_limit=False,
    36                emergency=True,
    37            ),
    38            NOT_MOVE
    39        )
    40
    41        self.assertEqual(
    42            src.elevator.elevator(
    43                doors_clear=True,
    44                number_pushed=True,
    45                above_weight_limit=False,
    46                emergency=False,
    47            ),
    48            'MOVE'
    49        )
    50
    51    def test_weight_w_doors_clear_number_not_pushed(self):
    

    green.

  • I change the name of the test from test_weight_w_doors_clear_number_pushed to test_doors_clear_number_pushed_w_emergency

     8class TestElevator(unittest.TestCase):
     9
    10    def test_doors_clear_number_pushed_w_emergency(self):
    11        self.assertEqual(
    12            src.elevator.elevator(
    13                doors_clear=True,
    14                number_pushed=True,
    15                above_weight_limit=True,
    16                emergency=True,
    17            ),
    18            NOT_MOVE
    19        )
    

test_doors_clear_number_not_pushed_w_emergency

The truth table for when the doors are clear and the button for a floor is NOT pushed, is

doors

floor number

weight limit

emergency button

output

clear

NOT pushed

above

pushed

NOT MOVE

clear

NOT pushed

above

NOT pushed

NOT MOVE

clear

NOT pushed

NOT above

pushed

NOT MOVE

clear

NOT pushed

NOT above

NOT pushed

NOT MOVE

  • I add a value for the emergency parameter to the first assertion in test_weight_w_doors_clear_number_not_pushed for when the doors are clear, button for a floor is NOT pushed, the elevator is above the weight limit, and the emergency button is pushed

    doors

    floor number

    weight limit

    emergency button

    output

    clear

    NOT pushed

    above

    pushed

    NOT MOVE

    51    def test_weight_w_doors_clear_number_not_pushed(self):
    52        self.assertEqual(
    53            src.elevator.elevator(
    54                doors_clear=True,
    55                number_pushed=False,
    56                above_weight_limit=True,
    57                emergency=True,
    58            ),
    59            NOT_MOVE
    60        )
    

    still green.

  • I add an assertion for when the doors are clear, the button for a floor is NOT pushed, the elevator is above the weight limit, and the emergency button is NOT pushed

    doors

    floor number

    weight limit

    emergency button

    output

    clear

    NOT pushed

    above

    NOT pushed

    NOT MOVE

    51    def test_weight_w_doors_clear_number_not_pushed(self):
    52        self.assertEqual(
    53            src.elevator.elevator(
    54                doors_clear=True,
    55                number_pushed=False,
    56                above_weight_limit=True,
    57                emergency=True,
    58            ),
    59            NOT_MOVE
    60        )
    61
    62        self.assertEqual(
    63            src.elevator.elevator(
    64                doors_clear=True,
    65                number_pushed=False,
    66                above_weight_limit=True,
    67                emergency=False,
    68            ),
    69            NOT_MOVE
    70        )
    71
    72        self.assertEqual(
    73            src.elevator.elevator(
    74                doors_clear=True,
    75                number_pushed=False,
    76            ),
    77            NOT_MOVE
    78        )
    79
    80    def test_weight_w_doors_not_clear_number_pushed(self):
    

    the test is still green.

  • I add values for the above_weight_limit and emergency parameters, even though I do not need to because they have default values. This will make things clearer in the last assertion, for when the doors are clear, the button for the floor is NOT pushed, the elevator is NOT above the weight limit, and the emergency button is pushed

    doors

    floor number

    weight limit

    emergency button

    output

    clear

    NOT pushed

    NOT above

    pushed

    NOT MOVE

    51    def test_weight_w_doors_clear_number_not_pushed(self):
    52        self.assertEqual(
    53            src.elevator.elevator(
    54                doors_clear=True,
    55                above_weight_limit=False,
    56                number_pushed=True,
    57                emergency=True,
    58            ),
    59            NOT_MOVE
    60        )
    61
    62        self.assertEqual(
    63            src.elevator.elevator(
    64                doors_clear=True,
    65                above_weight_limit=False,
    66                number_pushed=True,
    67                emergency=False,
    68            ),
    69            NOT_MOVE
    70        )
    71
    72        self.assertEqual(
    73            src.elevator.elevator(
    74                doors_clear=True,
    75                above_weight_limit=False,
    76                number_pushed=False,
    77                emergency=True,
    78            ),
    79            NOT_MOVE
    80        )
    81
    82    def test_weight_w_doors_not_clear_number_pushed(self):
    

    still green.

  • I add an assertion for when the doors are clear, the button for the floor is NOT pushed, the elevator is NOT above the weight limit, and the emergency button is NOT pushed

    doors

    floor number

    weight limit

    emergency button

    output

    clear

    NOT pushed

    NOT above

    NOT pushed

    NOT MOVE

    51    def test_weight_w_doors_clear_number_not_pushed(self):
    52        self.assertEqual(
    53            src.elevator.elevator(
    54                doors_clear=True,
    55                number_pushed=False,
    56                above_weight_limit=True,
    57                emergency=True,
    58            ),
    59            NOT_MOVE
    60        )
    61
    62        self.assertEqual(
    63            src.elevator.elevator(
    64                doors_clear=True,
    65                number_pushed=False,
    66                above_weight_limit=True,
    67                emergency=False,
    68            ),
    69            NOT_MOVE
    70        )
    71
    72        self.assertEqual(
    73            src.elevator.elevator(
    74                doors_clear=True,
    75                number_pushed=False,
    76                above_weight_limit=False,
    77                emergency=True,
    78            ),
    79            NOT_MOVE
    80        )
    81
    82        self.assertEqual(
    83            src.elevator.elevator(
    84                doors_clear=True,
    85                number_pushed=False,
    86                above_weight_limit=False,
    87                emergency=False,
    88            ),
    89            NOT_MOVE
    90        )
    91
    92    def test_weight_w_doors_not_clear_number_pushed(self):
    

    green.

  • I change the name of the test from test_weight_w_doors_clear_number_not_pushed to test_doors_clear_number_not_pushed_w_emergency

    41        self.assertEqual(
    42            src.elevator.elevator(
    43                doors_clear=True,
    44                number_pushed=True,
    45                above_weight_limit=False,
    46                emergency=False,
    47            ),
    48            'MOVE'
    49        )
    50
    51    def test_doors_clear_number_not_pushed_w_emergency(self):
    52        self.assertEqual(
    53            src.elevator.elevator(
    54                doors_clear=True,
    55                number_pushed=False,
    56                above_weight_limit=True,
    57                emergency=True,
    58            ),
    59            NOT_MOVE
    60        )
    

test_doors_not_clear_number_pushed_w_emergency

The truth table for when the doors are NOT clear and the button for a floor is pushed, is

doors

floor number

weight limit

emergency button

output

NOT clear

pushed

above

pushed

NOT MOVE

NOT clear

pushed

above

NOT pushed

NOT MOVE

NOT clear

pushed

NOT above

pushed

NOT MOVE

NOT clear

pushed

NOT above

NOT pushed

NOT MOVE

  • I add a value for the emergency parameter to the first assertion of test_weight_w_doors_not_clear_number_pushed, for when the doors are NOT clear, the button for a floor is pushed, the elevator is above the weight limit, and the emergency button is pushed

    doors

    floor number

    weight limit

    emergency button

    output

    NOT clear

    pushed

    above

    pushed

    NOT MOVE

     92    def test_weight_w_doors_not_clear_number_pushed(self):
     93        self.assertEqual(
     94            src.elevator.elevator(
     95                doors_clear=False,
     96                number_pushed=True,
     97                above_weight_limit=True,
     98                emergency=True,
     99            ),
    100            NOT_MOVE
    101        )
    

    still green.

  • I add an assertion for when the doors are NOT clear, the button for a floor is pushed, the elevator is above the weight limit, and the emergency button is NOT pushed

    doors

    floor number

    weight limit

    emergency button

    output

    NOT clear

    pushed

    above

    NOT pushed

    NOT MOVE

     92    def test_weight_w_doors_not_clear_number_pushed(self):
     93        self.assertEqual(
     94            src.elevator.elevator(
     95                doors_clear=False,
     96                number_pushed=True,
     97                above_weight_limit=True,
     98                emergency=True,
     99            ),
    100            NOT_MOVE
    101        )
    102
    103        self.assertEqual(
    104            src.elevator.elevator(
    105                doors_clear=False,
    106                number_pushed=True,
    107                above_weight_limit=True,
    108                emergency=False,
    109            ),
    110            NOT_MOVE
    111        )
    112
    113        self.assertEqual(
    114            src.elevator.elevator(
    115                doors_clear=False,
    116                number_pushed=True,
    117            ),
    118            NOT_MOVE
    119        )
    120
    121    def test_weight_w_doors_not_clear_number_not_pushed(self):
    

    still green.

  • I add a value for the above_weight_limit, even though I do not need to because it has a default value. I also add a value for the emergency parameter. This will make things clearer in the third assertion which is for when the doors are NOT clear, the button for the floor is pushed, the elevator is NOT above the weight limit, and the emergency button is pushed

    doors

    floor number

    weight limit

    emergency button

    output

    NOT clear

    pushed

    NOT above

    pushed

    NOT MOVE

     92    def test_weight_w_doors_not_clear_number_pushed(self):
     93        self.assertEqual(
     94            src.elevator.elevator(
     95                doors_clear=False,
     96                number_pushed=True,
     97                above_weight_limit=True,
     98                emergency=True,
     99            ),
    100            NOT_MOVE
    101        )
    102
    103        self.assertEqual(
    104            src.elevator.elevator(
    105                doors_clear=False,
    106                number_pushed=True,
    107                above_weight_limit=True,
    108                emergency=False,
    109            ),
    110            NOT_MOVE
    111        )
    112
    113        self.assertEqual(
    114            src.elevator.elevator(
    115                doors_clear=False,
    116                number_pushed=True,
    117                above_weight_limit=False,
    118                emergency=True,
    119            ),
    120            NOT_MOVE
    121        )
    122
    123    def test_weight_w_doors_not_clear_number_not_pushed(self):
    

    the test is still green.

  • I add an assertion for when the doors are NOT clear, the button for the floor is pushed, the elevator is NOT above the weight limit, and the emergency button is NOT pushed

    doors

    floor number

    weight limit

    emergency button

    output

    NOT clear

    pushed

    NOT above

    NOT pushed

    NOT MOVE

     92    def test_weight_w_doors_not_clear_number_pushed(self):
     93        self.assertEqual(
     94            src.elevator.elevator(
     95                doors_clear=False,
     96                number_pushed=True,
     97                above_weight_limit=True,
     98                emergency=True,
     99            ),
    100            NOT_MOVE
    101        )
    102
    103        self.assertEqual(
    104            src.elevator.elevator(
    105                doors_clear=False,
    106                number_pushed=True,
    107                above_weight_limit=True,
    108                emergency=False,
    109            ),
    110            NOT_MOVE
    111        )
    112
    113        self.assertEqual(
    114            src.elevator.elevator(
    115                doors_clear=False,
    116                number_pushed=True,
    117                above_weight_limit=False,
    118                emergency=True,
    119            ),
    120            NOT_MOVE
    121        )
    122
    123        self.assertEqual(
    124            src.elevator.elevator(
    125                doors_clear=False,
    126                number_pushed=True,
    127                above_weight_limit=False,
    128                emergency=False,
    129            ),
    130            NOT_MOVE
    131        )
    132
    133    def test_weight_w_doors_not_clear_number_not_pushed(self):
    

    still green.

  • I change the name of the test from test_weight_w_doors_not_clear_number_pushed to test_doors_not_clear_number_pushed_w_emergency

     82        self.assertEqual(
     83            src.elevator.elevator(
     84                doors_clear=True,
     85                number_pushed=False,
     86                above_weight_limit=False,
     87                emergency=False,
     88            ),
     89            NOT_MOVE
     90        )
     91
     92    def test_doors_not_clear_number_pushed_w_emergency(self):
     93        self.assertEqual(
     94            src.elevator.elevator(
     95                doors_clear=False,
     96                number_pushed=True,
     97                above_weight_limit=True,
     98                emergency=True,
     99            ),
    100            NOT_MOVE
    101        )
    

test_doors_not_clear_number_not_pushed_w_emergency

The truth table for when the doors are NOT clear and the button for a floor is NOT pushed, is

doors

floor number

weight limit

emergency button

output

NOT clear

NOT pushed

above

pushed

NOT MOVE

NOT clear

NOT pushed

above

NOT pushed

NOT MOVE

NOT clear

NOT pushed

NOT above

pushed

NOT MOVE

NOT clear

NOT pushed

NOT above

NOT pushed

NOT MOVE

  • I add a value for the emergency parameter to the first assertion in test_weight_w_doors_not_clear_number_not_pushed, for when the doors are NOT clear, the button for a floor is NOT pushed, the elevator is above the weight limit, and the emergency button is pushed

    doors

    floor number

    weight limit

    emergency button

    output

    NOT clear

    NOT pushed

    above

    pushed

    NOT MOVE

    133    def test_weight_w_doors_not_clear_number_not_pushed(self):
    134        self.assertEqual(
    135            src.elevator.elevator(
    136                doors_clear=False,
    137                number_pushed=False,
    138                above_weight_limit=True,
    139                emergency=True,
    140            ),
    141            NOT_MOVE
    142        )
    

    the test is still green.

  • I add an assertion for when the doors are NOT clear, the button for a floor is NOT pushed, the elevator is above the weight limit, and the emergency button is NOT pushed

    doors

    floor number

    weight limit

    emergency button

    output

    NOT clear

    NOT pushed

    above

    NOT pushed

    NOT MOVE

    133    def test_weight_w_doors_not_clear_number_not_pushed(self):
    134        self.assertEqual(
    135            src.elevator.elevator(
    136                doors_clear=False,
    137                number_pushed=False,
    138                above_weight_limit=True,
    139                emergency=True,
    140            ),
    141            NOT_MOVE
    142        )
    143
    144        self.assertEqual(
    145            src.elevator.elevator(
    146                doors_clear=False,
    147                number_pushed=False,
    148                above_weight_limit=True,
    149                emergency=False,
    150            ),
    151            NOT_MOVE
    152        )
    153
    154        self.assertEqual(
    155            src.elevator.elevator(
    156                doors_clear=False,
    157                number_pushed=False,
    158            ),
    159            NOT_MOVE
    160        )
    161
    162
    163# Exceptions seen
    

    still green.

  • I add values for the above_weight_limit parameter, even though I do not need to because it has a default value. I also add a value for the emergency parameter. This will make things clearer in the third assertion, which is for when the doors are NOT clear, the button for the floor is NOT pushed, the elevator is NOT above the weight limit, and the emergency button is pushed

    doors

    floor number

    weight limit

    emergency button

    output

    NOT clear

    NOT pushed

    NOT above

    pushed

    NOT MOVE

    133    def test_weight_w_doors_not_clear_number_not_pushed(self):
    134        self.assertEqual(
    135            src.elevator.elevator(
    136                doors_clear=False,
    137                number_pushed=False,
    138                above_weight_limit=True,
    139                emergency=True,
    140            ),
    141            NOT_MOVE
    142        )
    143
    144        self.assertEqual(
    145            src.elevator.elevator(
    146                doors_clear=False,
    147                number_pushed=False,
    148                above_weight_limit=True,
    149                emergency=False,
    150            ),
    151            NOT_MOVE
    152        )
    153
    154        self.assertEqual(
    155            src.elevator.elevator(
    156                doors_clear=False,
    157                number_pushed=False,
    158                above_weight_limit=False,
    159                emergency=True,
    160            ),
    161            NOT_MOVE
    162        )
    163
    164
    165# Exceptions seen
    

    green.

  • I add an assertion for when the doors are NOT clear, the button for the floor is NOT pushed, the elevator is NOT above the weight limit, and the emergency button is NOT pushed

    doors

    floor number

    weight limit

    emergency button

    output

    NOT clear

    NOT pushed

    NOT above

    NOT pushed

    NOT MOVE

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

    all the tests are still green.

  • I change the name of the test from test_weight_w_doors_not_clear_number_not_pushed to test_doors_not_clear_number_not_pushed_w_emergency

    123        self.assertEqual(
    124            src.elevator.elevator(
    125                doors_clear=False,
    126                above_weight_limit=True,
    127                number_pushed=False,
    128                emergency=False,
    129            ),
    130            NOT_MOVE
    131        )
    132
    133    def test_doors_not_clear_number_not_pushed_w_emergency(self):
    134        self.assertEqual(
    135            src.elevator.elevator(
    136                doors_clear=False,
    137                above_weight_limit=False,
    138                number_pushed=True,
    139                emergency=True,
    140            ),
    141            NOT_MOVE
    142        )
    
  • To review, the elevator function

     1def elevator(
     2        doors_clear, number_pushed,
     3        above_weight_limit=False, emergency=False,
     4    ):
     5    not_move = 'NOT MOVE'
     6
     7    if emergency:
     8        return not_move
     9
    10    if above_weight_limit:
    11        return not_move
    12
    13    if not doors_clear:
    14        return not_move
    15
    16    if not number_pushed:
    17        return not_move
    18
    19    return 'MOVE'
    
    • returns ‘NOT MOVE’ if the emergency button is pushed

    • returns ‘NOT MOVE’ if the elevator is above the weight limit

    • returns ‘NOT MOVE’ if the button for the floor is NOT pushed

    • returns ‘NOT MOVE’ if the doors are NOT clear

    • returns ‘MOVE’ if the above conditions are NOT met

  • All the if statements return ‘NOT MOVE’ which means I could use Logical Disjunction (OR) to put them together though it will be a long statement

     1def elevator(
     2        doors_clear, number_pushed,
     3        above_weight_limit=False, emergency=False,
     4    ):
     5    if (
     6        emergency
     7        or above_weight_limit
     8        or not doors_clear
     9        or not number_pushed
    10    ):
    11        return 'NOT MOVE'
    12
    13    return 'MOVE'
    

    the tests are still green.

  • I rewrite the statement in terms of NOT because it happens two times

     1def elevator(
     2        doors_clear, number_pushed,
     3        above_weight_limit=False, emergency=False,
     4    ):
     5    # if (
     6    #     emergency
     7    #     or above_weight_limit
     8    #     or not doors_clear
     9    #     or not number_pushed
    10    # ):
    11    if (
    12        emergency
    13        or above_weight_limit
    14        or (
    15            (not doors_clear)
    16            (not and)
    17            (not number_pushed)
    18        )
    19    ):
    20        return 'NOT MOVE'
    21
    22    return 'MOVE'
    

    the terminal is my friend, and shows SyntaxError

    SyntaxError: invalid syntax
    

    because I cannot negate and, this way

  • I “factor” out the nots

     1def elevator(
     2        doors_clear, number_pushed,
     3        above_weight_limit=False, emergency=False,
     4    ):
     5    # if (
     6    #     emergency
     7    #     or above_weight_limit
     8    #     or not doors_clear
     9    #     or not number_pushed
    10    # ):
    11    # if (
    12    #     emergency
    13    #     or above_weight_limit
    14    #     or (
    15    #         (not doors_clear)
    16    #         (not and)
    17    #         (not number_pushed)
    18    #     )
    19    # ):
    20    if (
    21        emergency
    22        or above_weight_limit
    23        or not (
    24            doors_clear
    25            and
    26            number_pushed
    27        )
    28    ):
    29        return 'NOT MOVE'
    30
    31    return 'MOVE'
    

    the tests are green again

  • I remove the commented lines

     1def elevator(
     2        doors_clear, number_pushed,
     3        above_weight_limit=False, emergency=False,
     4    ):
     5    if (
     6        emergency
     7        or above_weight_limit
     8        or not (
     9            doors_clear
    10            and
    11            number_pushed
    12        )
    13    ):
    14        return 'NOT MOVE'
    15
    16    return 'MOVE'
    

    Which do you like better? One if statement to bind them all or many simple statements?

close the project

  • I close test_elevator.py and elevator.py

  • I click in the terminal, then use q on the doorsboard to leave the tests. The terminal goes back to the command line.

  • I change directory to the parent of 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:

  • are the doors clear?

  • is it above the weight limit?

  • was the number for a floor pushed?

  • was the emergency button pushed?

the inputs gave me this truth table

doors

floor number

weight limit

emergency button

output

clear

pushed

above

pushed

NOT MOVE

clear

pushed

above

NOT pushed

NOT MOVE

clear

pushed

NOT above

pushed

NOT MOVE

clear

pushed

NOT above

NOT pushed

MOVE

doors

floor number

weight limit

emergency button

output

clear

NOT pushed

above

pushed

NOT MOVE

clear

NOT pushed

above

NOT pushed

NOT MOVE

clear

NOT pushed

NOT above

pushed

NOT MOVE

clear

NOT pushed

NOT above

NOT pushed

NOT MOVE

doors

floor number

weight limit

emergency button

output

NOT clear

pushed

above

pushed

NOT MOVE

NOT clear

pushed

above

NOT pushed

NOT MOVE

NOT clear

pushed

NOT above

pushed

NOT MOVE

NOT clear

pushed

NOT above

NOT pushed

NOT MOVE

doors

floor number

weight limit

emergency button

output

NOT clear

NOT pushed

above

pushed

NOT MOVE

NOT clear

NOT pushed

above

NOT pushed

NOT MOVE

NOT clear

NOT pushed

NOT above

pushed

NOT MOVE

NOT clear

NOT pushed

NOT above

NOT pushed

NOT MOVE

the only time this elevator goes up or down is when the doors are clear, the button for a floor is pushed, the elevator is NOT above the weight limit, and the emergency button is NOT pushed.


code from the chapter

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.