test_functions¶
test_functions_w_pass¶
red: make it fail¶
I open a terminal to run makePythonTdd.sh with
functions
as the name of the project./makePythonTdd.sh functions
on Windows without Windows Subsystem Linux use makePythonTdd.ps1
./makePythonTdd.ps1 functions
it makes the folders and files that are needed, installs packages, runs the first test, and the terminal shows AssertionError
E AssertionError: True is not false tests/test_functions.py:7: AssertionError
I hold
ctrl
(windows/linux) oroption
(mac) on the keyboard and use the mouse to click ontests/test_functions.py:7
to open it in the editorthen change
True
toFalse
and change
test_failure
import unittest
import functions
class TestFunctions(unittest.TestCase):
def test_functions_w_pass(self):
self.assertIsNone(functions.function_w_pass())
the terminal shows ModuleNotFoundError , and I add it to the list of Exceptions encountered
# Exceptions Encountered
# AssertionError
# ModuleNotFoundError
green: make it pass¶
I make a file called
functions.py
in the project folder and the terminal shows AttributeError, which I add to the list of Exceptions encountered# Exceptions Encountered # AssertionError # ModuleNotFoundError # AttributeError
I add a function definition to
functions.py
def function_w_pass(): pass
and we have a passing test
the test checks if the value of the call to
functions.function_w_pass
is Nonethe function definition simply says pass yet the test passes
pass is a placeholder keyword which allows the function definition to follow Python syntax rules
the test passes because in Python all functions return None by default, like the function has an invisible line that says
return None
test_functions_w_return¶
red: make it fail¶
I add a new failing test to TestFunctions
in test_functions.py
to check that functions always return None
def test_functions_w_return(self):
self.assertIsNone(functions.function_w_return())
the terminal shows AttributeError
green: make it fail¶
I add a new function to functions.py
to make the test pass, this time with a return
statement instead of pass
def function_w_return(self):
return
the terminal shows this test also passes
I defined 2 functions with different statements in their body but they both return the same result, because “in Python all functions return None by default, like the function has an invisible line that says return None
”
test_functions_w_return_none¶
red: make it fail¶
I add one more test to the TestFunctions
class in test_functions.py
to help drive home the point
def test_functions_w_return_none(self):
self.assertIsNone(
functions.function_w_return_none()
)
the terminal shows AttributeError
green: make it pass¶
from the Zen of Python: Explicit is better than implicit.
I add a function definition to functions.py
this time with an explicit return
statement showing the value returned
def function_w_return_none():
return None
and the terminal shows passing tests.
test_singleton_functions¶
Singleton functions always return the same thing when called
red: make it fail¶
I add a test to test_functions.py
def test_singleton_functions(self):
self.assertEqual(functions.singleton(), 'my_first_name')
the terminal shows AttributeError
green: make it pass¶
I change the function to make it pass
def singleton():
return 'my_first_name'
test_singleton_functions_w_inputs¶
red: make it fail¶
I add a new test that checks if a singleton that takes inputs returns the same value regardless of the inputs
def test_singleton_functions_w_inputs(self):
self.assertEqual(
functions.singleton_w_inputs('Bob', 'James', 'Frank'),
'joe'
)
self.assertEqual(
functions.singleton_w_inputs('a', 2, 'c', 3),
'joe'
)
the terminal shows AttributeError
green: make it pass¶
and I add a function for singleton_w_inputs
to functions.py
def singleton_w_inputs(*args):
return 'joe'
the terminal shows passing tests
test_passthrough_functions¶
Passthrough functions return their input as output
red: make it fail¶
I add a failing test to the TestFunctions
class in test_functions.py
def test_passthrough_functions(self):
self.assertEqual(functions.passthrough(False), False)
the terminal shows AttributeError
green: make it pass¶
I add a function definition to
functions.py
def passthrough(): return None
the terminal shows TypeError
TypeError: passthrough() takes 0 positional arguments but 1 was given
because the definition for
passthrough
does not allow inputs and the test sends False as inputI add the error to the list of Exceptions encountered
# Exceptions Encountered # AssertionError # ModuleNotFoundError # AttributeError # TypeError
then I make
passthrough
infunctions.py
to take 1 positional argumentdef passthrough(argument): return None
and the terminal shows AssertionError
AssertionError: None != False
because the result of calling
functions.passthrough
with False as input is None which is not equal to the expected result (False)I change the definition of
passthrough
to make the test passdef passthrough(argument): return False
the terminal shows passing tests. I am genius!
refactor: make it better¶
Wait a minute! Something is not quite right here. The definition for a passthrough function was that it returned the same thing it was given, the test passes when False is given as input, will it still pass when another value is given or will it always return False? Time to write a test
I add a new assertion to
test_passthrough_functions
def test_passthrough_functions(self): self.assertEqual(functions.passthrough(False), False) self.assertEqual(functions.passthrough(True), True)
the terminal shows AssertionError
AssertionError: False != True
the function returns False instead of True in the second case, I am not all the way genius, yet
I change the definition of
passthrough
infunctions.py
def passthrough(argument): return argument
the terminal shows passing tests. I have more confidence that the passthrough function will return its input.
I add more tests for good measure using the other Python data structures
def test_passthrough_functions(self): self.assertEqual(functions.passthrough(False), False) self.assertEqual(functions.passthrough(True), True) self.assertEqual(functions.passthrough(None), False) self.assertEqual(functions.passthrough(int), False) self.assertEqual(functions.passthrough(str), False) self.assertEqual(functions.passthrough(tuple), False) self.assertEqual(functions.passthrough(list), False) self.assertEqual(functions.passthrough(set), False) self.assertEqual(functions.passthrough(dict), False)
the terminal shows AssertionError for each line until I make the input match the output, proving that the passthrough function I have defined returns the input it is given. Hooray! I am genius again
review¶
The 3 ways I have defined functions so far have the exact same outcome, they all return None
. If Explicit is better than implicit.
then I prefer to use return None
telling anyone who reads the code exactly what the function returns.
Here is what I know so far from the tests
passthrough functions return their input
singleton functions always return the same thing
Would you like to test singleton functions?