functions 3
Since I know how to use for loops, I can do better with the assertions of test_why_use_a_function
open the project
I change directory to the
functionsfoldercd functionsthe terminal shows I am in the
functionsfolder.../pumping_python/functionsI use
pytest-watcherto run the testsuv run pytest-watcher . --nowthe terminal shows
rootdir: .../pumping_python/functions configfile: pyproject.toml collected 12 items tests/test_functions.py ............ [100%] ======================= 12 passed in X.YZs =========================I hold ctrl on the keyboard, then click on
tests/test_functions.pyto open it in the editor
a better way to test why use a function
RED: make it fail
I add a variable to test_why_use_a_function
7 def test_why_use_a_function(self): 8 def add(x=3, y=0): 9 return x + y 10 11 x = 4 12 numbers = (0, 1, 2, 3, 4, 5, 6, 7, 8, 9) 13 14 y = 0 15 self.assertEqual(add(x, y), x+y)I add a for loop with an assertion and the subTest method
11 x = 4 12 numbers = (0, 1, 2, 3, 4, 5, 6, 7, 8, 9) 13 for y in numbers: 14 with self.subTest(y=y): 15 self.assertEqual(add(x, y), x+x) 16 17 y = 0 18 self.assertEqual(add(x, y), x+y)the terminal shows AssertionError
SUBFAILED(y=0) ... - AssertionError: 4 != 104 SUBFAILED(y=1) ... - AssertionError: 5 != 104 SUBFAILED(y=2) ... - AssertionError: 6 != 104 SUBFAILED(y=3) ... - AssertionError: 7 != 104 SUBFAILED(y=4) ... - AssertionError: 8 != 104 SUBFAILED(y=5) ... - AssertionError: 9 != 104 SUBFAILED(y=6) ... - AssertionError: 10 != 104 SUBFAILED(y=7) ... - AssertionError: 11 != 104 SUBFAILED(y=8) ... - AssertionError: 12 != 104 SUBFAILED(y=9) ... - AssertionError: 13 != 104
GREEN: make it pass
I change the calculation to x+y
11 x = 4
12 numbers = (0, 1, 2, 3, 4, 5, 6, 7, 8, 9)
13 for y in numbers:
14 with self.subTest(y=y):
15 self.assertEqual(add(x, y), x+y)
the test passes
REFACTOR: make it better
I remove the other assertions because the for loop does what they do
7 def test_why_use_a_function(self): 8 def add(x=3, y=0): 9 return x + y 10 11 x = 4 12 numbers = (0, 1, 2, 3, 4, 5, 6, 7, 8, 9) 13 for y in numbers: 14 with self.subTest(y=y): 15 self.assertEqual(add(x, y), x+y) 16 17 def test_making_a_function_w_pass(self):I add a for loop for the value of
x11 x = 4 12 numbers = (0, 1, 2, 3, 4, 5, 6, 7, 8, 9) 13 for y in numbers: 14 for x in numbers: 15 with self.subTest(x=x, y=y): 16 self.assertEqual(add(x, y), x+100)the terminal shows AssertionError
================== 100 failed, 12 passed in X.YZs ===================the two for loops go through every combination of
xandy(x, y) (0, 0) (0, 1) (0, 2) ... (5, 0) (5, 1) (5, 2) ... (9, 7) (9, 8) (9, 9)I change the calculation in the expectation to the right thing
16 self.assertEqual(add(x, y), x+y)the test passes
I remove the
xvariable, then the default values from theaddfunction7 def test_why_use_a_function(self): 8 def add(x, y): 9 return x + y 10 11 numbers = (0, 1, 2, 3, 4, 5, 6, 7, 8, 9) 12 for y in numbers: 13 for x in numbers: 14 with self.subTest(x=x, y=y): 15 self.assertEqual(add(x, y), x+y)the test is still green
I can use a list comprehension instead of the 2 for loops
11 numbers = (0, 1, 2, 3, 4, 5, 6, 7, 8, 9) 12 for y in numbers: 13 for x in numbers: 14 with self.subTest(x=x, y=y): 15 self.assertEqual(add(x, y), x+y) 16 17 for x, y in ((x, y) for x in numbers for y in numbers): 18 with self.subTest(x=x, y=y): 19 self.assertEqual(add(x, y), x+100)the terminal shows AssertionError
================== 100 failed, 12 passed in X.YZs ===================I change the calculation in the expectation
15 self.assertEqual(add(x, y), x+y)the test passes. That used
for3 times, confusing.I can do the same thing with the product method from the itertools module which comes with Python, it needs an import statement
17 for x, y in ((x, y) for x in numbers for y in numbers): 18 with self.subTest(x=x, y=y): 19 self.assertEqual(add(x, y), x+y) 20 21 import itertools 22 for x, y in itertools.product(numbers, repeat=2): 23 with self.subTest(x=x, y=y): 24 self.assertEqual(add(x, y), x+100)the terminal shows AssertionError
================== 100 failed, 12 passed in X.YZs ===================I change the expectation
24 self.assertEqual(add(x, y), x+y) 25 26 def test_making_a_function_w_pass(self):the test passes, not as confusing.
I can use a range object to make the test use more than 10 numbers
11 # numbers = range(0, 1, 2, 3, 4, 5, 6, 7, 8, 9) 12 numbers = range(-10, 10) 13 for y in numbers:the test is still green
I change the expectation in the first assertion
11 # numbers = range(0, 1, 2, 3, 4, 5, 6, 7, 8, 9) 12 numbers = range(-10, 10) 13 for y in numbers: 14 for x in numbers: 15 with self.subTest(x=x, y=y): 16 self.assertEqual(add(x, y), x+100)the terminal shows AssertionError
================== 400 failed, 12 passed in X.YZs ===================the test takes longer to run because there are more numbers to calculate
I change the expectation back then remove the commented line
5class TestFunctions(unittest.TestCase): 6 7 def test_why_use_a_function(self): 8 def add(x, y): 9 return x + y 10 11 numbers = range(-10, 10) 12 for y in numbers: 13 for x in numbers: 14 with self.subTest(x=x, y=y): 15 self.assertEqual(add(x, y), x+y) 16 17 for x, y in ((x, y) for x in numbers for y in numbers): 18 with self.subTest(x=x, y=y): 19 self.assertEqual(add(x, y), x+y) 20 21 import itertools 22 for x, y in itertools.product(numbers, repeat=2): 23 with self.subTest(x=x, y=y): 24 self.assertEqual(add(x, y), x+y) 25 26 def test_making_a_function_w_pass(self):the test is green again
close the project
I close
test_functions.pyandfunctions.pyin the editorI click in the terminal, then use q on the keyboard to leave the tests. The terminal goes back to the command line
I change directory to the parent of
functionscd ..the terminal shows
.../pumping_pythonI am back in the
pumping_pythondirectory
review
I used a for loop to remove repetition.
Why did my “list comprehensions” look like tuples and not lists?
code from the chapter
what is next?
you know
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