how to make a person


This is an exercise in making dictionaries with functions. I think they are the 2 most important things in Python


preview

These are the tests I have by the end of the chapter

 1import datetime
 2import random
 3import src.person
 4import unittest
 5
 6
 7def choose(*choices):
 8    return random.choice(choices)
 9
10
11def this_year():
12    return datetime.datetime.now().year
13
14
15class TestPerson(unittest.TestCase):
16
17    def setUp(self):
18        self.random_year_of_birth = random.randint(
19            this_year()-120, this_year()
20        )
21        self.random_first_name = choose('jane', 'joe', 'john', 'person')
22
23    def test_factory_takes_keyword_arguments(self):
24        a_person = dict(
25            first_name=self.random_first_name,
26            last_name=choose('doe', 'smith', 'blow', 'public'),
27            sex=choose('F', 'M'),
28        )
29
30        self.assertEqual(
31            src.person.factory(
32                **a_person,
33                year_of_birth=self.random_year_of_birth,
34            ),
35            dict(
36                **a_person,
37                age=this_year()-self.random_year_of_birth,
38            )
39        )
40
41    def test_factory_w_default_arguments(self):
42        self.assertEqual(
43            src.person.factory(
44                first_name=self.random_first_name,
45                year_of_birth=self.random_year_of_birth,
46            ),
47            dict(
48                first_name=self.random_first_name,
49                last_name='doe',
50                sex='M',
51                age=this_year()-self.random_year_of_birth,
52            )
53        )
54
55
56# Exceptions seen
57# AssertionError
58# NameError
59# AttributeError
60# TypeError
61# SyntaxError

start the project


test_factory_takes_keyword_arguments

RED: make it fail


  • I change test_failure to test_factory_takes_keyword_arguments

     1import unittest
     2
     3
     4class TestPerson(unittest.TestCase):
     5
     6    def test_factory_takes_keyword_arguments(self):
     7        self.assertEqual(
     8            src.person.factory(),
     9            None
    10        )
    11
    12
    13# Exceptions seen
    14# AssertionError
    

    the terminal shows NameError

    NameError: name 'src' is not defined
    
  • I add NameError to the list of Exceptions seen

    13# Exceptions seen
    14# AssertionError
    15# NameError
    

GREEN: make it pass


  • I add an import statement for the person module at the top of test_person.py

    1import src.person
    2import unittest
    

    the terminal shows AttributeError

    AttributeError: module 'src.person' has no attribute 'factory'
    

    there is nothing in person.py with that name

  • I add AttributeError to the list of Exceptions seen

    14# Exceptions seen
    15# AssertionError
    16# NameError
    17# AttributeError
    
  • I open person.py from the src folder in the editor

  • I add a function to person.py

    1def factory():
    2    return None
    

    the test passes


  • I want the function to take in a keyword argument called first_name. I add it to the test in test_person.py

     7    def test_factory_takes_keyword_arguments(self):
     8        self.assertEqual(
     9            src.person.factory(
    10                first_name='first_name',
    11            ),
    12            None
    13        )
    14
    15
    16# Exceptions seen
    

    the terminal shows TypeError

    TypeError: factory() got an unexpected keyword argument 'first_name'
    

    the test calls the factory function with input, but the definition in person.py does not take any input

  • I add TypeError to the list of Exceptions seen in test_person.py

    16# Exceptions seen
    17# AssertionError
    18# NameError
    19# AttributeError
    20# TypeError
    
  • I add first_name as an input parameter to the function in person.py

    1def factory(first_name):
    2    return None
    

    the test passes


  • I want the function to take in a keyword argument called last_name. I add it to the test in test_person.py

     7    def test_factory_takes_keyword_arguments(self):
     8        self.assertEqual(
     9            src.person.factory(
    10                first_name='first_name',
    11                last_name='last_name',
    12            ),
    13            None
    14        )
    

    the terminal shows TypeError

    TypeError: factory() got an unexpected keyword argument 'last_name'. Did you mean 'first_name'?
    

    the test calls the factory function with 2 inputs, but the definition in person.py only takes 1 input

  • I add last_name to the function definition in person.py

    1def factory(first_name, last_name):
    2    return None
    

    the test passes


  • I want the function to take in a keyword argument called sex. I add it to the test in test_person.py

     7    def test_factory_takes_keyword_arguments(self):
     8        self.assertEqual(
     9            src.person.factory(
    10                first_name='first_name',
    11                last_name='last_name',
    12                sex='M',
    13            ),
    14            None
    15        )
    

    the terminal shows TypeError

    TypeError: factory() got an unexpected keyword argument 'sex'
    

    the test calls the factory function with 3 inputs, but the definition in person.py only takes 2 inputs

  • I add sex as an input parameter to the factory function in person.py

    1def factory(
    2        first_name, last_name,
    3        sex,
    4    ):
    5    return None
    

    the test passes


  • I want the function to take in a keyword argument for year_of_birth and give it the result of calling another function. I add it to the test in test_person.py

     7    def test_factory_takes_keyword_arguments(self):
     8        self.assertEqual(
     9            src.person.factory(
    10                first_name='first_name',
    11                last_name='last_name',
    12                sex='M',
    13                year_of_birth=this_year(),
    14            ),
    15            None
    16        )
    

    the terminal shows NameError

    NameError: name 'this_year' is not defined
    

    there is nothing with that name in this file

  • I add a definition for the this_year function above the class definition in test_person.py

    1import src.person
    2import unittest
    3
    4
    5def this_year():
    6    return None
    7
    8
    9class TestPerson(unittest.TestCase):
    

    the terminal shows TypeError

    TypeError: factory() got an unexpected keyword argument 'year_of_birth'
    

    the test calls the factory function with 4 inputs, but the definition in person.py only takes 3 inputs

  • I add the name to the function definition in person.py

    1def factory(
    2        first_name, last_name,
    3        sex, year_of_birth,
    4    ):
    5    return None
    

    the test passes


  • I want the factory function to return a dictionary as output, I change the expectation of the assertion in test_person.py

    11    def test_factory_takes_keyword_arguments(self):
    12        self.assertEqual(
    13            src.person.factory(
    14                first_name='first_name',
    15                last_name='last_name',
    16                sex='M',
    17                year_of_birth=this_year(),
    18            ),
    19            dict()
    20        )
    

    the terminal shows AssertionError

    AssertionError: None != {}
    
  • I change None to a dictionary in the return statement in person.py

    1def factory(
    2        first_name, last_name,
    3        sex, year_of_birth,
    4    ):
    5    return {}
    

    the test passes because {} and dict() are two ways to make the empty dictionary


  • I want the expected dictionary in the test to have a key called first_name with the same value as what is given when the factory function is called. I add the key in test_person.py

    11    def test_factory_takes_keyword_arguments(self):
    12        self.assertEqual(
    13            src.person.factory(
    14                first_name='first_name',
    15                last_name='last_name',
    16                sex='M',
    17                year_of_birth=this_year(),
    18            ),
    19            dict(
    20                first_name='first_name',
    21            )
    22        )
    

    the terminal shows AssertionError

    AssertionError: {} != {'first_name': 'first_name'}
    
  • I change the return statement in person.py

    1def factory(
    2        first_name, last_name,
    3        sex, year_of_birth,
    4    ):
    5    return {'first_name': 'first_name'}
    

    the test passes

  • I typed 'first_name' two times in the test, which means I have to make a change in 2 places when I want a different value. I add a variable to remove the repetition in test_person.py

    11    def test_factory_takes_keyword_arguments(self):
    12        first_name = 'first_name'
    13
    14        self.assertEqual(
    
  • I use the variable as the value for first_name in the call to src.person.factory in the assertion

    14        self.assertEqual(
    15            src.person.factory(
    16                # first_name='first_name',
    17                first_name=first_name,
    18                last_name='last_name',
    19                sex='M',
    20                year_of_birth=this_year(),
    21            ),
    

    the test is still green

  • I use the variable as the value for the first_name key in the expected dictionary

    22            dict(
    23                # first_name='first_name',
    24                first_name=first_name,
    25            )
    

    still green

  • I remove the commented lines

    11    def test_factory_takes_keyword_arguments(self):
    12        first_name = 'first_name'
    13
    14        self.assertEqual(
    15            src.person.factory(
    16                first_name=first_name,
    17                last_name='last_name',
    18                sex='M',
    19                year_of_birth=this_year(),
    20            ),
    21            dict(
    22                first_name=first_name,
    23            )
    24        )
    25
    26
    27# Exceptions seen
    

    I now only need to change the value of first_name in one place

  • I change 'first_name' to 'jane'

    11    def test_factory_takes_keyword_arguments(self):
    12        first_name = 'jane'
    

    the terminal shows AssertionError

    AssertionError: {'first_name': 'first_name'} != {'first_name': 'jane'}
    
  • I change the return statement in person.py

    1def factory(
    2        first_name, last_name,
    3        sex, year_of_birth,
    4    ):
    5    return {'first_name': 'jane'}
    

    and the test is green again


  • I want the expected dictionary to have a key called last_name with the same value as what is given in the call to the factory function. I add it to the expectation in test_person.py

    14        self.assertEqual(
    15            src.person.factory(
    16                first_name=first_name,
    17                last_name='last_name',
    18                sex='M',
    19                year_of_birth=this_year()
    20            ),
    21            dict(
    22                first_name=first_name,
    23                last_name='last_name',
    24            )
    25        )
    

    the terminal shows AssertionError

    E       - {'first_name': 'jane'}
    E       + {'first_name': 'jane', 'last_name': 'last_name'}
    
  • I change the return statement in person.py

    1def factory(
    2        first_name, last_name,
    3        sex, year_of_birth,
    4    ):
    5    return {
    6        'first_name': 'jane',
    7        'last_name': 'last_name',
    8    }
    

    the test passes

  • 'last_name' happens two times in the test, I add a variable to remove the repetition like I did with 'first_name' in test_person.py

    11    def test_factory_takes_keyword_arguments(self):
    12        first_name = 'jane'
    13        last_name = 'last_name'
    14
    15        self.assertEqual(
    
  • I use the new variable in the call to src.person.factory in the assertion

    15        self.assertEqual(
    16            src.person.factory(
    17                first_name=first_name,
    18                # last_name='last_name',
    19                last_name=last_name,
    20                sex='M',
    21                year_of_birth=this_year(),
    22            ),
    

    the test is still green

  • I use the variable in the expected dictionary

    23            dict(
    24                first_name=first_name,
    25                # last_name='last_name',
    26                last_name=last_name,
    27            )
    

    still green

  • I remove the commented lines

    11    def test_factory_takes_keyword_arguments(self):
    12        first_name = 'jane'
    13        last_name = 'last_name'
    14
    15        self.assertEqual(
    16            src.person.factory(
    17                first_name=first_name,
    18                last_name=last_name,
    19                sex='M',
    20                year_of_birth=this_year(),
    21            ),
    22            dict(
    23                first_name=first_name,
    24                last_name=last_name,
    25            )
    26        )
    27
    28
    29# Exceptions seen
    

    the test is still green

  • I change the value from 'last_name' to 'doe'

    11    def test_factory_takes_keyword_arguments(self):
    12        first_name = 'jane'
    13        last_name = 'doe'
    

    the terminal shows AssertionError

    E       - {'first_name': 'jane', 'last_name': 'last_name'}
    E       ?                                      ^^^^^^^^
    E
    E       + {'first_name': 'jane', 'last_name': 'doe'}
    E       ?                                      ^^
    

    the values for the last_name key are different in the 2 dictionaries

  • I change the return statement in person.py

    1def factory(
    2        first_name, last_name,
    3        sex, year_of_birth,
    4    ):
    5    return {
    6        'first_name': 'jane',
    7        'last_name': 'doe',
    8    }
    

    the test passes


  • I add a key called sex to the dictionary with the same value as what is given in the call to the factory function in test_person.py

    15        self.assertEqual(
    16            src.person.factory(
    17                first_name=first_name,
    18                last_name=last_name,
    19                sex='M',
    20                year_of_birth=this_year(),
    21            ),
    22            dict(
    23                first_name=first_name,
    24                last_name=last_name,
    25                sex='M',
    26            )
    27        )
    

    the terminal shows AssertionError

    E       - {'first_name': 'jane', 'last_name': 'doe'}
    E       + {'first_name': 'jane', 'last_name': 'doe', 'sex': 'M'}
    E       ?                                          ++++++++++++
    
  • I add a new key to the return statement in person.py

    1def factory(
    2        first_name, last_name,
    3        sex, year_of_birth,
    4    ):
    5    return {
    6        'first_name': 'jane',
    7        'last_name': 'doe',
    8        'sex': 'M',
    9    }
    

    the test passes

  • I add a variable to remove the repetition of the value for sex in test_person.py

    11    def test_factory_takes_keyword_arguments(self):
    12        first_name = 'jane'
    13        last_name = 'doe'
    14        sex = 'M'
    15
    16        self.assertEqual(
    
  • I use the variable in the call to src.person.factory in the assertion

    16        self.assertEqual(
    17            src.person.factory(
    18                first_name=first_name,
    19                last_name=last_name,
    20                # sex='M',
    21                sex=sex,
    22                year_of_birth=this_year(),
    23            ),
    

    the test is still green

  • I use the variable in the expected dictionary

    24            dict(
    25                first_name=first_name,
    26                last_name=last_name,
    27                # sex='M',
    28                sex=sex,
    29            )
    

    still green

  • I remove the commented lines

    11    def test_factory_takes_keyword_arguments(self):
    12        first_name = 'jane'
    13        last_name = 'doe'
    14        sex = 'M'
    15
    16        self.assertEqual(
    17            src.person.factory(
    18                first_name=first_name,
    19                last_name=last_name,
    20                sex=sex,
    21                year_of_birth=this_year(),
    22            ),
    23            dict(
    24                first_name=first_name,
    25                last_name=last_name,
    26                sex=sex,
    27            )
    28        )
    29
    30
    31# Exceptions seen
    
  • I change the value of the sex variable

    11    def test_factory_takes_keyword_arguments(self):
    12        first_name = 'jane'
    13        last_name = 'doe'
    14        sex = 'F'
    

    the terminal shows AssertionError

    E       - {'first_name': 'jane', 'last_name': 'doe', 'sex': 'M'}
    E       ?                                                    ^
    E
    E       + {'first_name': 'jane', 'last_name': 'doe', 'sex': 'F'}
    E       ?                                                    ^
    
  • I change the return statement in person.py

    1def factory(
    2        first_name, last_name,
    3        sex, year_of_birth,
    4    ):
    5    return {
    6        'first_name': 'jane',
    7        'last_name': 'doe',
    8        'sex': 'F',
    9    }
    

    and the test is green again


  • I want the factory function to return the age of the person it makes. I add a key to the expectation in test_person.py

    16        self.assertEqual(
    17            src.person.factory(
    18                first_name=first_name,
    19                last_name=last_name,
    20                sex=sex,
    21                year_of_birth=this_year(),
    22            ),
    23            dict(
    24                first_name=first_name,
    25                last_name=last_name,
    26                sex=sex,
    27                age=this_year()-this_year(),
    28            )
    29        )
    

    the terminal shows TypeError

    TypeError: unsupported operand type(s) for -: 'NoneType' and 'NoneType'
    

    I cannot do arithmetic with None and I want the value for this year

  • I add an import statement for the datetime module at the top of test_person.py

    1import datetime
    2import src.person
    3import unittest
    4
    5
    6def this_year():
    7    return None
    

    datetime is a module from the Python standard library that is used for dates and times

  • I change the return statement in the this_year function

    6def this_year():
    7    return datetime.datetime.now().year
    

    Tip

    I can also use the today method to get the same value

    6def this_year():
    7    return datetime.datetime.today().year
    

    The terminal shows AssertionError

    E       - {'first_name': 'jane', 'last_name': 'doe', 'sex': 'F'}
    E       + {'age': 0, 'first_name': 'jane', 'last_name': 'doe', 'sex': 'F'}
    E       ?  ++++++++++
    

    the new dictionary has a value for the 'age' key.

    Here is what datetime.datetime.now().year or datetime.datetime.today().year means

    that was a lot of words, they become clearer in the chapters on classes and AttributeError.

  • I add a key for age to the return statement in person.py

     4def factory(
     5        first_name, last_name,
     6        sex, year_of_birth,
     7    ):
     8    return {
     9        'first_name': 'jane',
    10        'last_name': 'doe',
    11        'sex': 'F',
    12        'age': 0,
    13    }
    

    the test passes

  • I add a variable for year_of_birth in test_person.py

    12    def test_factory_takes_keyword_arguments(self):
    13        first_name = 'jane'
    14        last_name = 'doe'
    15        sex = 'F'
    16        year_of_birth = this_year()
    17
    18        self.assertEqual(
    
  • I use the variable in the call to src.person.factory in the assertion

    18        self.assertEqual(
    19            src.person.factory(
    20                first_name=first_name,
    21                last_name=last_name,
    22                sex=sex,
    23                # year_of_birth=this_year(),
    24                year_of_birth=year_of_birth,
    25            ),
    

    the test is still green

  • I use the variable in the expected dictionary

    26            dict(
    27                first_name=first_name,
    28                last_name=last_name,
    29                sex=sex,
    30                # age=this_year()-this_year(),
    31                age=this_year()-year_of_birth,
    32            )
    

    still green

  • I remove the commented lines

    12    def test_factory_takes_keyword_arguments(self):
    13        first_name = 'jane'
    14        last_name = 'doe'
    15        sex = 'F'
    16        year_of_birth = this_year()
    17
    18        self.assertEqual(
    19            src.person.factory(
    20                first_name=first_name,
    21                last_name=last_name,
    22                sex=sex,
    23                year_of_birth=year_of_birth,
    24            ),
    25            dict(
    26                first_name=first_name,
    27                last_name=last_name,
    28                sex=sex,
    29                age=this_year()-year_of_birth,
    30            )
    31        )
    32
    33
    34# Exceptions seen
    

REFACTOR: make it better


  • the only difference between the call to the factory function and the expected dictionary in the assertion is that one has a year of birth and the other does a calculation with the year of birth. The other things are the same. I add a dictionary to remove the repetition

    12    def test_factory_takes_keyword_arguments(self):
    13        first_name = 'jane'
    14        last_name = 'doe'
    15        sex = 'F'
    16        year_of_birth = this_year()
    17        a_person = dict(
    18            first_name=first_name,
    19            last_name=last_name,
    20            sex=sex,
    21        )
    22
    23        self.assertEqual(
    
  • I use the new variable with a starred expression in the call to src.function.factory like I did in test_functions_w_unknown_arguments

    23        self.assertEqual(
    24            src.person.factory(
    25                # first_name=first_name,
    26                # last_name=last_name,
    27                # sex=sex,
    28                **a_person,
    29                year_of_birth=year_of_birth,
    30            ),
    

    the test is still green

  • I do the same thing in the expectation

    31            dict(
    32                # first_name=first_name,
    33                # last_name=last_name,
    34                # sex=sex,
    35                **a_person,
    36                age=this_year()-year_of_birth,
    37            )
    

    still green

  • I remove the commented lines

    23        self.assertEqual(
    24            src.person.factory(
    25                **a_person,
    26                year_of_birth=year_of_birth,
    27            ),
    28            dict(
    29                **a_person,
    30                age=this_year()-year_of_birth,
    31            )
    32        )
    

    green

  • I use the values of first_name, last_name and the sex variables in the dictionary

    12    def test_factory_takes_keyword_arguments(self):
    13        first_name = 'jane'
    14        last_name = 'doe'
    15        sex = 'F'
    16        year_of_birth = this_year()
    17        a_person = dict(
    18            # first_name=first_name,
    19            # last_name=last_name,
    20            # sex=sex,
    21            first_name='jane',
    22            last_name='doe',
    23            sex='F',
    24        )
    

    still green

  • I remove the commented lines and the first_name, last_name and sex variables since they are no longer used

    12    def test_factory_takes_keyword_arguments(self):
    13        year_of_birth = this_year()
    14        a_person = dict(
    15            first_name='jane',
    16            last_name='doe',
    17            sex='F',
    18        )
    19
    20        self.assertEqual(
    21            src.person.factory(
    22                **a_person,
    23                year_of_birth=year_of_birth,
    24            ),
    25            dict(
    26                **a_person,
    27                age=this_year()-year_of_birth,
    28            )
    29        )
    30
    31
    32# Exceptions seen
    

    green


test factory with random values

I want to use random values in the test. I add an import statement at the top of test_person.py

1import datetime
2import random
3import src.person
4import unittest

random is a module from the Python standard library that is used to make fake random numbers


RED: make it fail


  • I use a random integer for the year_of_birth variable

    13    def test_factory_takes_keyword_arguments(self):
    14        # year_of_birth = this_year()
    15        year_of_birth = random.randint(
    16            this_year()-120, this_year()
    17        )
    18        a_person = dict(
    

    Here is what the new line means

    • random is the random module

    • .randint is a call to the randint method from the random module. Okay, this one does not use the same name again

    • this_year()-120 returns this year minus 120

    • this_year() returns datetime.datetime.now().year which is the value for the current year

    • random.randint(this_year()-120, this_year()) gives me a random number from 120 years ago, up to and also the current year which is returned by the call to this_year()

  • I use ctrl+s (Windows/Linux) or command+s (MacOS) to save the file a few times to run the tests. When the age is not 0, the terminal shows AssertionError

    E       - {'age': 0, 'first_name': 'jane', 'last_name': 'doe', 'sex': 'F'}
    E       ?         ^
    E
    E       + {'age': X, 'first_name': 'jane', 'last_name': 'doe', 'sex': 'F'}
    E       ?         ^
    

    Note

    X is for the random age


GREEN: make it pass


  • I add the age calculation from test_person.py to the return statement in person.py

     1def factory(
     2        first_name, last_name,
     3        sex, year_of_birth,
     4    ):
     5    return {
     6        'first_name': 'jane',
     7        'last_name': 'doe',
     8        'sex': 'F',
     9        'age': this_year() - year_of_birth,
    10    }
    

    the terminal shows NameError

    NameError: name 'this_year' is not defined
    

    because I used a name that is not defined in person.py

  • I use the return statement of the this_year() function from test_person.py to change this_year() in person.py

     8    return {
     9        'first_name': 'jane',
    10        'last_name': 'doe',
    11        'sex': 'F,
    12        'age': datetime.datetime.now().year - year_of_birth,
    13    }
    

    the terminal shows NameError

    NameError: name 'datetime' is not defined. Did you forget to import 'datetime'
    
  • I add an import statement for the datetime module at the top of person.py

    1import datetime
    2
    3
    4def factory(
    

    the test passes


REFACTOR: make it better


  • I remove the commented # year_of_birth = this_year() line from test_person.py

  • I add randomness to the sex key in test_person.py

    13    def test_factory_takes_keyword_arguments(self):
    14        year_of_birth = random.randint(
    15            this_year()-120, this_year()
    16        )
    17        a_person = dict(
    18            first_name='jane',
    19            last_name='doe',
    20            # sex='F',
    21            sex=random.choice(('F', 'M')),
    22        )
    23
    24        self.assertEqual(
    
  • I use ctrl+s (Windows/Linux) or command+s (MacOS) to run the test a few times and it passes when sex is randomly 'F'.

    When sex is randomly 'M', the terminal shows AssertionError

    E       - {'age': X, 'first_name': 'jane', 'last_name': 'doe', 'sex': 'F'}
    E       ?                                                              ^
    E
    E       + {'age': X, 'first_name': 'jane', 'last_name': 'doe', 'sex': 'M'}
    E       ?                                                              ^
    
  • I add the sex input parameter instead of a value that does not change to the return statement in person.py

     8    return {
     9        'first_name': 'jane',
    10        'last_name': 'doe',
    11        'sex': sex,
    12        'age': datetime.datetime.now().year - year_of_birth,
    13    }
    

    the test passes with no more random failures

  • I remove # sex = 'F' from test_person.py


  • I use random.choice with the last_name key

    17        a_person = dict(
    18            first_name='jane',
    19            # last_name='doe',
    20            last_name=random.choice((
    21                'doe', 'smith', 'blow', 'public',
    22            )),
    23            sex=random.choice(('F', 'M')),
    24        )
    
  • I use ctrl+s (Windows/Linux) or command+s (MacOS) to run the test a few times and it passes when last_name is 'doe'.

    When last_name is not doe, the terminal shows AssertionError

    E       - {'age': X, 'first_name': 'jane', 'last_name': 'doe', 'sex': A}
    E       ?                                                ^^^
    E
    E       + {'age': X, 'first_name': 'jane', 'last_name': Z, 'sex': A}
    E       ?                                               ^
    

    Note

    Z is for the random last name and A is for the random sex value

  • I use the last_name input parameter as the value for the 'last_name' key in the return statement in person.py

     8    return {
     9        'first_name': 'jane',
    10        'last_name': last_name,
    11        'sex': sex,
    12        'age': datetime.datetime.today().year - year_of_birth,
    13    }
    

    and the test is green again


  • I remove # last_name = 'doe' then add randomness to the first_name key in test_person.py

    17        a_person = dict(
    18            # first_name='jane',
    19            first_name=random.choice((
    20                'jane', 'joe', 'john', 'person',
    21            )),
    22            last_name=random.choice((
    23                'doe', 'smith', 'blow', 'public',
    24            )),
    25            sex=random.choice(('F', 'M')),
    26        )
    

    I use ctrl+s (Windows/Linux) or command+s (MacOS) to run the test a few times and it passes when first_name is 'jane'.

    When first_name is not 'jane' the terminal shows AssertionError

    E       - {'age': X, 'first_name': 'jane', 'last_name': Z, 'sex': A}
    E       ?                          ^^^^^^
    E
    E       + {'age': X, 'first_name': Y, 'last_name': Z, 'sex': A}
    E       ?                          ^
    

    Note

    Y is for the random first name

  • I add the first_name input parameter to the return statement in person.py

     4def factory(
     5        first_name, last_name,
     6        sex, year_of_birth,
     7    ):
     8    return {
     9        'first_name': first_name,
    10        'last_name': last_name,
    11        'sex': sex,
    12        'age': datetime.datetime.today().year - year_of_birth,
    13    }
    

    the test passes

  • I remove the commented line # first_name = 'jane' from test_person.py

  • I add a function for the calls to the random.choice method with a starred expression like in test_functions_w_unknown_arguments

     4import unittest
     5
     6
     7def choose(*choices):
     8    return random.choice(choices)
     9
    10
    11def this_year():
    
  • I use the new function in the test

    21        a_person = dict(
    22            # first_name=random.choice((
    23            #     'jane', 'joe', 'john', 'person',
    24            # )),
    25            # last_name=random.choice((
    26            #     'doe', 'smith', 'blow', 'public',
    27            # )),
    28            # sex=random.choice(('F', 'M')),
    29            first_name=choose('jane', 'joe', 'john', 'person'),
    30            last_name=choose('doe', 'smith', 'blow', 'public'),
    31            sex=choose('F', 'M'),
    32        )
    33
    34        self.assertEqual(
    

    the test is still green

  • I remove the commented lines

    17    def test_factory_takes_keyword_arguments(self):
    18        year_of_birth = random.randint(
    19            this_year()-120, this_year()
    20        )
    21        a_person = dict(
    22            first_name=choose('jane', 'joe', 'john', 'person'),
    23            last_name=choose('doe', 'smith', 'blow', 'public'),
    24            sex=choose('F', 'M'),
    25        )
    26
    27        self.assertEqual(
    28            src.person.factory(
    29                **a_person,
    30                year_of_birth=year_of_birth,
    31            ),
    32            dict(
    33                **a_person,
    34                age=this_year()-year_of_birth,
    35            )
    36        )
    37
    38
    39# Exceptions seen
    

    still green


test_factory_w_default_arguments

I want to see what happens when I try to make a person without a value for the last_name argument


RED: make it fail


  • I copy test_factory_takes_keyword_arguments and paste it below in test_person.py

  • I change the name of the new test to test_factory_w_default_arguments, then comment out the last_name key-value pair in the a_person dictionary

    27        self.assertEqual(
    28            src.person.factory(
    29                **a_person,
    30                year_of_birth=year_of_birth,
    31            ),
    32            dict(
    33                **a_person,
    34                age=this_year()-year_of_birth,
    35            )
    36        )
    37
    38    def test_factory_w_default_arguments(self):
    39        year_of_birth = random.randint(
    40            this_year()-120, this_year()
    41        )
    42        a_person = dict(
    43            first_name=choose('jane', 'joe', 'john', 'person'),
    44            # last_name=choose('doe', 'smith', 'blow', 'public'),
    45            sex=choose('F', 'M'),
    46        )
    47
    48        self.assertEqual(
    49            src.person.factory(
    50                **a_person,
    51                year_of_birth=year_of_birth,
    52            ),
    53            dict(
    54                **a_person,
    55                age=this_year()-year_of_birth,
    56            )
    57        )
    58
    59
    60# Exceptions seen
    

    the terminal shows TypeError

    TypeError: factory() missing 1 required positional argument: 'last_name'
    

GREEN: make it pass


  • I add a default value for last_name in the factory function in person.py to make it a choice

    4def factory(
    5        first_name, last_name=None,
    6        sex, year_of_birth,
    7    ):
    

    the terminal shows SyntaxError

    SyntaxError: parameter without a default follows parameter with a default
    

    I cannot put a parameter that does NOT have a default value after a parameter that has a default value

  • I add SyntaxError to the list of Exceptions seen in test_person.py

    64# Exceptions seen
    65# AssertionError
    66# NameError
    67# AttributeError
    68# TypeError
    69# SyntaxError
    
  • I add a default value for sex in the factory function in person.py

    4def factory(
    5        first_name, last_name=None,
    6        sex=None, year_of_birth,
    7    ):
    

    the terminal shows SyntaxError

    SyntaxError: parameter without a default follows parameter with a default
    
  • I add a default value for year_of_birth

    4def factory(
    5        first_name, last_name=None,
    6        sex=None, year_of_birth=None,
    7    ):
    

    the terminal shows AssertionError

    E       - {'age': X, 'first_name': Y, 'last_name': None, 'sex': 'F'}
    E       ?                           -------------------
    E
    E       + {'age': X, 'first_name': Y, 'sex': 'F'
    

    Note

    X is for the random age, Y is for the random first name

    the factory function returns a dictionary with a key called 'last_name', the test does not expect a dictionary with a key called 'last_name'

  • I add a key-value pair for last_name in the expectation of test_factory_w_default_arguments in test_person.py

    57            dict(
    58                **a_person,
    59                last_name='doe',
    60                age=this_year()-year_of_birth,
    61            )
    

    the terminal shows AssertionError

    E       - {'age': X, 'first_name': Y, 'last_name': None, 'sex': A}
    E       ?                                          ^ -
    E
    E       + {'age': X, 'first_name': Y, 'last_name': 'doe', 'sex': A}
    E       ?                                          ^^  +
    

    the factory function returns a dictionary with a value of None for last_name and the test expects 'doe'

  • I change the default value for last_name in the factory function in person.py

    4def factory(
    5        first_name, last_name='doe',
    6        sex=None, year_of_birth=None,
    7    ):
    

    the test passes

    Note

    When the factory function is called with no value for the last_name argument, it uses 'doe' because that is the default value in the function definition, it is the same as calling it with last_name='doe'

    src.person.factory(
        first_name=first_name,
        sex=sex,
        year_of_birth=year_of_birth,
        last_name='doe',
    )
    

    see test_functions_w_default_arguments for more


  • I remove the commented line from test_factory_w_default_arguments in test_person.py

  • I comment out the sex key in test_factory_w_default_arguments to see what happens when I call the factory function without it

    38    def test_factory_w_default_arguments(self):
    39        year_of_birth = random.randint(
    40            this_year()-120, this_year()
    41        )
    42        a_person = dict(
    43            first_name=choose('jane', 'joe', 'john', 'person'),
    44            # sex=choose('F', 'M'),
    45        )
    

    the terminal shows AssertionError

    E       - {'age': X, 'first_name': Y, 'last_name': 'doe', 'sex': None}
    E       ?                                               -------------
    E
    E       + {'age': X, 'first_name': Y, 'last_name': 'doe'}
    

    the factory function returns a dictionary with a key called 'sex', the test does not expect a dictionary with a key called 'sex'

  • I add a key-value pair for sex in the expectation of test_factory_w_default_arguments in test_person.py

    52            dict(
    53                **a_person,
    54                last_name='doe',
    55                sex='M',
    56                age=this_year()-year_of_birth,
    57            )
    

    the terminal shows AssertionError

    E       - {'age': X, 'first_name': Y, 'last_name': Z, 'sex': None}
    E       ?                                                    ^^^^
    E
    E       + {'age': X, 'first_name': Y, 'last_name': Z, 'sex': 'M'}
    E       ?                                                    ^^^
    

    the factory function returns a dictionary with a value of None for sex and the test expects 'M'

  • I change the default value for sex in the factory function in person.py

    4def factory(
    5        first_name, last_name='doe',
    6        sex='M', year_of_birth=None,
    7    ):
    

    the test passes

    Note

    When the factory function is called with no value for the sex argument, it uses 'M' because that is the default value in the function definition, it is the same as calling it with sex='M'

    src.person.factory(
        first_name=first_name,
        year_of_birth=year_of_birth,
        last_name='doe',
        sex='M',
    )
    

    since the values are the same as the default values, I can call the function without them

    src.person.factory(
        first_name=first_name,
        year_of_birth=year_of_birth,
    )
    

    see test_functions_w_default_arguments for more


  • I remove the commented line # sex=choose('F', 'M'), from test_factory_w_default_arguments in test_person.py

  • I do not need the a_person dictionary in test_factory_takes_keyword_arguments because it has only one key. I can use a variable

    42        a_person = dict(
    43            first_name=choose('jane', 'joe', 'john', 'person'),
    44        )
    45        first_name = choose('jane', 'joe', 'john', 'person')
    46
    47        self.assertEqual(
    
  • I use the variable in the call to src.person.factory in the assertion

    47        self.assertEqual(
    48            src.person.factory(
    49                **a_person,
    50                first_name=first_name,
    51                year_of_birth=year_of_birth,
    52            ),
    

    the terminal shows TypeError

    TypeError: src.person.factory() got multiple values for keyword argument 'first_name'
    

    because the **a_person dictionary has a key called first_name, the call to src.person.factory gets called with the same name two times

  • I comment out a_person, in the call to src.person.factory

    47        self.assertEqual(
    48            src.person.factory(
    49                # **a_person,
    50                first_name=first_name,
    51                year_of_birth=year_of_birth,
    52            ),
    

    the terminal randomly shows AssertionError

    E       - {'age': X, 'first_name': Y, 'last_name': 'doe', 'sex': 'M'}
    E       ?                          ^
    E
    E       + {'age': X, 'first_name': B, 'last_name': 'doe', 'sex': 'M'}
    E       ?                          ^
    

    because the values for first_name randomly change in both dictionaries

  • I use the first_name variable in the expectation

    53            dict(
    54                **a_person,
    55                first_name=first_name,
    56                last_name='doe',
    57                sex='M',
    58                age=this_year()-year_of_birth,
    59            )
    

    the terminal shows TypeError

    TypeError: dict() got multiple values for keyword argument 'first_name'
    
  • I comment out **a_person, in the dictionary

    53              dict(
    54                  # **a_person,
    55                  first_name=first_name,
    56                  last_name='doe',
    57                  sex='M',
    58                  age=this_year()-year_of_birth,
    59              )
    

    the test passes

  • I remove the commented lines and the a_person dictionary

    38    def test_factory_w_default_arguments(self):
    39        year_of_birth = random.randint(
    40            this_year()-120, this_year()
    41        )
    42        first_name = choose('jane', 'joe', 'john', 'person')
    43
    44        self.assertEqual(
    45            src.person.factory(
    46                first_name=first_name,
    47                year_of_birth=year_of_birth,
    48            ),
    49            dict(
    50                first_name=first_name,
    51                last_name='doe',
    52                sex='M',
    53                age=this_year()-year_of_birth,
    54            )
    55        )
    56
    57
    58# Exceptions seen
    

REFACTOR: make it better


  • first_name and year_of_birth are made the same way in both tests. I add the setUp method to the TestPerson class with a class attribute (variable) to remove the repetition of the year_of_birth variable

    15class TestPerson(unittest.TestCase):
    16
    17    def setUp(self):
    18        self.random_year_of_birth = random.randint(
    19            this_year()-120, this_year()
    20        )
    21
    22    def test_factory_takes_keyword_arguments(self):
    

    I can use the class attribute directly

  • I point year_of_birth in test_factory_takes_keyword_arguments to the class attribute

    22    def test_factory_takes_keyword_arguments(self):
    23        # year_of_birth = random.randint(
    24        #     this_year()-120, this_year()
    25        # )
    26        year_of_birth = self.random_year_of_birth
    27        a_person = dict(
    

    the test is still green

  • I use the class attribute in the call to src.person.factory in the assertion

    33        self.assertEqual(
    34            src.person.factory(
    35                **a_person,
    36                # year_of_birth=year_of_birth,
    37                year_of_birth=self.random_year_of_birth,
    38            ),
    

    still green

  • I use the class attribute in the expectation

    39            dict(
    40                **a_person,
    41                # age=this_year()-year_of_birth,
    42                age=this_year()-self.random_year_of_birth,
    43            )
    

    green

  • I remove the commented lines and the year_of_birth variable

    22    def test_factory_takes_keyword_arguments(self):
    23        a_person = dict(
    24            first_name=choose('jane', 'joe', 'john', 'person'),
    25            last_name=choose('doe', 'smith', 'blow', 'public'),
    26            sex=choose('F', 'M'),
    27        )
    28
    29        self.assertEqual(
    30            src.person.factory(
    31                **a_person,
    32                year_of_birth=self.random_year_of_birth,
    33            ),
    34            dict(
    35                **a_person,
    36                age=this_year()-self.random_year_of_birth,
    37            )
    38        )
    39
    40    def test_factory_w_default_arguments(self):
    
  • I point the year_of_birth variable in test_factory_w_default_arguments to the class attribute

    40    def test_factory_w_default_arguments(self):
    41        # year_of_birth = random.randint(
    42        #     this_year()-120, this_year()
    43        # )
    44        year_of_birth = self.random_year_of_birth
    45        first_name = choose('jane', 'joe', 'john', 'person')
    

    the test is still green

  • I use the class attribute in the call to src.person.factory in the assertion

    47        self.assertEqual(
    48            src.person.factory(
    49                first_name=first_name,
    50                # year_of_birth=year_of_birth,
    51                year_of_birth=self.random_year_of_birth,
    52            ),
    

    still green

  • I use the class attribute in the expectation of the assertion

    53            dict(
    54                first_name=first_name,
    55                last_name='doe',
    56                sex='M',
    57                # age=this_year()-year_of_birth,
    58                age=this_year()-self.random_year_of_birth,
    59            )
    

    green

  • I remove the commented lines and the year_of_birth variable

    40    def test_factory_w_default_arguments(self):
    41        first_name = choose('jane', 'joe', 'john', 'person')
    42
    43        self.assertEqual(
    44            src.person.factory(
    45                first_name=first_name,
    46                year_of_birth=self.random_year_of_birth,
    47            ),
    48            dict(
    49                first_name=first_name,
    50                last_name='doe',
    51                sex='M',
    52                age=this_year()-self.random_year_of_birth,
    53            )
    54        )
    55
    56
    57# Exceptions seen
    

    the tests are still green


  • I add a class attribute (variable) for first_name to the setUp method to remove repetition of the variable

    17    def setUp(self):
    18        self.random_year_of_birth = random.randint(
    19            this_year()-120, this_year()
    20        )
    21        self.random_first_name = choose('jane', 'joe', 'john', 'person')
    22
    23    def test_factory_takes_keyword_arguments(self):
    

    I can use the class attribute directly

  • I use the class attribute as the value for the first_name key in the a_person dictionary in test_factory_takes_keyword_arguments

    23    def test_factory_takes_keyword_arguments(self):
    24        a_person = dict(
    25            # first_name=choose('jane', 'joe', 'john', 'person'),
    26            first_name=self.random_first_name,
    27            last_name=choose('doe', 'smith', 'blow', 'public'),
    28            sex=choose('F', 'M'),
    29        )
    

    the test is still green

  • I remove the commented line

    21    def test_factory_takes_keyword_arguments(self):
    22        a_person = dict(
    23            first_name=self.random_first_name,
    24            last_name=choose('doe', 'smith', 'blow', 'public'),
    25            sex=choose('F', 'M'),
    26        )
    27
    28        self.assertEqual(
    29            src.person.factory(
    30                **a_person,
    31                year_of_birth=self.random_year_of_birth,
    32            ),
    33            dict(
    34                **a_person,
    35                age=this_year()-self.random_year_of_birth,
    36            )
    37        )
    38
    39    def test_factory_w_default_arguments(self):
    

    still green

  • I point the first_name variable in test_factory_w_default_arguments to the class attribute

    41    def test_factory_w_default_arguments(self):
    42        # first_name = choose('jane', 'joe', 'john', 'person')
    43        first_name = self.random_first_name
    44
    45        self.assertEqual(
    

    green

  • I use the class attribute in the call to src.person.factory in the assertion

    45        self.assertEqual(
    46            src.person.factory(
    47                # first_name=first_name,
    48                first_name=self.random_first_name,
    49                year_of_birth=self.random_year_of_birth,
    50            ),
    

    still green

  • I use the class attribute in the expectation of the assertion

    53            dict(
    54                # first_name=first_name,
    55                first_name=self.random_first_name,
    56                last_name='doe',
    57                sex='M',
    58                age=this_year()-self.random_year_of_birth,
    59            )
    

    the test is still green

  • I remove the commented lines and the first_name variable

    41    def test_factory_w_default_arguments(self):
    42        self.assertEqual(
    43            src.person.factory(
    44                first_name=self.random_first_name,
    45                year_of_birth=self.random_year_of_birth,
    46            ),
    47            dict(
    48                first_name=self.random_first_name,
    49                last_name='doe',
    50                sex='M',
    51                age=this_year()-self.random_year_of_birth,
    52            )
    53        )
    54
    55
    56# Exceptions seen
    

    the tests are still green


test_person_tests

I want to write the solution without looking at the tests


RED: make it fail


  • I close test_person.py in the editor

  • then I delete all the text in person.py. The terminal shows AttributeError

    AttributeError: module 'src.person' has no attribute 'factory'
    

    there is nothing in person.py with the name factory


GREEN: make it pass


  • I add the name

    1factory
    

    the terminal shows NameError

    NameError: name 'factory' is not defined
    
  • I point it to None to define it

    1factory = None
    

    the terminal shows TypeError

    TypeError: 'NoneType' object is not callable
    

    factory points to None which is not callable like a function

  • I make factory a function

    1def factory():
    2    return None
    

    the terminal shows TypeError

    TypeError: factory() got an unexpected keyword argument 'first_name'
    

    the test called the function with a keyword argument

  • I add first_name to the function definition

    1def factory(first_name):
    2    return None
    

    the terminal shows TypeError

    TypeError: factory() got an unexpected keyword argument 'year_of_birth'
    

    the test called the function with another keyword argument

  • I add year_of_birth to the function definition

    1def factory(first_name, year_of_birth):
    2    return None
    

    the terminal shows AssertionError

    AssertionError: None != {'first_name': X, 'last_name': 'doe', 'sex': 'M', 'age': A}
    

    the tests expect a dictionary and the factory function returns None

  • I make the function return a dictionary instead of None

    1def factory(first_name, year_of_birth):
    2    return {
    3        'first_name': 'john',
    4        'last_name': 'doe',
    5        'sex': 'M',
    6        'age': 55,
    7    }
    

    the terminal shows AssertionError

    Attention

    Some of your values will be different because the test uses random values

    E       - {'age': 55, 'first_name': 'john', 'last_name': 'doe', 'sex': 'M'}
    E       ?         ^^                  ^^
    E
    E       + {'age': X, 'first_name': Y, 'last_name': 'doe', 'sex': 'M'}
    E       ?         ^                ^
    

    the values of the age and first_name keys change randomly

  • I use the first_name input parameter in the return statement

    1def factory(first_name, year_of_birth):
    2    return {
    3        'first_name': first_name,
    4        'last_name': 'doe',
    5        'sex': 'M',
    6        'age': 55,
    7    }
    

    the first name matches and when the ages are different, the terminal shows AssertionError

    E       - {'age': 55, 'first_name': Y, 'last_name': 'doe', 'sex': A}
    E       ?         ^^
    E
    E       + {'age': X, 'first_name': Y, 'last_name': 'doe', 'sex': A}
    E       ?         ^
    

    sometimes the terminal shows TypeError

    TypeError: factory() got an unexpected keyword argument 'last_name'. Did you mean 'first_name'?
    
  • I use the year_of_birth input parameter in the return statement for the value of age

    1def factory(first_name, year_of_birth):
    2    return {
    3        'first_name': first_name,
    4        'last_name': 'doe',
    5        'sex': 'M',
    6        'age': year_of_birth,
    7    }
    

    the terminal shows AssertionError

    E       - {'age': ABCD, 'first_name': 'john', 'last_name': 'doe', 'sex': 'M'}
    E       ?         ^^^^
    E
    E       + {'age': X, 'first_name': 'john', 'last_name': 'doe', 'sex': 'M'}
    E       ?         ^
    

    the value the factory function returned for the age key has 4 digits (a year), and the test expects the difference between that value and the current year

  • I add an import statement for the datetime module at the top of the file

    1import datetime
    2
    3
    4def factory(
    

    the terminal still shows AssertionError

  • I use the datetime module to get the current year for the age calculation

    4    return {
    5        'first_name': first_name,
    6        'last_name': 'doe',
    7        'sex': 'M',
    8        'age': datetime.datetime.today().year - year_of_birth,
    9    }
    

    the terminal shows TypeError

    TypeError: factory() got an unexpected keyword argument 'last_name'. Did you mean 'first_name'?
    

    the test called the function with another keyword argument

  • I add a new input parameter to the function

    4def factory(
    5        first_name, year_of_birth,
    6        last_name,
    7    ):
    8    return {
    

    the terminal shows TypeError

    TypeError: factory() missing 1 required positional argument: 'last_name'
    

    the test called the function with another argument and Python took it is a positional argument for last_name

  • I add a default value for last_name so Python does not take it is a positional argument when a name is not given

    4def factory(
    5        first_name, year_of_birth,
    6        last_name=None,
    7    ):
    8    return {
    

    the terminal shows TypeError

    TypeError: factory() got an unexpected keyword argument 'sex'
    

    another keyword argument

  • I add the name to the definition of the function

    4def factory(
    5        first_name, year_of_birth,
    6        last_name=None, sex,
    7    ):
    

    the terminal shows SyntaxError

    SyntaxError: parameter without a default follows parameter with a default
    

    I cannot put a parameter that does NOT have a default value after a parameter that has a default value

  • I add a default value for sex

    1def factory(
    2        first_name, year_of_birth,
    3        last_name=None, sex=None,
    4    ):
    

    the terminal shows AssertionError

    E       - {'age': X, 'first_name': Y, 'last_name': 'doe', 'sex': 'M'}
    E       ?                                           ^^^
    E
    E       + {'age': X, 'first_name': Y, 'last_name': Z, 'sex': A}
    E       ?                                          ^         ^
    

    the values for last_name and sex change every time the tests run

  • I use the sex input parameter in the return statement

     8    return {
     9        'first_name': first_name,
    10        'last_name': 'doe',
    11        'sex': sex,
    12        'age': datetime.datetime.today().year - year_of_birth,
    13    }
    

    the terminal shows AssertionError

    E       - {'age': X, 'first_name': Y, 'last_name': Z, 'sex': None}
    E       ?                                                    ^^^^
    E
    E       + {'age': X, 'first_name': Y, 'last_name': Z, 'sex': 'M'}
    E       ?                                                    ^^^
    

    the test expects 'M' as the value of sex and the function returns None which is its default value

  • I change the default value of sex to 'M'

    4def factory(
    5        first_name, year_of_birth,
    6        last_name=None, sex='M',
    7    ):
    

    the test passes when the last_name is randomly 'doe'.

    When the last_name is not 'doe', the terminal shows AssertionError

    E       - {'age': X, 'first_name': Y, 'last_name': 'doe', 'sex': A}
    E       ?                                          ^^^^^
    E
    E       + {'age': X, 'first_name': Y, 'last_name': Z, 'sex': A}
    E       ?                                          ^
    

    the last_name value is different between the two dictionaries

  • I use the last_name input parameter in the return statement

     8    return {
     9        'first_name': first_name,
    10        'last_name': last_name,
    11        'sex': sex,
    12        'age': datetime.datetime.today().year - year_of_birth,
    13    }
    

    the terminal shows AssertionError

    E       - {'age': X, 'first_name': Y, 'last_name': None, 'sex': A}
    E       ?                                          ^ -
    E
    E       + {'age': X, 'first_name': Y, 'last_name': 'doe', 'sex': A}
    E       ?                                          ^^  +
    

    the test expects 'doe' as the value of last_name and the function returns None which is its default value

  • I change the default value for last_name to match the expectation

     1import datetime
     2
     3
     4def factory(
     5        first_name, year_of_birth,
     6        last_name='doe', sex='M',
     7    ):
     8    return {
     9        'first_name': first_name,
    10        'last_name': last_name,
    11        'sex': sex,
    12        'age': datetime.datetime.today().year - year_of_birth,
    13    }
    

    the test passes with no more random failures. I am getting pretty good at this.


This solution only has 2 parameters with default values

def factory(
        first_name, year_of_birth,
        last_name='doe', sex='M',
    ):

which is a little bit different from the first solution where I had 3 parameters with default values

def factory(
        first_name, last_name='doe',
        sex='M', year_of_birth=None,
    ):

new things can be learned from repetition


close the project

  • I close person.py in the editor

  • I click in the terminal and use ctrl+c on the keyboard to leave the tests, the terminal shows

    .../pumping_python
    

    I am back in the pumping_python directory

Note

on Windows without Windows Subsystem for Linux


review

I ran tests to make a function that takes in keyword arguments as input, has default values for some of them, performs an action based on an input and returns a dictionary as output

I also saw the following Exceptions


code from the chapter

Do you want to see all the CODE I typed in this chapter?


what is next?

you know

Would you like to put it all together in classes?


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