test elevator with list comprehensions

I want to use for loops in the Elevator project. It has tests for an Elevator Controller that will MOVE the Elevator Car to a floor when I push a button for the floor based on these inputs:

  • was the number for a floor pushed?

  • are the doors closed?

  • is it above the weight limit?

  • was the emergency button pushed?

the inputs gave me this truth table

floor button

doors

weight limit

emergency button

output

pushed

closed

above

pushed

False

pushed

closed

above

NOT pushed

False

pushed

closed

below

pushed

False

pushed

closed

below

NOT pushed

True

floor button

doors

weight limit

emergency button

output

pushed

open

above

pushed

False

pushed

open

above

NOT pushed

False

pushed

open

below

pushed

False

pushed

open

below

NOT pushed

False

floor button

doors

weight limit

emergency button

output

NOT pushed

closed

above

pushed

False

NOT pushed

closed

above

NOT pushed

False

NOT pushed

closed

below

pushed

False

NOT pushed

closed

below

NOT pushed

False

floor button

doors

weight limit

emergency button

output

NOT pushed

open

above

pushed

False

NOT pushed

open

above

NOT pushed

False

NOT pushed

open

below

pushed

False

NOT pushed

open

below

NOT pushed

False

The only time this elevator moves up or down is when the button for a floor is pushed AND the doors are closed AND the Elevator is NOT above the weight limit, and the emergency button is NOT pushed.

preview

These is the test I have at the end of the chapter

elevator/tests/test_elevator.py
 1import src.elevator
 2import unittest
 3
 4
 5class TestElevator(unittest.TestCase):
 6
 7    def test_elevator_controller(self):
 8        booleans = (False, True)
 9        for number_pushed in booleans:
10            for doors_closed in booleans:
11                for above_weight in booleans:
12                    for emergency in booleans:
13                        with self.subTest(
14                            number_pushed=number_pushed,
15                            doors_closed=doors_closed,
16                            above_weight=above_weight,
17                            emergency=emergency,
18                        ):
19                            result = src.elevator.controller(
20                                number_pushed=number_pushed,
21                                doors_closed=doors_closed,
22                                above_weight=above_weight,
23                                emergency=emergency,
24                            )
25                            try:
26                                self.assertFalse(result)
27                            except AssertionError:
28                                self.assertTrue(result)
29
30
31# Exceptions seen
32# AssertionError
33# NameError
34# AttributeError
35# TypeError
36# SyntaxError

open the project


extract test_elevator_controller

RED: make it fail


I add a test with a for loop for all the cases

elevator/tests/test_elevator.py
 5class TestElevator(unittest.TestCase):
 6
 7    def test_elevator_controller(self):
 8        booleans = (False, True)
 9        for number_pushed in booleans:
10            for doors_closed in booleans:
11                for above_weight in booleans:
12                    for emergency in booleans:
13                        with self.subTest(
14                            number_pushed=number_pushed,
15                            doors_closed=doors_closed,
16                            above_weight=above_weight,
17                            emergency=emergency,
18                        ):
elevator/tests/test_elevator.py
 5                            result = src.elevator.controller(
 6                                number_pushed=number_pushed,
 7                                doors_closed=doors_closed,
 8                                above_weight=above_weight,
 9                                emergency=emergency,
10                            )
11                            self.assertEqual(result, 'BOOM!!!')
12
13    def test_above_weight_doors_closed_number_pushed(self):

the terminal is my friend, and shows AssertionError

terminal
SUBFAILED(
    number_pushed=False, doors_closed=False,
    above_weight=False, emergency=False
) ... AssertionError: False != 'BOOM!!!'
SUBFAILED(
    number_pushed=False, doors_closed=False,
    above_weight=False, emergency=True
) ... AssertionError: False != 'BOOM!!!'
SUBFAILED(
    number_pushed=False, doors_closed=False,
    above_weight=True, emergency=False
) ... AssertionError: False != 'BOOM!!!'
SUBFAILED(
    number_pushed=False, doors_closed=False,
    above_weight=True, emergency=True
) ... AssertionError: False != 'BOOM!!!'
terminal
SUBFAILED(
    number_pushed=False, doors_closed=True,
    above_weight=False, emergency=False
) ... AssertionError: False != 'BOOM!!!'
SUBFAILED(
    number_pushed=False, doors_closed=True,
    above_weight=False, emergency=True
) ... AssertionError: False != 'BOOM!!!'
SUBFAILED(
    number_pushed=False, doors_closed=True,
    above_weight=True, emergency=False
) ... AssertionError: False != 'BOOM!!!'
SUBFAILED(
    number_pushed=False, doors_closed=True,
    above_weight=True, emergency=True
) ... AssertionError: False != 'BOOM!!!'
terminal
SUBFAILED(
    number_pushed=True, doors_closed=False,
    above_weight=False, emergency=False
) ... AssertionError: False != 'BOOM!!!'
SUBFAILED(
    number_pushed=True, doors_closed=False,
    above_weight=False, emergency=True
) ... AssertionError: False != 'BOOM!!!'
SUBFAILED(
    number_pushed=True, doors_closed=False,
    above_weight=True, emergency=False
) ... AssertionError: False != 'BOOM!!!'
SUBFAILED(
    number_pushed=True, doors_closed=False,
    above_weight=True, emergency=True
) ... AssertionError: False != 'BOOM!!!'
terminal
SUBFAILED(
    number_pushed=True, doors_closed=True,
    above_weight=False, emergency=False
) ... AssertionError: True != 'BOOM!!!'
SUBFAILED(
    number_pushed=True, doors_closed=True,
    above_weight=False, emergency=True
) ... AssertionError: False != 'BOOM!!!'
SUBFAILED(
    number_pushed=True, doors_closed=True,
    above_weight=True, emergency=False
) ... AssertionError: False != 'BOOM!!!'
SUBFAILED(
    number_pushed=True, doors_closed=True,
    above_weight=True, emergency=True
) ... AssertionError: False != 'BOOM!!!'

GREEN: make it pass


  • I change self.assertEqual(result, 'BOOM!!!') to handle the fifteen cases where the controller functions returns False

    elevator/tests/test_elevator.py
    19                            result = src.elevator.controller(
    20                                number_pushed=number_pushed,
    21                                doors_closed=doors_closed,
    22                                above_weight=above_weight,
    23                                emergency=emergency,
    24                            )
    25                            self.assertFalse(result)
    26
    27    def test_above_weight_doors_closed_number_pushed(self):
    

    the terminal is my friend, and shows AssertionError

    terminal
    SUBFAILED(
        number_pushed=True, doors_closed=True,
        above_weight=False, emergency=False
    ) ... AssertionError: True is not false
    
  • I move the assertion into a try statement for it

    elevator/tests/test_elevator.py
    19                          result = src.elevator.controller(
    20                              number_pushed=number_pushed,
    21                              doors_closed=doors_closed,
    22                              above_weight=above_weight,
    23                              emergency=emergency,
    24                          )
    25                          try:
    26                              self.assertFalse(result)
    27                          except AssertionError:
    28                              self.assertTrue(result)
    29
    30  def test_above_weight_doors_closed_number_pushed(self):
    

    the test passes.


REFACTOR: make it better


  • I remove all the other tests because they are now covered by test_elevator_controller

    elevator/tests/test_elevator.py
    25                            try:
    26                                self.assertFalse(result)
    27                            except AssertionError:
    28                                self.assertTrue(result)
    29
    30
    31# Exceptions seen
    
  • I add a git commit message

    terminal
    git commit -am \
    'extract test_elevator_controller'
    

close the project

  • I close tests/test_elevator.py

  • I click in the terminal where the tests are running

  • I use q on the keyboard to leave the tests

  • I change directory to the parent of Elevator

    terminal
    cd ..
    

review

I also used four nested for loops to make one test for all sixteen cases. There has to be a better way that looks better.


code from the chapter

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


what is next?

Would you like to test the functions project with loops?


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.