test car with list comprehensions
I want to use for loops in the Car project. It has tests for a Car ignition with these inputs:
was the start button pressed?
is the key close to the ignition?
is the brake being pressed?
is the car in park?
the inputs gave me this truth table
key |
brake |
start |
gear |
output |
|---|---|---|---|---|
close |
pressed |
pressed |
in park |
True |
close |
pressed |
pressed |
NOT in park |
False |
close |
NOT pressed |
pressed |
in park |
False |
close |
NOT pressed |
pressed |
NOT in park |
False |
key |
brake |
start |
gear |
output |
|---|---|---|---|---|
NOT close |
pressed |
pressed |
in park |
False |
NOT close |
pressed |
pressed |
NOT in park |
False |
NOT close |
NOT pressed |
pressed |
in park |
False |
NOT close |
NOT pressed |
pressed |
NOT in park |
False |
key |
brake |
start |
gear |
output |
|---|---|---|---|---|
close |
pressed |
NOT pressed |
in park |
False |
close |
pressed |
NOT pressed |
NOT in park |
False |
close |
NOT pressed |
NOT pressed |
in park |
False |
close |
NOT pressed |
NOT pressed |
NOT in park |
False |
key |
brake |
start |
gear |
output |
|---|---|---|---|---|
NOT close |
pressed |
NOT pressed |
in park |
False |
NOT close |
pressed |
NOT pressed |
NOT in park |
False |
NOT close |
NOT pressed |
NOT pressed |
in park |
False |
NOT close |
NOT pressed |
NOT pressed |
NOT in park |
False |
the only time the Car starts is if the start button is pressed AND the key is close to the ignition AND the brake is being pressed AND the car gear is in park.
preview
This is the test I have at the end of the chapter
1import src.car
2import unittest
3
4
5class TestCar(unittest.TestCase):
6
7 def test_car_ignition(self):
8 booleans = (False, True)
9 for start_is_pressed in booleans:
10 for key_is_close in booleans:
11 for brake_is_pressed in booleans:
12 for in_park in booleans:
13 with self.subTest(
14 start_is_pressed=start_is_pressed,
15 key_is_close=key_is_close,
16 brake_is_pressed=brake_is_pressed,
17 in_park=in_park,
18 ):
19 result = src.car.ignition(
20 start_is_pressed=start_is_pressed,
21 key_is_close=key_is_close,
22 brake_is_pressed=brake_is_pressed,
23 in_park=in_park,
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
I open a terminal
I change directory to the car folder in the
pumping_pythonfolderI open
test_car.pyfrom thetestsfolderI use pytest-watcher to run the tests automatically
extract test_car_ignition
RED: make it fail
I add a test with a for loop for all the cases
5class TestCar(unittest.TestCase): 6 7 def test_car_ignition(self): 8 booleans = (False, True) 9 for start_is_pressed in booleans: 10 for key_is_close in booleans: 11 for brake_is_pressed in booleans: 12 for in_park in booleans: 13 with self.subTest( 14 start_is_pressed=start_is_pressed, 15 key_is_close=key_is_close, 16 brake_is_pressed=brake_is_pressed, 17 in_park=in_park, 18 ):19 result = src.car.ignition( 20 start_is_pressed=start_is_pressed, 21 key_is_close=key_is_close, 22 brake_is_pressed=brake_is_pressed, 23 in_park=in_park, 24 ) 25 self.assertEqual(result, 'BOOM!!!') 26 27 def test_park_w_brake_pressed_key_close_start_pressed(self):the terminal is my friend, and shows AssertionError
SUBFAILED( start_is_pressed=False, key_is_close=False, brake_is_pressed=False, in_park=False ) ... AssertionError: False != 'BOOM!!!' SUBFAILED( start_is_pressed=False, key_is_close=False, brake_is_pressed=False, in_park=True ) ... AssertionError: False != 'BOOM!!!' SUBFAILED( start_is_pressed=False, key_is_close=False, brake_is_pressed=True, in_park=False ) ... AssertionError: False != 'BOOM!!!' SUBFAILED( start_is_pressed=False, key_is_close=False, brake_is_pressed=True, in_park=True ) ... AssertionError: False != 'BOOM!!!'SUBFAILED( start_is_pressed=False, key_is_close=True, brake_is_pressed=False, in_park=False ) ... AssertionError: False != 'BOOM!!!' SUBFAILED( start_is_pressed=False, key_is_close=True, brake_is_pressed=False, in_park=True ) ... AssertionError: False != 'BOOM!!!' SUBFAILED( start_is_pressed=False, key_is_close=True, brake_is_pressed=True, in_park=False ) ... AssertionError: False != 'BOOM!!!' SUBFAILED( start_is_pressed=False, key_is_close=True, brake_is_pressed=True, in_park=True ) ... AssertionError: False != 'BOOM!!!'SUBFAILED( start_is_pressed=True, key_is_close=False, brake_is_pressed=False, in_park=False ) ... AssertionError: False != 'BOOM!!!' SUBFAILED( start_is_pressed=True, key_is_close=False, brake_is_pressed=False, in_park=True ) ... AssertionError: False != 'BOOM!!!' SUBFAILED( start_is_pressed=True, key_is_close=False, brake_is_pressed=True, in_park=False ) ... AssertionError: False != 'BOOM!!!' SUBFAILED( start_is_pressed=True, key_is_close=False, brake_is_pressed=True, in_park=True ) ... AssertionError: False != 'BOOM!!!'SUBFAILED( start_is_pressed=True, key_is_close=True, brake_is_pressed=False, in_park=False ) ... AssertionError: False != 'BOOM!!!' SUBFAILED( start_is_pressed=True, key_is_close=True, brake_is_pressed=False, in_park=True ) ... AssertionError: False != 'BOOM!!!' SUBFAILED( start_is_pressed=True, key_is_close=True, brake_is_pressed=True, in_park=False ) ... AssertionError: False != 'BOOM!!!' SUBFAILED( start_is_pressed=True, key_is_close=True, brake_is_pressed=True, in_park=True ) ... AssertionError: True != 'BOOM!!!'
GREEN: make it pass
I change
self.assertEqual(result, 'BOOM!!!')to handle the fifteen cases where theignitionfunction returns False19 result = src.car.ignition( 20 start_is_pressed=start_is_pressed, 21 key_is_close=key_is_close, 22 brake_is_pressed=brake_is_pressed, 23 in_park=in_park, 24 ) 25 self.assertFalse(result) 26 27 def test_park_w_brake_pressed_key_close_start_pressed(self):the terminal is my friend, and shows AssertionError for the one case where the Car starts.
I move the assertion into a try statement for it
19 result = src.car.ignition( 20 start_is_pressed=start_is_pressed, 21 key_is_close=key_is_close, 22 brake_is_pressed=brake_is_pressed, 23 in_park=in_park, 24 ) 25 try: 26 self.assertFalse(result) 27 except AssertionError: 28 self.assertTrue(result) 29 30 def test_park_w_brake_pressed_key_close_start_pressed(self):the test passes.
REFACTOR: make it better
I remove all the other tests because they are now covered by test_car_ignition
close the project
I close
tests/test_car.pyI 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 Car
review
Once again, I used four nested for loops (ugly) to put all the tests together which leaves me with less lines of code and something that is harder to understand.
There has to be a better way that does not write this many loops.
code from the chapter
Do you want to see all the CODE I typed in this chapter?
what is next?
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.