test person with unittest


I want to use the unittest library in the person project.


preview

I have these tests by the end of the chapter

person/tests/test_person.py
 1import src.person
 2import unittest
 3
 4
 5class TestPerson(unittest.TestCase):
 6
 7    def assert_person_factory_works(
 8            self, first_name, last_name,
 9            sex, year_of_birth
10        ):
11        self.assertEqual(
12            src.person.person(
13                first_name=first_name,
14                last_name=last_name,
15                sex=sex,
16                year_of_birth=year_of_birth,
17            ),
18            (
19                f'{first_name}, {last_name},'
20                f' {sex}, {year_of_birth}'
21            )
22        )
person/tests/test_person.py
24    def assert_say_hello_works(
25            self, first_name, last_name,
26            year_of_birth,
27        ):
28        self.assertEqual(
29            src.person.say_hello(
30                first_name=first_name,
31                last_name=last_name,
32                year_of_birth=year_of_birth
33            ),
34            (
35                f'Hello, my name is {first_name}'
36                f' {last_name} and I am'
37                f' {2026-year_of_birth}.'
38            )
39        )
person/tests/test_person.py
41    def assert_person_can_say_hello(
42            self,first_name, last_name,
43            sex, year_of_birth,
44        ):
45        self.assertEqual(
46            src.person.Person(
47                first_name=first_name,
48                last_name=last_name,
49                sex=sex,
50                year_of_birth=year_of_birth,
51            ).say_hello(),
52            (
53                f'Hello, my name is {first_name}'
54                f' {last_name} and I am'
55                f' {2026-year_of_birth}.'
56            )
57        )
person/tests/test_person.py
59    def test_joe(self):
60        first_name = 'joe'
61        last_name = 'blow'
62        sex = 'M'
63        year_of_birth = 1996
64
65        self.assert_person_factory_works(
66            first_name=first_name,
67            last_name=last_name,
68            sex=sex,
69            year_of_birth=year_of_birth
70        )
71
72        self.assert_say_hello_works(
73            first_name=first_name,
74            last_name=last_name,
75            year_of_birth=year_of_birth,
76        )
77
78        self.assert_person_can_say_hello(
79            first_name=first_name,
80            last_name=last_name,
81            sex=sex,
82            year_of_birth=year_of_birth
83        )
person/tests/test_person.py
 85    def test_jane(self):
 86        first_name = 'jane'
 87        last_name = 'doe'
 88        sex = 'F'
 89        year_of_birth = 1991
 90
 91        self.assert_person_factory_works(
 92            first_name=first_name,
 93            last_name=last_name,
 94            sex=sex,
 95            year_of_birth=year_of_birth,
 96        )
 97
 98        self.assert_say_hello_works(
 99            first_name=first_name,
100            last_name=last_name,
101            year_of_birth=year_of_birth,
102        )
103
104        self.assert_person_can_say_hello(
105            first_name=first_name,
106            last_name=last_name,
107            sex=sex,
108            year_of_birth=year_of_birth,
109        )
person/tests/test_person.py
111    def test_john(self):
112        first_name = 'john'
113        last_name = 'smith'
114        sex = 'M'
115        year_of_birth = 1580
116
117        self.assert_person_factory_works(
118            first_name=first_name,
119            last_name=last_name,
120            sex=sex,
121            year_of_birth=year_of_birth,
122        )
123
124        self.assert_say_hello_works(
125            first_name=first_name,
126            last_name=last_name,
127            year_of_birth=year_of_birth,
128        )
129
130        self.assert_person_can_say_hello(
131            first_name=first_name,
132            last_name=last_name,
133            sex=sex,
134            year_of_birth=year_of_birth,
135        )
person/tests/test_person.py
137    def test_mary(self):
138        first_name = 'mary'
139        last_name = 'public'
140        sex = 'F'
141        year_of_birth = 2000
142
143        self.assert_person_factory_works(
144            first_name=first_name,
145            last_name=last_name,
146            sex=sex,
147            year_of_birth=year_of_birth,
148        )
149
150        self.assert_say_hello_works(
151            first_name=first_name,
152            last_name=last_name,
153            year_of_birth=year_of_birth,
154        )
155
156        self.assert_person_can_say_hello(
157            first_name=first_name,
158            last_name=last_name,
159            sex=sex,
160            year_of_birth=year_of_birth,
161        )
person/tests/test_person.py
163    def test_dir_person_class(self):
164        self.assertEqual(
165            dir(src.person.Person),
166            [
167                '__class__', '__delattr__', '__dict__',
168                '__dir__', '__doc__', '__eq__',
169                '__firstlineno__', '__format__', '__ge__',
170                '__getattribute__', '__getstate__', '__gt__',
171                '__hash__', '__init__', '__init_subclass__',
172                '__le__', '__lt__', '__module__', '__ne__',
173                '__new__', '__reduce__', '__reduce_ex__',
174                '__repr__', '__setattr__', '__sizeof__',
175                '__static_attributes__', '__str__',
176                '__subclasshook__', '__weakref__', 'say_hello'
177            ]
178        )
person/tests/test_person.py
180    def test_dir_person_instance(self):
181        self.assertEqual(
182            dir(
183                src.person.Person(
184                    first_name='first_name',
185                    last_name='last_name',
186                    sex='M',
187                    year_of_birth=2026,
188                )
189            ),
190            [
191                '__class__', '__delattr__', '__dict__',
192                '__dir__', '__doc__', '__eq__',
193                '__firstlineno__', '__format__', '__ge__',
194                '__getattribute__', '__getstate__', '__gt__',
195                '__hash__', '__init__', '__init_subclass__',
196                '__le__', '__lt__', '__module__', '__ne__',
197                '__new__', '__reduce__', '__reduce_ex__',
198                '__repr__', '__setattr__', '__sizeof__',
199                '__static_attributes__', '__str__',
200                '__subclasshook__', '__weakref__', 'first_name',
201                'last_name', 'say_hello', 'sex', 'year_of_birth',
202            ]
203        )
204
205
206# Exceptions seen
207# AssertionError
208# NameError
209# TypeError
210# AttributeError
211# SyntaxError

open the project

  • I open a terminal

  • I change directory to the project

    cd person
    
  • I open test_person.py from the tests folder

  • I use pytest-watcher to run the tests automatically

    uv run pytest-watcher . --now
    

    the terminal shows

    tests/test_person.py ......                         [100%]
    
    =================== 6 passed in A.BCs ====================
    

add TestPerson class

RED: make it fail


I add an object named TestPerson to test_person.py

45def assert_person_factory_works(
46        first_name, last_name,
47        sex, year_of_birth
48    ):
49    assert_equal(
50        src.person.person(
51            first_name=first_name,
52            last_name=last_name,
53            sex=sex,
54            year_of_birth=year_of_birth,
55        ),
56        (
57            f'{first_name}, {last_name},'
58            f' {sex}, {year_of_birth}'
59        )
60    )
61
62
63class TestPerson(object):
64
65    def test_failure(self):
66        self.assertEqual(False, True)
67
68
69def test_joe():

the terminal is my friend, and shows AttributeError

AttributeError: 'TestPerson' object
                has no attribute 'assertEqual'

GREEN: make it pass


  • I add unittest.TestCase as the parent object of TestPerson

    63# class TestPerson(object):
    64class TestPerson(unittest.TestCase):
    65
    66    def test_failure(self):
    67        self.assertEqual(False, True)
    

    the terminal is my friend, and shows NameError

    NameError: name 'unittest' is not defined.
               Did you forget to import 'unittest'?
    
  • I add an import statement at the top of the file

    1import src.person
    2import unittest
    3
    4
    5def assert_equal(left, right):
    6    assert left == right
    

    the terminal is my friend, and shows AssertionError

    AssertionError: False != True
    
  • I change False to True in the assertion

    64# class TestPerson(object):
    65class TestPerson(unittest.TestCase):
    66
    67    def test_failure(self):
    68        # self.assertEqual(False, True)
    69        self.assertEqual(True, True)
    70
    71
    72def test_joe():
    

    the test passes.


REFACTOR: make it better


  • I remove the commented lines

    46def assert_person_factory_works(
    47        first_name, last_name,
    48        sex, year_of_birth
    49    ):
    50    assert_equal(
    51        src.person.person(
    52            first_name=first_name,
    53            last_name=last_name,
    54            sex=sex,
    55            year_of_birth=year_of_birth,
    56        ),
    57        (
    58            f'{first_name}, {last_name},'
    59            f' {sex}, {year_of_birth}'
    60        )
    61    )
    62
    63
    64class TestPerson(unittest.TestCase):
    65
    66    def test_failure(self):
    67        self.assertEqual(True, True)
    68
    69
    70def test_joe():
    
  • I open a new terminal then make sure I am in the person folder

    cd person
    
  • I add a git commit message in the new terminal

    git commit -am \
    'add TestPerson class'
    

move test_joe to TestPerson

RED: make it fail


  • I go back to the terminal where the tests are running

  • I remove test_failure from the TestPerson class

  • I move test_joe to make it a method of the TestPerson class

    64class TestPerson(unittest.TestCase):
    65
    66    def test_joe():
    67        first_name = 'joe'
    68        last_name = 'blow'
    69        sex = 'M'
    70        year_of_birth = 1996
    71
    72        assert_person_factory_works(
    73            first_name=first_name,
    74            last_name=last_name,
    75            sex=sex,
    76            year_of_birth=year_of_birth
    77        )
    78
    79        assert_say_hello_works(
    80            first_name=first_name,
    81            last_name=last_name,
    82            year_of_birth=year_of_birth,
    83        )
    84
    85        assert_person_can_say_hello(
    86            first_name=first_name,
    87            last_name=last_name,
    88            sex=sex,
    89            year_of_birth=year_of_birth
    90        )
    91
    92
    93def test_jane():
    

    the terminal is my friend, and shows TypeError

    TypeError: TestPerson.test_joe() takes
               0 positional arguments but 1 was given
    

    because a method of an instance takes the instance of the class (self) it belongs to as the first argument.


GREEN: make it pass


  • I add the staticmethod decorator to test_joe because …

    64class TestPerson(unittest.TestCase):
    65
    66    @staticmethod
    67    def test_joe():
    68        first_name = 'joe'
    

    the test is green again.

  • I add a git commit message in the other terminal

    git commit -am 'move test_joe to TestPerson'
    

move test_jane to TestPerson

RED: make it fail


  • I go back to the terminal where the tests are running

  • I move test_jane to make it a method of the TestPerson class

     86        assert_person_can_say_hello(
     87            first_name=first_name,
     88            last_name=last_name,
     89            sex=sex,
     90            year_of_birth=year_of_birth
     91        )
     92
     93    def test_jane():
     94        first_name = 'jane'
     95        last_name = 'doe'
     96        sex = 'F'
     97        year_of_birth = 1991
     98
     99        assert_person_factory_works(
    100            first_name=first_name,
    101            last_name=last_name,
    102            sex=sex,
    103            year_of_birth=year_of_birth,
    104        )
    105
    106        assert_say_hello_works(
    107            first_name=first_name,
    108            last_name=last_name,
    109            year_of_birth=year_of_birth,
    110        )
    111
    112        assert_person_can_say_hello(
    113            first_name=first_name,
    114            last_name=last_name,
    115            sex=sex,
    116            year_of_birth=year_of_birth,
    117        )
    118
    119
    120def test_john():
    

    the terminal is my friend, and shows TypeError

    TypeError: TestPerson.test_jane() takes
               0 positional arguments but 1 was given
    

    because …


GREEN: make it pass


  • I add the staticmethod decorator to test_jane since it also does not use anything in the TestPerson class, yet

    86        assert_person_can_say_hello(
    87            first_name=first_name,
    88            last_name=last_name,
    89            sex=sex,
    90            year_of_birth=year_of_birth
    91        )
    92
    93    @staticmethod
    94    def test_jane():
    

    the test passes.

  • I add a git commit message in the other terminal

    git commit -am 'move test_jane to TestPerson'
    

move test_john to TestPerson

RED: make it fail


  • I go back to the terminal where the tests are running

  • I move test_john to make it a method of the TestPerson class

    113        assert_person_can_say_hello(
    114            first_name=first_name,
    115            last_name=last_name,
    116            sex=sex,
    117            year_of_birth=year_of_birth,
    118        )
    119
    120    def test_john():
    121        first_name = 'john'
    122        last_name = 'smith'
    123        sex = 'M'
    124        year_of_birth = 1580
    125
    126        assert_person_factory_works(
    127            first_name=first_name,
    128            last_name=last_name,
    129            sex=sex,
    130            year_of_birth=year_of_birth,
    131        )
    132
    133        assert_say_hello_works(
    134            first_name=first_name,
    135            last_name=last_name,
    136            year_of_birth=year_of_birth,
    137        )
    138
    139        assert_person_can_say_hello(
    140            first_name=first_name,
    141            last_name=last_name,
    142            sex=sex,
    143            year_of_birth=year_of_birth,
    144        )
    145
    146
    147def test_mary():
    

    the terminal is my friend, and shows TypeError

    TypeError: TestPerson.test_john() takes
               0 positional arguments but 1 was given
    

    because a method of an instance takes the instance of the class (self) it belongs to as the first argument.


GREEN: make it pass


  • I also add the staticmethod decorator to test_john

    113        assert_person_can_say_hello(
    114            first_name=first_name,
    115            last_name=last_name,
    116            sex=sex,
    117            year_of_birth=year_of_birth,
    118        )
    119
    120    @staticmethod
    121    def test_john():
    

    green again.

  • I add a git commit message in the other terminal

    git commit -am 'move test_john to TestPerson'
    

move test_mary to TestPerson

RED: make it fail


  • I go back to the terminal where the tests are running

  • I move test_mary to make it a method of the TestPerson class

    140        assert_person_can_say_hello(
    141            first_name=first_name,
    142            last_name=last_name,
    143            sex=sex,
    144            year_of_birth=year_of_birth,
    145        )
    146
    147    def test_mary():
    148        first_name = 'mary'
    149        last_name = 'public'
    150        sex = 'F'
    151        year_of_birth = 2000
    152
    153        assert_person_factory_works(
    154            first_name=first_name,
    155            last_name=last_name,
    156            sex=sex,
    157            year_of_birth=year_of_birth,
    158        )
    159
    160        assert_say_hello_works(
    161            first_name=first_name,
    162            last_name=last_name,
    163            year_of_birth=year_of_birth,
    164        )
    165
    166        assert_person_can_say_hello(
    167            first_name=first_name,
    168            last_name=last_name,
    169            sex=sex,
    170            year_of_birth=year_of_birth,
    171        )
    172
    173
    174def test_dir_person_class():
    

    the terminal is my friend, and shows TypeError

    TypeError: TestPerson.test_mary() takes
               0 positional arguments but 1 was given
    

    because a method of an instance takes the instance of the class (self) it belongs to as the first argument.


GREEN: make it pass


  • I add the staticmethod decorator to test_mary because I can use it when a method does not use anything in the object it belongs to

    140        assert_person_can_say_hello(
    141            first_name=first_name,
    142            last_name=last_name,
    143            sex=sex,
    144            year_of_birth=year_of_birth,
    145        )
    146
    147    @staticmethod
    148    def test_mary():
    

    green.

  • I add a git commit message in the other terminal

    git commit -am 'move test_mary to TestPerson'
    

test_dir_person_class with unittest

RED: make it fail


  • I go back to the terminal where the tests are running

  • I move test_dir_person_class to make it a method of the TestPerson class

    167        assert_person_can_say_hello(
    168            first_name=first_name,
    169            last_name=last_name,
    170            sex=sex,
    171            year_of_birth=year_of_birth,
    172        )
    173
    174    def test_dir_person_class():
    175        assert_equal(
    176            dir(src.person.Person),
    177            [
    178                '__class__', '__delattr__', '__dict__',
    
    187                '__subclasshook__', '__weakref__', 'say_hello'
    188            ]
    189        )
    190
    191
    192def test_dir_person_instance():
    

    the terminal is my friend, and shows TypeError

    TypeError:
        TestPerson.test_dir_person_class()
        takes 0 positional arguments but 1 was given
    

    because a method of an instance takes the instance of the class (self) it belongs to as the first argument.


GREEN: make it pass


I add self to the parentheses of test_dir_person_class

167        assert_person_can_say_hello(
168            first_name=first_name,
169            last_name=last_name,
170            sex=sex,
171            year_of_birth=year_of_birth,
172        )
173
174    # def test_dir_person_class():
175    def test_dir_person_class(self):
176        assert_equal(
177            dir(src.person.Person),
178            [
179                '__class__', '__delattr__', '__dict__',

green again.


REFACTOR: make it better


  • I change the call to my assert_equal function to the assertNotEqual method of the unittest.TestCase class in test_dir_person_class

    174    # def test_dir_person_class():
    175    def test_dir_person_class(self):
    176        # assert_equal(
    177        self.assertNotEqual(
    178            dir(src.person.Person),
    179            [
    180                '__class__', '__delattr__', '__dict__',
    

    the terminal is my friend, and shows AssertionError.

  • I change assertNotEqual to assertEqual in test_dir_person_class

    174    # def test_dir_person_class():
    175    def test_dir_person_class(self):
    176        # assert_equal(
    177        # self.assertNotEqual(
    178        self.assertEqual(
    179            dir(src.person.Person),
    180            [
    181                '__class__', '__delattr__', '__dict__',
    

    the test passes.

  • I remove the commented lines from test_dir_person_class

    167        assert_person_can_say_hello(
    168            first_name=first_name,
    169            last_name=last_name,
    170            sex=sex,
    171            year_of_birth=year_of_birth,
    172        )
    173
    174    def test_dir_person_class(self):
    175        self.assertEqual(
    176            dir(src.person.Person),
    177            [
    178                '__class__', '__delattr__', '__dict__',
    
    187                '__subclasshook__', '__weakref__', 'say_hello'
    188            ]
    189        )
    190
    191
    192def test_dir_person_instance():
    
  • I add a git commit message in the other terminal

    git commit -am
    'move test_dir_person_class to TestPerson'
    

test_dir_person_instance with unittest

RED: make it fail


  • I go back to the terminal where the tests are running

  • I move test_dir_person_instance to make it a method of the TestPerson class

    187                '__subclasshook__', '__weakref__', 'say_hello'
    188            ]
    189        )
    190
    191    def test_dir_person_instance():
    192        assert_equal(
    193            dir(
    194                src.person.Person(
    195                    first_name='first_name',
    196                    last_name='last_name',
    197                    sex='M',
    198                    year_of_birth=2026,
    199                )
    200            ),
    201            [
    202                '__class__', '__delattr__', '__dict__',
    
    212                'last_name', 'say_hello', 'sex', 'year_of_birth',
    213            ]
    214        )
    215
    216
    217# Exceptions seen
    

    the terminal is my friend, and shows TypeError

    TypeError:
        TestPerson.test_dir_person_instance()
        takes 0 positional arguments but 1 was given
    

    because …


GREEN: make it pass


I add self to the parentheses of test_dir_person_instance

187                '__subclasshook__', '__weakref__', 'say_hello'
188            ]
189        )
190
191    # def test_dir_person_instance():
192    def test_dir_person_instance(self):
193        assert_equal(
194            dir(
195                src.person.Person(
196                    first_name='first_name',
197                    last_name='last_name',
198                    sex='M',
199                    year_of_birth=2026,
200                )
201            ),
202            [
203                '__class__', '__delattr__', '__dict__',

the test is green again.


REFACTOR: make it better


  • I change the call to my assert_equal function to the assertNotEqual method of the unittest.TestCase class in test_dir_person_instance

    191    # def test_dir_person_instance():
    192    def test_dir_person_instance(self):
    193        # assert_equal(
    194        self.assertNotEqual(
    195            dir(
    196                src.person.Person(
    197                    first_name='first_name',
    198                    last_name='last_name',
    199                    sex='M',
    200                    year_of_birth=2026,
    201                )
    202            ),
    203            [
    204                '__class__', '__delattr__', '__dict__',
    

    the terminal is my friend, and shows AssertionError.

  • I change assertNotEqual to assertEqual in test_dir_person_instance

    191    # def test_dir_person_instance():
    192    def test_dir_person_instance(self):
    193        # assert_equal(
    194        # self.assertNotEqual(
    195        self.assertEqual(
    196            dir(
    197                src.person.Person(
    198                    first_name='first_name',
    199                    last_name='last_name',
    200                    sex='M',
    201                    year_of_birth=2026,
    202                )
    203            ),
    204            [
    205                '__class__', '__delattr__', '__dict__',
    

    the test passes.

  • I remove the commented lines from test_dir_person_instance

    187                '__subclasshook__', '__weakref__', 'say_hello'
    188            ]
    189        )
    190
    191    def test_dir_person_instance(self):
    192        self.assertEqual(
    193            dir(
    194                src.person.Person(
    195                    first_name='first_name',
    196                    last_name='last_name',
    197                    sex='M',
    198                    year_of_birth=2026,
    199                )
    200            ),
    201            [
    202                '__class__', '__delattr__', '__dict__',
    
    212                'last_name', 'say_hello', 'sex', 'year_of_birth',
    213            ]
    214        )
    215
    216
    217# Exceptions seen
    218# AssertionError
    219# NameError
    220# TypeError
    221# AttributeError
    222# SyntaxError
    
  • I add a git commit message in the other terminal

    git commit -am
    'move test_dir_person_instance to TestPerson'
    

move assert_person_can_say_hello to TestPerson

RED: make it fail


  • I go back to the terminal where the tests are running

  • I add a copy of the assert_person_can_say_hello function to make it a method of the TestPerson class

    64class TestPerson(unittest.TestCase):
    65
    66    def assert_person_can_say_hello(
    67            first_name, last_name,
    68            sex, year_of_birth,
    69        ):
    70        assert_equal(
    71            src.person.Person(
    72                first_name=first_name,
    73                last_name=last_name,
    74                sex=sex,
    75                year_of_birth=year_of_birth,
    76            ).say_hello(),
    77            (
    78                f'Hello, my name is {first_name}'
    79                f' {last_name} and I am'
    80                f' {2026-year_of_birth}.'
    81            )
    82        )
    83
    84    @staticmethod
    85    def test_joe():
    
  • I change the call from the assert_person_can_say_hello function to the assert_person_can_say_hello method of the TestPerson class in test_joe

    84    @staticmethod
    85    def test_joe():
    86        first_name = 'joe'
    87        last_name = 'blow'
    88        sex = 'M'
    89        year_of_birth = 1996
    90
    91        assert_person_factory_works(
    92            first_name=first_name,
    93            last_name=last_name,
    94            sex=sex,
    95            year_of_birth=year_of_birth
    96        )
    
     98        assert_say_hello_works(
     99            first_name=first_name,
    100            last_name=last_name,
    101            year_of_birth=year_of_birth,
    102        )
    103
    104        # assert_person_can_say_hello(
    105        self.assert_person_can_say_hello(
    106            first_name=first_name,
    107            last_name=last_name,
    108            sex=sex,
    109            year_of_birth=year_of_birth
    110        )
    111
    112    @staticmethod
    113    def test_jane():
    

    the terminal is my friend, and shows NameError

    NameError: name 'self' is not defined
    

GREEN: make it pass


  • I add self to the parentheses of test_joe

    84    @staticmethod
    85    # def test_joe():
    86    def test_joe(self):
    87        first_name = 'joe'
    88        last_name = 'blow'
    89        sex = 'M'
    90        year_of_birth = 1996
    

    the terminal is my friend, and shows TypeError

    TypeError: TestPerson.test_joe() missing
               1 required positional argument: 'self'
    
  • I comment out the staticmethod decorator from test_joe

    84    # @staticmethod
    85    # def test_joe():
    86    def test_joe(self):
    

    the terminal is my friend, and shows TypeError

    TypeError: TestPerson.assert_person_can_say_hello()
               got multiple values for argument 'first_name'
    

    because a method of an instance takes the instance of the class (self) it belongs to as the first argument.

  • I add self to the parentheses of the assert_person_can_say_hello method of the TestPerson class

    64class TestPerson(unittest.TestCase):
    65
    66    def assert_person_can_say_hello(
    67            # first_name, last_name,
    68            self, first_name, last_name,
    69            sex, year_of_birth,
    70        ):
    

    the test is green again.


REFACTOR: make it better


  • I change the call to my assert_equal function to the assertNotEqual method of the unittest.TestCase class in the assert_person_can_say_hello method of the TestPerson class

    66    def assert_person_can_say_hello(
    67            # first_name, last_name,
    68            self,first_name, last_name,
    69            sex, year_of_birth,
    70        ):
    71        # assert_equal(
    72        self.assertNotEqual(
    73            src.person.Person(
    74                first_name=first_name,
    75                last_name=last_name,
    76                sex=sex,
    77                year_of_birth=year_of_birth,
    78            ).say_hello(),
    79            (
    80                f'Hello, my name is {first_name}'
    81                f' {last_name} and I am'
    82                f' {2026-year_of_birth}.'
    83            )
    84        )
    

    the terminal is my friend, and shows AssertionError

    AssertionError: 'Hello, my name is joe blow and I am 30.'
                 == 'Hello, my name is joe blow and I am 30.'
    
  • I change assertNotEqual to assertEqual in the assert_person_can_say_hello method of the TestPerson class

    66    def assert_person_can_say_hello(
    67            # first_name, last_name,
    68            self,first_name, last_name,
    69            sex, year_of_birth,
    70        ):
    71        # assert_equal(
    72        # self.assertNotEqual(
    73        self.assertEqual(
    74            src.person.Person(
    75                first_name=first_name,
    76                last_name=last_name,
    77                sex=sex,
    78                year_of_birth=year_of_birth,
    79            ).say_hello(),
    80            (
    81                f'Hello, my name is {first_name}'
    82                f' {last_name} and I am'
    83                f' {2026-year_of_birth}.'
    84            )
    85        )
    

    the test is green again.

  • I remove the commented lines from the assert_person_can_say_hello method of the TestPerson class

    64class TestPerson(unittest.TestCase):
    65
    66    def assert_person_can_say_hello(
    67            self,first_name, last_name,
    68            sex, year_of_birth,
    69        ):
    70        self.assertEqual(
    71            src.person.Person(
    72                first_name=first_name,
    73                last_name=last_name,
    74                sex=sex,
    75                year_of_birth=year_of_birth,
    76            ).say_hello(),
    77            (
    78                f'Hello, my name is {first_name}'
    79                f' {last_name} and I am'
    80                f' {2026-year_of_birth}.'
    81            )
    82        )
    83
    84    # @staticmethod
    85    # def test_joe():
    86    def test_joe(self):
    
  • I change the call from the assert_person_can_say_hello function to the assert_person_can_say_hello method of the TestPerson class in test_jane

    113    @staticmethod
    114    def test_jane():
    115        first_name = 'jane'
    116        last_name = 'doe'
    117        sex = 'F'
    118        year_of_birth = 1991
    119
    120        assert_person_factory_works(
    121            first_name=first_name,
    122            last_name=last_name,
    123            sex=sex,
    124            year_of_birth=year_of_birth,
    125        )
    
    127        assert_say_hello_works(
    128            first_name=first_name,
    129            last_name=last_name,
    130            year_of_birth=year_of_birth,
    131        )
    132
    133        # assert_person_can_say_hello(
    134        self.assert_person_can_say_hello(
    135            first_name=first_name,
    136            last_name=last_name,
    137            sex=sex,
    138            year_of_birth=year_of_birth,
    139        )
    140
    141    @staticmethod
    142    def test_john():
    

    the terminal is my friend, and shows NameError

    NameError: name 'self' is not defined
    
  • I add self to the parentheses of test_jane

    113    @staticmethod
    114    # def test_jane():
    115    def test_jane(self):
    116        first_name = 'jane'
    

    the terminal is my friend, and shows TypeError

    TypeError: TestPerson.test_jane() missing
               1 required positional argument: 'self'
    
  • I comment out the staticmethod decorator from test_jane

    113    # @staticmethod
    114    # def test_jane():
    115    def test_jane(self):
    116        first_name = 'jane'
    

    the test is green again.

  • I change the call from the assert_person_can_say_hello function to the assert_person_can_say_hello method of the TestPerson class in test_john

    142    @staticmethod
    143    def test_john():
    144        first_name = 'john'
    145        last_name = 'smith'
    146        sex = 'M'
    147        year_of_birth = 1580
    148
    149        assert_person_factory_works(
    150            first_name=first_name,
    151            last_name=last_name,
    152            sex=sex,
    153            year_of_birth=year_of_birth,
    154        )
    
    156        assert_say_hello_works(
    157            first_name=first_name,
    158            last_name=last_name,
    159            year_of_birth=year_of_birth,
    160        )
    161
    162        # assert_person_can_say_hello(
    163        self.assert_person_can_say_hello(
    164            first_name=first_name,
    165            last_name=last_name,
    166            sex=sex,
    167            year_of_birth=year_of_birth,
    168        )
    169
    170    @staticmethod
    171    def test_mary():
    

    the terminal is my friend, and shows NameError

    NameError: name 'self' is not defined
    
  • I add self to the parentheses of test_john

    142    @staticmethod
    143    # def test_john():
    144    def test_john(self):
    145        first_name = 'john'
    

    the terminal is my friend, and shows TypeError

    TypeError: TestPerson.test_john() missing
               1 required positional argument: 'self'
    
  • I comment out the staticmethod decorator from test_john

    142    # @staticmethod
    143    # def test_john():
    144    def test_john(self):
    145        first_name = 'john'
    

    the test is green again.

  • I change the call from the assert_person_can_say_hello function to the assert_person_can_say_hello method of the TestPerson class in test_mary

    171    @staticmethod
    172    def test_mary():
    173        first_name = 'mary'
    174        last_name = 'public'
    175        sex = 'F'
    176        year_of_birth = 2000
    177
    178        assert_person_factory_works(
    179            first_name=first_name,
    180            last_name=last_name,
    181            sex=sex,
    182            year_of_birth=year_of_birth,
    183        )
    
    185        assert_say_hello_works(
    186            first_name=first_name,
    187            last_name=last_name,
    188            year_of_birth=year_of_birth,
    189        )
    190
    191        # assert_person_can_say_hello(
    192        self.assert_person_can_say_hello(
    193            first_name=first_name,
    194            last_name=last_name,
    195            sex=sex,
    196            year_of_birth=year_of_birth,
    197        )
    198
    199    def test_dir_person_class(self):
    

    the terminal is my friend, and shows NameError

    NameError: name 'self' is not defined
    
  • I add self to the parentheses of test_mary

    171    @staticmethod
    172    # def test_mary():
    173    def test_mary(self):
    174        first_name = 'mary'
    

    the terminal is my friend, and shows TypeError

    TypeError: TestPerson.test_mary() missing
               1 required positional argument: 'self'
    
  • I comment out the staticmethod decorator from test_mary

    171    # @staticmethod
    172    # def test_mary():
    173    def test_mary(self):
    174        first_name = 'mary'
    

    green again.

  • I remove the assert_person_can_say_hello function since it is now a repetition

     1import src.person
     2import unittest
     3
     4
     5def assert_equal(left, right):
     6    assert left == right
     7
     8
     9def assert_say_hello_works(
    10        first_name, last_name,
    11        year_of_birth,
    12    ):
    

    all the tests are still green.

  • I add a git commit message in the other terminal

    git commit -am
    'move assert_person_can_say_hello to TestPerson'
    

move assert_say_hello_works to TestPerson

RED: make it fail


  • I go back to the terminal where the tests are running

  • I add a copy of the assert_say_hello_works function to make it a method of the TestPerson class

    45class TestPerson(unittest.TestCase):
    46
    47    def assert_say_hello_works(
    48            first_name, last_name,
    49            year_of_birth,
    50        ):
    51        assert_equal(
    52            src.person.say_hello(
    53                first_name=first_name,
    54                last_name=last_name,
    55                year_of_birth=year_of_birth
    56            ),
    57            (
    58                f'Hello, my name is {first_name}'
    59                f' {last_name} and I am'
    60                f' {2026-year_of_birth}.'
    61            )
    62        )
    63
    64    def assert_person_can_say_hello(
    65            self, first_name, last_name,
    66            sex, year_of_birth,
    67        ):
    
  • I change the call from the assert_say_hello_works function to the assert_say_hello_works method of the TestPerson class in test_joe

     82    # @staticmethod
     83    # def test_joe():
     84    def test_joe(self):
     85        first_name = 'joe'
     86        last_name = 'blow'
     87        sex = 'M'
     88        year_of_birth = 1996
     89
     90        assert_person_factory_works(
     91            first_name=first_name,
     92            last_name=last_name,
     93            sex=sex,
     94            year_of_birth=year_of_birth
     95        )
     96
     97        # assert_say_hello_works(
     98        self.assert_say_hello_works(
     99            first_name=first_name,
    100            last_name=last_name,
    101            year_of_birth=year_of_birth,
    102        )
    

    the terminal is my friend, and shows TypeError

    TypeError: TestPerson.assert_say_hello_works()
               got multiple values for argument 'first_name'
    

    because …


GREEN: make it pass


  • I add self to the parentheses of the assert_say_hello_works method of the TestPerson class

    45class TestPerson(unittest.TestCase):
    46
    47    def assert_say_hello_works(
    48            # first_name, last_name,
    49            self,first_name, last_name,
    50            year_of_birth,
    51        ):
    

    the test is green again.


REFACTOR: make it better


  • I remove the commented line from the assert_say_hello_works method of the TestPerson class

    45class TestPerson(unittest.TestCase):
    46
    47    def assert_say_hello_works(
    48            self,first_name, last_name,
    49            year_of_birth,
    50        ):
    
  • I change the call from the assert_say_hello_works function to the assert_say_hello_works method of the TestPerson class in test_jane

    112    # @staticmethod
    113    # def test_jane():
    114    def test_jane(self):
    115        first_name = 'jane'
    116        last_name = 'doe'
    117        sex = 'F'
    118        year_of_birth = 1991
    119
    120        assert_person_factory_works(
    121            first_name=first_name,
    122            last_name=last_name,
    123            sex=sex,
    124            year_of_birth=year_of_birth,
    125        )
    126
    127        # assert_say_hello_works(
    128        self.assert_say_hello_works(
    129            first_name=first_name,
    130            last_name=last_name,
    131            year_of_birth=year_of_birth,
    132        )
    

    the test is still green.

  • I change the call from the assert_say_hello_works function to the assert_say_hello_works method of the TestPerson class in test_john

    142    # @staticmethod
    143    # def test_john():
    144    def test_john(self):
    145        first_name = 'john'
    146        last_name = 'smith'
    147        sex = 'M'
    148        year_of_birth = 1580
    149
    150        assert_person_factory_works(
    151            first_name=first_name,
    152            last_name=last_name,
    153            sex=sex,
    154            year_of_birth=year_of_birth,
    155        )
    156
    157        # assert_say_hello_works(
    158        self.assert_say_hello_works(
    159            first_name=first_name,
    160            last_name=last_name,
    161            year_of_birth=year_of_birth,
    162        )
    

    still green.

  • I change the call from the assert_say_hello_works function to the assert_say_hello_works method of the TestPerson class in test_mary

    172    # @staticmethod
    173    # def test_mary():
    174    def test_mary(self):
    175        first_name = 'mary'
    176        last_name = 'public'
    177        sex = 'F'
    178        year_of_birth = 2000
    179
    180        assert_person_factory_works(
    181            first_name=first_name,
    182            last_name=last_name,
    183            sex=sex,
    184            year_of_birth=year_of_birth,
    185        )
    186
    187        # assert_say_hello_works(
    188        self.assert_say_hello_works(
    189            first_name=first_name,
    190            last_name=last_name,
    191            year_of_birth=year_of_birth,
    192        )
    

    green.

  • I change the call to my assert_equal function to the assertNotEqual method of the unittest.TestCase class in the assert_say_hello_works method of the TestPerson class

    47    def assert_say_hello_works(
    48            self, first_name, last_name,
    49            year_of_birth,
    50        ):
    51        # assert_equal(
    52        self.assertNotEqual(
    53            src.person.say_hello(
    54                first_name=first_name,
    55                last_name=last_name,
    56                year_of_birth=year_of_birth
    57            ),
    58            (
    59                f'Hello, my name is {first_name}'
    60                f' {last_name} and I am'
    61                f' {2026-year_of_birth}.'
    62            )
    63        )
    

    the terminal is my friend, and shows AssertionError

    FAILED ...test_jane - AssertionError:
        'Hello, my name is jane doe and I am 35.'
     == 'Hello, my name is jane doe and I am 35.'
    FAILED ...test_joe - AssertionError:
        'Hello, my name is joe blow and I am 30.'
     == 'Hello, my name is joe blow and I am 30.'
    FAILED ...test_john - AssertionError:
        'Hello, my name is john smith and I am 446.'
     == 'Hello, my name is john smith and I am 446.'
    FAILED ...test_mary - AssertionError:
        'Hello, my name is mary public and I am 26.'
     == 'Hello, my name is mary public and I am 26.'
    
  • I change assertNotEqual to assertEqual in the assert_say_hello_works method of the TestPerson class

    47    def assert_say_hello_works(
    48            self, first_name, last_name,
    49            year_of_birth,
    50        ):
    51        # assert_equal(
    52        # self.assertNotEqual(
    53        self.assertEqual(
    54            src.person.say_hello(
    55                first_name=first_name,
    56                last_name=last_name,
    57                year_of_birth=year_of_birth
    58            ),
    59            (
    60                f'Hello, my name is {first_name}'
    61                f' {last_name} and I am'
    62                f' {2026-year_of_birth}.'
    63            )
    64        )
    

    the test is green again.

  • I remove the commented lines from the assert_say_hello_works method of the TestPerson class

    47    def assert_say_hello_works(
    48            self, first_name, last_name,
    49            year_of_birth,
    50        ):
    51        self.assertEqual(
    52            src.person.say_hello(
    53                first_name=first_name,
    54                last_name=last_name,
    55                year_of_birth=year_of_birth
    56            ),
    57            (
    58                f'Hello, my name is {first_name}'
    59                f' {last_name} and I am'
    60                f' {2026-year_of_birth}.'
    61            )
    62        )
    63
    64    def assert_person_can_say_hello(
    
  • I remove the assert_say_hello_works function since it is now a repetition

     1import src.person
     2import unittest
     3
     4
     5def assert_equal(left, right):
     6    assert left == right
     7
     8
     9def assert_person_factory_works(
    10        first_name, last_name,
    11        sex, year_of_birth
    12    ):
    

    the tests are still green.

  • I add a git commit message in the other terminal

    git commit -am
    'move assert_say_hello_works to TestPerson'
    

move assert_person_factory_works to TestPerson

RED: make it fail


  • I go back to the terminal where the tests are running

  • I add a copy of the assert_person_factory_works function to make it a method of the TestPerson class

    27class TestPerson(unittest.TestCase):
    28
    29    def assert_person_factory_works(
    30            first_name, last_name,
    31            sex, year_of_birth
    32        ):
    33        assert_equal(
    34            src.person.person(
    35                first_name=first_name,
    36                last_name=last_name,
    37                sex=sex,
    38                year_of_birth=year_of_birth,
    39            ),
    40            (
    41                f'{first_name}, {last_name},'
    42                f' {sex}, {year_of_birth}'
    43            )
    44        )
    45
    46    def assert_say_hello_works(
    47            self, first_name, last_name,
    48            year_of_birth,
    49        ):
    
  • I change the call from the assert_person_factory_works function to the assert_person_factory_works method of the TestPerson class in test_joe

    81    # @staticmethod
    82    # def test_joe():
    83    def test_joe(self):
    84        first_name = 'joe'
    85        last_name = 'blow'
    86        sex = 'M'
    87        year_of_birth = 1996
    88
    89        # assert_person_factory_works(
    90        self.assert_person_factory_works(
    91            first_name=first_name,
    92            last_name=last_name,
    93            sex=sex,
    94            year_of_birth=year_of_birth
    95        )
    

    the terminal is my friend, and shows TypeError

    TypeError: TestPerson.assert_person_factory_works()
               got multiple values for argument 'first_name'
    

GREEN: make it pass



REFACTOR: make it better


  • I remove the commented line from the assert_person_factory_works method of the TestPerson class

    27class TestPerson(unittest.TestCase):
    28
    29    def assert_person_factory_works(
    30            self, first_name, last_name,
    31            sex, year_of_birth
    32        ):
    
  • I remove the commented lines from test_joe

    63    def assert_person_can_say_hello(
    64            self,first_name, last_name,
    65            sex, year_of_birth,
    66        ):
    67        self.assertEqual(
    68            src.person.Person(
    69                first_name=first_name,
    70                last_name=last_name,
    71                sex=sex,
    72                year_of_birth=year_of_birth,
    73            ).say_hello(),
    74            (
    75                f'Hello, my name is {first_name}'
    76                f' {last_name} and I am'
    77                f' {2026-year_of_birth}.'
    78            )
    79        )
    
    81    def test_joe(self):
    82        first_name = 'joe'
    83        last_name = 'blow'
    84        sex = 'M'
    85        year_of_birth = 1996
    86
    87        self.assert_person_factory_works(
    88            first_name=first_name,
    89            last_name=last_name,
    90            sex=sex,
    91            year_of_birth=year_of_birth
    92        )
    
     94        self.assert_say_hello_works(
     95            first_name=first_name,
     96            last_name=last_name,
     97            year_of_birth=year_of_birth,
     98        )
     99
    100        self.assert_person_can_say_hello(
    101            first_name=first_name,
    102            last_name=last_name,
    103            sex=sex,
    104            year_of_birth=year_of_birth
    105        )
    106
    107    # @staticmethod
    108    # def test_jane():
    109    def test_jane(self):
    
  • I change the call from the assert_person_factory_works function to the assert_person_factory_works method of the TestPerson class in test_jane

    107    # @staticmethod
    108    # def test_jane():
    109    def test_jane(self):
    110        first_name = 'jane'
    111        last_name = 'doe'
    112        sex = 'F'
    113        year_of_birth = 1991
    114
    115        # assert_person_factory_works(
    116        self.assert_person_factory_works(
    117            first_name=first_name,
    118            last_name=last_name,
    119            sex=sex,
    120            year_of_birth=year_of_birth,
    121        )
    

    still green.

  • I remove the commented lines from test_jane

    100        self.assert_person_can_say_hello(
    101            first_name=first_name,
    102            last_name=last_name,
    103            sex=sex,
    104            year_of_birth=year_of_birth
    105        )
    106
    107    def test_jane(self):
    108        first_name = 'jane'
    109        last_name = 'doe'
    110        sex = 'F'
    111        year_of_birth = 1991
    112
    113        self.assert_person_factory_works(
    114            first_name=first_name,
    115            last_name=last_name,
    116            sex=sex,
    117            year_of_birth=year_of_birth,
    118        )
    
    120        self.assert_say_hello_works(
    121            first_name=first_name,
    122            last_name=last_name,
    123            year_of_birth=year_of_birth,
    124        )
    125
    126        self.assert_person_can_say_hello(
    127            first_name=first_name,
    128            last_name=last_name,
    129            sex=sex,
    130            year_of_birth=year_of_birth,
    131        )
    132
    133    # @staticmethod
    134    # def test_john():
    135    def test_john(self):
    
  • I change the call from the assert_person_factory_works function to the assert_person_factory_works method of the TestPerson class in test_john

    133    # @staticmethod
    134    # def test_john():
    135    def test_john(self):
    136        first_name = 'john'
    137        last_name = 'smith'
    138        sex = 'M'
    139        year_of_birth = 1580
    140
    141        # assert_person_factory_works(
    142        self.assert_person_factory_works(
    143            first_name=first_name,
    144            last_name=last_name,
    145            sex=sex,
    146            year_of_birth=year_of_birth,
    147        )
    

    the test is still green.

  • I remove the commented lines from test_john

    126        self.assert_person_can_say_hello(
    127            first_name=first_name,
    128            last_name=last_name,
    129            sex=sex,
    130            year_of_birth=year_of_birth,
    131        )
    132
    133    def test_john(self):
    134        first_name = 'john'
    135        last_name = 'smith'
    136        sex = 'M'
    137        year_of_birth = 1580
    138
    139        self.assert_person_factory_works(
    140            first_name=first_name,
    141            last_name=last_name,
    142            sex=sex,
    143            year_of_birth=year_of_birth,
    144        )
    
    146        self.assert_say_hello_works(
    147            first_name=first_name,
    148            last_name=last_name,
    149            year_of_birth=year_of_birth,
    150        )
    151
    152        self.assert_person_can_say_hello(
    153            first_name=first_name,
    154            last_name=last_name,
    155            sex=sex,
    156            year_of_birth=year_of_birth,
    157        )
    158
    159    # @staticmethod
    160    # def test_mary():
    161    def test_mary(self):
    
  • I change the call from the assert_person_factory_works function to the assert_person_factory_works method of the TestPerson class in test_mary

    159    # @staticmethod
    160    # def test_mary():
    161    def test_mary(self):
    162        first_name = 'mary'
    163        last_name = 'public'
    164        sex = 'F'
    165        year_of_birth = 2000
    166
    167        # assert_person_factory_works(
    168        self.assert_person_factory_works(
    169            first_name=first_name,
    170            last_name=last_name,
    171            sex=sex,
    172            year_of_birth=year_of_birth,
    173        )
    

    green.

  • I remove the commented lines from test_mary

    152        self.assert_person_can_say_hello(
    153            first_name=first_name,
    154            last_name=last_name,
    155            sex=sex,
    156            year_of_birth=year_of_birth,
    157        )
    158
    159    def test_mary(self):
    160        first_name = 'mary'
    161        last_name = 'public'
    162        sex = 'F'
    163        year_of_birth = 2000
    164
    165        self.assert_person_factory_works(
    166            first_name=first_name,
    167            last_name=last_name,
    168            sex=sex,
    169            year_of_birth=year_of_birth,
    170        )
    
    172        self.assert_say_hello_works(
    173            first_name=first_name,
    174            last_name=last_name,
    175            year_of_birth=year_of_birth,
    176        )
    177
    178        self.assert_person_can_say_hello(
    179            first_name=first_name,
    180            last_name=last_name,
    181            sex=sex,
    182            year_of_birth=year_of_birth,
    183        )
    184
    185    def test_dir_person_class(self):
    
  • I change the call to my assert_equal function to the assertNotEqual method of the unittest.TestCase class in the assert_person_factory_works method of the TestPerson class

    29    def assert_person_factory_works(
    30            self, first_name, last_name,
    31            sex, year_of_birth
    32        ):
    33        # assert_equal(
    34        self.assertNotEqual(
    35            src.person.person(
    36                first_name=first_name,
    37                last_name=last_name,
    38                sex=sex,
    39                year_of_birth=year_of_birth,
    40            ),
    41            (
    42                f'{first_name}, {last_name},'
    43                f' {sex}, {year_of_birth}'
    44            )
    45        )
    

    the terminal is my friend, and shows AssertionError

    FAILED ...test_jane - AssertionError:
        'jane, doe, F, 1991' == 'jane, doe, F, 1991'
    FAILED ...test_joe - AssertionError:
        'joe, blow, M, 1996' == 'joe, blow, M, 1996'
    FAILED ...test_john - AssertionError:
        'john, smith, M, 1580' == 'john, smith, M, 1580'
    FAILED ...test_mary - AssertionError:
        'mary, public, F, 2000' == 'mary, public, F, 2000'
    
  • I change assertNotEqual to assertEqual in the assert_person_factory_works method of the TestPerson class

    29    def assert_person_factory_works(
    30            self, first_name, last_name,
    31            sex, year_of_birth
    32        ):
    33        # assert_equal(
    34        # self.assertNotEqual(
    35        self.assertEqual(
    36            src.person.person(
    37                first_name=first_name,
    38                last_name=last_name,
    39                sex=sex,
    40                year_of_birth=year_of_birth,
    41            ),
    42            (
    43                f'{first_name}, {last_name},'
    44                f' {sex}, {year_of_birth}'
    45            )
    46        )
    

    the test is green again.

  • I remove the commented lines from the assert_person_factory_works method of the TestPerson class

    27class TestPerson(unittest.TestCase):
    28
    29    def assert_person_factory_works(
    30            self, first_name, last_name,
    31            sex, year_of_birth
    32        ):
    33        self.assertEqual(
    34            src.person.person(
    35                first_name=first_name,
    36                last_name=last_name,
    37                sex=sex,
    38                year_of_birth=year_of_birth,
    39            ),
    40            (
    41                f'{first_name}, {last_name},'
    42                f' {sex}, {year_of_birth}'
    43            )
    44        )
    
  • I remove the assert_person_factory_works function since it is now a repetition and my assert_equal function since it is no longer used

    1import src.person
    2import unittest
    3
    4
    5class TestPerson(unittest.TestCase):
    

    green.

  • I add a git commit message in the other terminal

    git commit -am
    'move assert_person_factory_works to TestPerson'
    

close the project

  • I close test_person.py

  • I click in the terminal where the tests are running

  • I use q on the keyboard to leave the tests. The terminal goes back to the command line.

  • I change directory to the parent of person

    cd ..
    

    the terminal shows

    ...\pumping_python
    

    I am back in the pumping_python directory.


review


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 telephone project with the unittest library?


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.