how to pass values¶
I want to test passing values to programs. When testing, I want to be able to send input from my test to the program and see the results. This helps me see what is the same, and what is different, the difference gives helps me know what to change to get what I want.
requirements¶
I open a terminal to run makePythonTdd.sh with
telephoneas the name of the project./makePythonTdd.sh telephone
on Windows without Windows Subsystem Linux use makePythonTdd.ps1
./makePythonTdd.ps1 telephone
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_telephone.py:7: AssertionError
I hold
ctrl(windows/linux) oroption(mac) on the keyboard and use the mouse to click ontests/test_telephone.py:7to open it in the editorthen I change
TruetoFalseto make the test pass7 self.assertFalse(False)I change the name of the class to match the CapWords format
4class TestTelephone(unittest.TestCase):
test_passing_a_string¶
red: make it fail¶
green: make it pass¶
I add it to the list of Exceptions encountered
13# Exceptions Encountered 14# AssertionError 15# NameError
then I add an import statement for the
telephonemodule at the top of the fileNote
the …(ellipsis) represents code that does not need to change in this part
1import src.telephone 2import unittest 3 4 5class TestTelephone(unittest.TestCase): 6 7 ...
the terminal shows AttributeError
AttributeError: module 'src.telephone' has no attribute 'text'
I add it to the list of Exceptions encountered in
test_telephone.py14# Exceptions Encountered 15# AssertionError 16# NameError 17# AttributeError
I click on
telephone.pyin thesrcfolder to open it in the editor, then add a name1text
NameError: name 'text' is not defined
I point
textto None1text = None
TypeError: 'NoneType' object is not callable
I add it to the list of Exceptions encountered in
test_telephone.py14# Exceptions Encountered 15# AssertionError 16# NameError 17# AttributeError 18# TypeError
I change
textto a function to make it callable intelephone.py1def text(): 2 return None
TypeError: text() takes 0 positional arguments but 1 was given
src.telephone.textwas called with"hello"as input but the definition of the function does not take any input - the parentheses are emptyI make the function take input and call it
value1def text(value): 2 return None
the terminal shows AssertionError
AssertionError: None != 'I received: hello'
when I copy the string from the terminal and paste it in the return statement to replace None
1def text(value): 2 return 'I received: hello'
the test passes!
refactor: make it better¶
The problem with this solution is that the text function does not care about the input it receives and will always return 'I received: hello' when it is called. I want it to return the value it receives as part of the message.
red: make it fail¶
I add a new assertion to test_passing_a_string in test_telephone.py
7 def test_passing_a_string(self):
8 self.assertEqual(
9 src.telephone.text("hello"),
10 "I received: hello"
11 )
12 self.assertEqual(
13 src.telephone.text("yes"),
14 "I received: yes"
15 )
16
17
18# Exceptions Encountered
19...
the terminal shows AssertionError
AssertionError: 'I received: hello' != 'I received: yes'
green: make it pass¶
I change the return statement in
telephone.py1def text(value): 2 return 'I received: yes'
the terminal shows AssertionError
AssertionError: 'I received: yes' != 'I received: hello'
this will not work, my change breaks the test that was passing before. The return statement has to use the input
I use an f-string which allows me add any values I want to a string
1def text(value): 2 return f'I received: {value}'
the test passes. This is called string interpolation, I can use it to put values in strings. A string is any characters in between quotes e.g.
'a string made with single quotes'"a string made with double quotes"'''a string made with triple single quotes'''"""a string made with triple double quotes"""
I want to see what happens when I pass other Python basic data structures to the program
test_passing_a_class¶
red: make it fail¶
I add a failing test for a class in test_telephone.py
5class TestTelephone(unittest.TestCase):
6
7 def test_passing_a_string(self):
8 self.assertEqual(
9 src.telephone.text("hello"),
10 "I received: hello"
11 )
12 self.assertEqual(
13 src.telephone.text("yes"),
14 "I received: yes"
15 )
16
17 def test_passing_a_class(self):
18 self.assertEqual(
19 src.telephone.text(object),
20 "I received: object"
21 )
22
23
24# Exceptions Encountered
25...
the terminal shows AssertionError
AssertionError: "I received: <class 'object'>" != 'I received: object'
object is the mother class that all Python classes come from
green: make it pass¶
I make the expectation match reality
17 def test_passing_a_class(self):
18 self.assertEqual(
19 src.telephone.text(object),
20 "I received: <class 'object'>"
21 )
the test passes
refactor: make it better¶
I add another assertion with the TestTelephone class to test_passing_a_class
17 def test_passing_a_class(self):
18 self.assertEqual(
19 src.telephone.text(object),
20 "I received: <class 'object'>"
21 )
22 self.assertEqual(
23 src.telephone.text(TestTelephone),
24 "I received: <class 'object'>"
25 )
the terminal shows AssertionError
AssertionError: "I received: <class 'tests.test_telephone.TestTelephone'>" != "I received: <class 'object'>"
even though they are both classes, object and TestTelephone are different. I change the expectation
17 def test_passing_a_class(self):
18 self.assertEqual(
19 src.telephone.text(object),
20 "I received: <class 'object'>"
21 )
22 self.assertEqual(
23 src.telephone.text(TestTelephone),
24 "I received: <class 'tests.test_telephone.TestTelephone'>"
25 )
the test passes.
test_passing_none¶
red: make it fail¶
I add a new failing test for None in test_telephone.py
17 def test_passing_a_class(self):
18 self.assertEqual(
19 src.telephone.text(object),
20 "I received: <class 'object'>"
21 )
22 self.assertEqual(
23 src.telephone.text(TestTelephone),
24 "I received: <class 'tests.test_telephone.TestTelephone'>"
25 )
26
27 def test_passing_none(self):
28 self.assertEqual(
29 src.telephone.text(None),
30 "I received: 'None'"
31 )
the terminal shows AssertionError
AssertionError: 'I received: None' != "I received: 'None'"
green: make it pass¶
I remove the quotes from around None in the expectation
27 def test_passing_none(self):
28 self.assertEqual(
29 src.telephone.text(None),
30 "I received: None"
31 )
the test passes.
test_passing_a_boolean¶
red: make it fail¶
I add a test for booleans, first with an assertion for True
Note
the …(ellipsis) represents code that does not need to change in this part
27 def test_passing_none(self):
28 self.assertEqual(
29 src.telephone.text(None),
30 "I received: None"
31 )
32
33 def test_passing_a_boolean(self):
34 self.assertEqual(
35 src.telephone.text(True),
36 "I received: 'True'"
37 )
the terminal shows AssertionError
AssertionError: "I received: True" != "I received: 'True'"
green: make it pass¶
I change the expectation
33 def test_passing_a_boolean(self): 34 self.assertEqual( 35 src.telephone.text(True), 36 "I received: True" 37 )
the test passes
-
33 def test_passing_a_boolean(self): 34 self.assertEqual( 35 src.telephone.text(True), 36 "I received: True" 37 ) 38 self.assertEqual( 39 src.telephone.text(False), 40 "I received: 'False'" 41 )
the terminal shows AssertionError
AssertionError: "I received: False" != "I received: 'False'"
I change the expectation
33 def test_passing_a_boolean(self): 34 self.assertEqual( 35 src.telephone.text(True), 36 "I received: True" 37 ) 38 self.assertEqual( 39 src.telephone.text(False), 40 "I received: False" 41 )
the test passes.
test_passing_an_integer¶
red: make it fail¶
I add a test for an integer (a whole number)
33 def test_passing_a_boolean(self):
34 self.assertEqual(
35 src.telephone.text(True),
36 "I received: True"
37 )
38 self.assertEqual(
39 src.telephone.text(False),
40 "I received: False"
41 )
42
43 def test_passing_an_integer(self):
44 self.assertEqual(
45 src.telephone.text(1234),
46 "I received: '1234'"
47 )
the terminal shows AssertionError
AssertionError: 'I received: 1234' != "I received: '1234'"
green: make it pass¶
I remove the quotes from the expectation
43 def test_passing_an_integer(self):
44 self.assertEqual(
45 src.telephone.text(1234),
46 "I received: 1234"
47 )
the test passes.
test_passing_a_float¶
red: make it fail¶
I add a test for a float (floating point decimal numbers)
43 def test_passing_an_integer(self):
44 self.assertEqual(
45 src.telephone.text(1234),
46 "I received: 1234"
47 )
48
49 def test_passing_a_float(self):
50 self.assertEqual(
51 src.telephone.text(1.234),
52 "I received: '1.234'"
53 )
the terminal shows AssertionError
AssertionError: 'I received: 1.234' != "I received: '1.234'"
green: make it pass¶
I remove the quotes from the number
49 def test_passing_a_float(self):
50 self.assertEqual(
51 src.telephone.text(1.234),
52 "I received: 1.234"
53 )
the test passes.
test_passing_a_tuple¶
red: make it fail¶
I add a test for a tuple (things in parentheses (()), separated by a comma)
49 def test_passing_a_float(self):
50 self.assertEqual(
51 src.telephone.text(1.234),
52 "I received: 1.234"
53 )
54
55 def test_passing_a_tuple(self):
56 self.assertEqual(
57 src.telephone.text((1, 2, 3, "n")),
58 "I received: '(1, 2, 3, n)'"
59 )
the terminal shows AssertionError
AssertionError: "I received: (1, 2, 3, 'n')" != "I received: '(1, 2, 3, n)'"
green: make it pass¶
I change the expectation
55 def test_passing_a_tuple(self):
56 self.assertEqual(
57 src.telephone.text((1, 2, 3, "n")),
58 "I received: (1, 2, 3, 'n')"
59 )
the test passes.
test_passing_a_list¶
red: make it fail¶
I add a test for a list (things in square brackets ([]), separated by a comma)
55 def test_passing_a_tuple(self):
56 self.assertEqual(
57 src.telephone.text((1, 2, 3, "n")),
58 "I received: (1, 2, 3, 'n')"
59 )
60
61 def test_passing_a_list(self):
62 self.assertEqual(
63 src.telephone.text([1, 2, 3, "n"]),
64 "I received: '[1, 2, 3, n]'"
65 )
the terminal shows AssertionError
AssertionError: "I received: [1, 2, 3, 'n']" != "I received: '[1, 2, 3, n]'"
green: make it pass¶
I change the expectation to match reality
61 def test_passing_a_list(self):
62 self.assertEqual(
63 src.telephone.text([1, 2, 3, "n"]),
64 "I received: [1, 2, 3, 'n']"
65 )
the test passes.
test_passing_a_dictionary¶
red: make it fail¶
I add a test for a dictionary (key-value pairs in curly braces ({}), separated by a comma)
61 def test_passing_a_list(self):
62 self.assertEqual(
63 src.telephone.text([1, 2, 3, "n"]),
64 "I received: [1, 2, 3, 'n']"
65 )
66
67 def test_passing_a_dictionary(self):
68 self.assertEqual(
69 src.telephone.text({
70 "key1": "value1",
71 "keyN": [0, 1, 2, "n"],
72 }),
73 "I received: '{key1: value1, keyN: [0, 1, 2, 'n']}'"
74 )
the terminal shows AssertionError
AssertionError: "I received: {'key1': 'value1', 'keyN': [0, 1, 2, 'n']}" != "I received: '{key1: value1, keyN: [0, 1, 2, 'n']}'"
green: make it pass¶
I change the expectation
67 def test_passing_a_dictionary(self):
68 self.assertEqual(
69 src.telephone.text({
70 "key1": "value1",
71 "keyN": [0, 1, 2, "n"],
72 }),
73 "I received: {'key1': 'value1', 'keyN': [0, 1, 2, 'n']}"
74 )
75
76
77# Exceptions Encountered
78...
the terminal shows all tests are passing.
test_telephone¶
Time to write the program that makes the tests pass without looking at test_telephone.py
red: make it fail¶
I close
test_telephone.pythen delete all the text in
telephone.py, the terminal shows AttributeErrorAttributeError: module 'src.telephone' has no attribute 'text'
green: make it pass¶
I add the name to
telephone.py1text
NameError: name 'text' is not defined
I point it to None
1text = None
TypeError: 'NoneType' object is not callable
I make
texta function1def text(): 2 return None
TypeError: text() takes 0 positional arguments but 1 was given
I make the function take input
1def text(argument): 2 return None
the terminal shows AssertionError
AssertionError: None != 'I received: None'
I copy the string from the terminal and paste it in the return statement to match the expectation of the test
1def text(argument): 2 return 'I received: None'
the terminal shows AssertionError
AssertionError: 'I received: None' != 'I received: 1234'
I add a return statement to see the difference between the input and the expected output
1def text(argument): 2 return argument 3 return 'I received: None'
the test summary info shows that every test has AssertionError
AssertionError: True != 'I received: True' AssertionError: <class 'object'> != "I received: <class 'object'>" AssertionError: {'key1': 'value1', 'keyN': [0, 1, 2, 'n']} != "I received: {'key1': 'value1', 'keyN': [0, 1, 2, 'n']}" AssertionError: 1.234 != 'I received: 1.234' AssertionError: [1, 2, 3, 'n'] != "I received: [1, 2, 3, 'n']" AssertionError: "hello" != 'I received: hello' AssertionError: (1, 2, 3, 'n') != "I received: (1, 2, 3, 'n')" AssertionError: 1234 != 'I received: 1234' AssertionError: None != 'I received: None'
they all expect the input as part of the message
I remove the first return statement then make the second one use an f-string
1def text(argument): 2 return f'I received: {argument}'
and all the tests are passing! Once again! I am a programmer!!
review¶
Here are the tests I ran to see what happens when I pass Python basic data structures from a test to a program and place them in an f-string
I also ran into the following Exceptions
Would you like to test making a person?
Click Here to see the code from this chapter