classes: tests and solutions

classes tests

the code in person/tests/test_person.py from classes

  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
 15def random_year_of_birth():
 16    return random.randint(
 17        this_year()-120, this_year()
 18    )
 19
 20
 21def get_age(year_of_birth):
 22    return this_year() - year_of_birth
 23
 24
 25class TestPerson(unittest.TestCase):
 26
 27    RANDOM_NAMES = (
 28        'jane', 'joe', 'john', 'person',
 29        'doe', 'smith', 'blow', 'public',
 30    )
 31
 32    def setUp(self):
 33        self.random_year_of_birth = random_year_of_birth()
 34        self.random_new_year_of_birth = random_year_of_birth()
 35        self.original_age = get_age(self.random_year_of_birth)
 36        self.new_age = get_age(self.random_new_year_of_birth)
 37        self.random_first_name = choose(*self.RANDOM_NAMES)
 38        self.random_last_name = choose(*self.RANDOM_NAMES)
 39        self.random_sex = choose('M', 'F')
 40        self.random_factory_person = src.person.factory(
 41            first_name=self.random_first_name,
 42            last_name=self.random_last_name,
 43            sex=self.random_sex,
 44            year_of_birth=self.random_year_of_birth,
 45        )
 46        self.random_classy_person = src.person.Person(
 47            first_name=self.random_first_name,
 48            last_name=self.random_last_name,
 49            sex=self.random_sex,
 50            year_of_birth=self.random_year_of_birth,
 51        )
 52
 53    def test_factory_takes_keyword_arguments(self):
 54        self.assertEqual(
 55            src.person.factory(
 56                first_name=self.random_first_name,
 57                last_name=self.random_last_name,
 58                sex=self.random_sex,
 59                year_of_birth=self.random_year_of_birth,
 60            ),
 61            self.random_factory_person
 62        )
 63
 64    def test_factory_w_default_arguments(self):
 65        self.assertEqual(
 66            src.person.factory(
 67                first_name=self.random_first_name,
 68                year_of_birth=self.random_year_of_birth,
 69            ),
 70            dict(
 71                first_name=self.random_first_name,
 72                last_name='doe',
 73                sex='M',
 74                age=self.original_age,
 75            )
 76        )
 77
 78    def expected_greeting(self):
 79        return (
 80            f'Hi, my name is {self.random_first_name} '
 81            f'{self.random_last_name} '
 82            f'and I am {self.original_age}'
 83        )
 84
 85    def test_factory_person_greeting(self):
 86        self.assertEqual(
 87            src.person.hello(self.random_factory_person),
 88            self.expected_greeting()
 89        )
 90
 91    def test_classy_person_greeting(self):
 92        self.assertEqual(
 93            self.random_classy_person.hello(),
 94            self.expected_greeting()
 95        )
 96
 97    def test_update_factory_person_year_of_birth(self):
 98        self.assertEqual(
 99            self.random_factory_person.get('age'),
100            self.original_age
101        )
102
103        with self.assertRaises(KeyError):
104            self.random_factory_person['year_of_birth']
105        self.assertEqual(
106            self.random_factory_person.setdefault(
107                'year_of_birth', self.random_new_year_of_birth
108            ),
109            self.random_new_year_of_birth
110        )
111        self.assertEqual(
112            self.random_factory_person.get('age'),
113            self.original_age
114        )
115
116        self.assertEqual(
117            src.person.update_year_of_birth(
118                self.random_factory_person,
119                self.random_new_year_of_birth
120            ),
121            dict(
122                first_name=self.random_first_name,
123                last_name=self.random_last_name,
124                sex=self.random_sex,
125                age=self.new_age
126            )
127        )
128
129    def test_update_classy_person_year_of_birth(self):
130        self.assertEqual(
131            self.random_classy_person.get_age(),
132            self.original_age
133        )
134
135        self.random_classy_person.year_of_birth = self.random_new_year_of_birth
136        self.assertEqual(
137            self.random_classy_person.get_age(),
138            self.new_age
139        )
140
141
142# Exceptions seen
143# AssertionError
144# NameError
145# AttributeError
146# TypeError
147# SyntaxError

classes solutions

the solutions in person/src/person.py from classes

 1import datetime
 2
 3
 4def this_year():
 5    return datetime.datetime.today().year
 6
 7
 8def factory(
 9        first_name, year_of_birth,
10        last_name='doe', sex='M',
11    ):
12    return {
13        'first_name': first_name,
14        'last_name': last_name,
15        'sex': sex,
16        'age': this_year() - year_of_birth,
17    }
18
19
20def hello(person):
21    return (
22        f'Hi, my name is {person.get("first_name")} '
23        f'{person.get("last_name")} '
24        f'and I am {person.get("age")}'
25    )
26
27
28def update_year_of_birth(person, new_year_of_birth):
29    return factory(
30        first_name=person.get('first_name'),
31        last_name=person.get('last_name'),
32        sex=person.get('sex'),
33        year_of_birth=new_year_of_birth
34    )
35
36
37class Person:
38
39    def __init__(
40            self, first_name, last_name=None,
41            year_of_birth=None, sex=None,
42        ):
43        self.first_name = first_name
44        self.last_name = last_name
45        self.year_of_birth = year_of_birth
46        return None
47
48    def hello(self):
49        return (
50            f'Hi, my name is {self.first_name} '
51            f'{self.last_name} and I am {self.get_age()}'
52        )
53
54    def get_age(self):
55        return this_year() - self.year_of_birth

inheritance tests

the code in person/tests/test_classes.py from inheritance

 1import unittest
 2import src.classes
 3import src.person
 4
 5
 6class TestClasses(unittest.TestCase):
 7
 8    def test_making_a_class_w_pass(self):
 9        self.assertIsInstance(src.classes.WPass(), object)
10
11    def test_making_a_class_w_parentheses(self):
12        self.assertIsInstance(src.classes.WParentheses(), object)
13
14    def test_making_a_class_w_object(self):
15        self.assertIsInstance(src.classes.WObject(), object)
16
17    def test_attributes_and_methods_of_objects(self):
18        self.assertEqual(
19            dir(object),
20            [
21                '__class__',
22                '__delattr__',
23                '__dir__',
24                '__doc__',
25                '__eq__',
26                '__format__',
27                '__ge__',
28                '__getattribute__',
29                '__getstate__',
30                '__gt__',
31                '__hash__',
32                '__init__',
33                '__init_subclass__',
34                '__le__',
35                '__lt__',
36                '__ne__',
37                '__new__',
38                '__reduce__',
39                '__reduce_ex__',
40                '__repr__',
41                '__setattr__',
42                '__sizeof__',
43                '__str__',
44                '__subclasshook__'
45            ]
46        )
47
48    def test_making_classes_w_inheritance(self):
49        self.assertIsInstance(
50            src.classes.Doe('doe'),
51            src.person.Person
52        )
53        self.assertEqual(
54            dir(src.classes.Doe),
55            dir(src.person.Person)
56        )
57
58    def test_family_ties(self):
59        doe = src.classes.Doe('doe')
60        jane = src.classes.Doe('jane')
61        john = src.classes.Doe('john')
62        mary = src.classes.Smith('mary')
63        joe = src.classes.Blow('joe')
64        baby = src.classes.Baby('baby')
65        lil = src.classes.Lil('lil')
66
67        self.assertEqual(doe.last_name, 'doe')
68        self.assertEqual(jane.last_name, 'doe')
69        self.assertEqual(john.last_name, 'doe')
70        self.assertEqual(mary.last_name, 'smith')
71        self.assertEqual(joe.last_name, 'blow')
72        self.assertEqual(baby.last_name, 'blow')
73        self.assertEqual(lil.last_name, 'doe')
74
75
76# Exceptions seen
77# AssertionError

inheritance solutions

the solutions in person/src/classes.py from inheritance

 1import src.person
 2
 3
 4class WPass:
 5
 6    pass
 7
 8
 9class WParentheses():
10
11    pass
12
13
14class WObject(object):
15
16    pass
17
18
19class Doe(src.person.Person):
20
21    def __init__(self, first_name, last_name='doe'):
22        super().__init__(first_name, last_name)
23
24
25class Smith(src.person.Person):
26
27    def __init__(self, first_name, last_name='smith'):
28        super().__init__(first_name, last_name)
29
30
31class Blow(src.person.Person):
32
33    def __init__(self, first_name, last_name='blow'):
34        super().__init__(first_name, last_name)
35
36
37class Baby(Blow, Doe): pass
38
39
40class Lil(Doe, Smith): pass

booleans 3: tests

the code in booleans/tests/test_booleans.py from booleans 3

 1import unittest
 2
 3
 4class TestBooleans(unittest.TestCase):
 5
 6    def test_what_is_false(self):
 7        self.assertIsInstance(False, (bool, int))
 8        self.assertNotIsInstance(False, float)
 9        for false_item in (
10            False,
11            None,
12            0, 0.0,
13            str(),
14            tuple(),
15            list(),
16            set(),
17            dict(),
18        ):
19            with self.subTest(i=false_item):
20                self.assertFalse(false_item)
21
22    def test_what_is_true(self):
23        self.assertIsInstance(True, (bool, int))
24        self.assertNotIsInstance(True, float)
25        for true_item in (
26            True,
27            -1, 1,
28            -0.1, 0.1,
29            'text',
30            (1, 2, 3, 'n'),
31            [1, 2, 3, 'n'],
32            {1, 2, 3, 'n'},
33            {'key': 'value'},
34        ):
35            with self.subTest(i=true_item):
36                self.assertTrue(true_item)
37
38    def test_the_value_of_false(self):
39        self.assertEqual(False+1, 1)
40        self.assertEqual(False-1, -1)
41        self.assertEqual(False*1, 0)
42        with self.assertRaises(ZeroDivisionError):
43            1 / False
44
45    def test_the_value_of_true(self):
46        self.assertEqual(True+1, 2)
47        self.assertEqual(True-1, 0)
48        self.assertEqual(True*1, 1)
49        self.assertEqual(True/1, 1)
50
51    def test_if_bool_is_an_int(self):
52        self.assertNotIsInstance(bool, int)
53
54
55# NOTES
56# a dictionary with things is true
57# a set with things is true
58# a list with things is true
59# a tuple with things is true
60# a string with things is true
61# positive and negative numbers are true
62# True is true
63# True is not false
64# True is a boolean
65# True is an integer
66# True is not a float
67# True is 1
68# the empty dictionary is false
69# the empty set is false
70# the empty list is false
71# the empty tuple is false
72# the empty string is false
73# 0 is false
74# None is false
75# False is false
76# False is not true
77# False is a boolean
78# False is an integer
79# False is not a float
80# False is 0
81
82
83# Exceptions seen
84# AssertionError

how to make a calculator 8: tests

the code in calculator/tests/test_calculator.py from how to make a calculator 8

  1import random
  2import src.calculator
  3import unittest
  4
  5
  6def a_random_number():
  7    return random.triangular(-1000.0, 1000.0)
  8
  9
 10class TestCalculator(unittest.TestCase):
 11
 12    def setUp(self):
 13        self.history = {}
 14        self.random_first_number = a_random_number()
 15        self.random_second_number = a_random_number()
 16        try:
 17            self.division_result = (
 18                self.random_first_number / self.random_second_number
 19            )
 20        except ZeroDivisionError:
 21            self.division_result = 'brmph?! cannot divide by 0. Try again...'
 22
 23        self.calculator_tests = {
 24            'add': (
 25                self.random_first_number+self.random_second_number
 26            ),
 27            'subtract': (
 28                self.random_first_number-self.random_second_number
 29            ),
 30            'divide': self.division_result,
 31            'multiply': (
 32                self.random_first_number*self.random_second_number
 33            ),
 34        }
 35
 36    def test_calculator_functions(self):
 37        for operation in self.calculator_tests:
 38            with self.subTest(operation=operation):
 39                self.assertEqual(
 40                    src.calculator.__getattribute__(operation)(
 41                        self.random_first_number,
 42                        self.random_second_number
 43                    ),
 44                    self.calculator_tests[operation]
 45                )
 46
 47    def test_calculator_sends_message_when_input_is_not_a_number(self):
 48        for data in (
 49            None,
 50            True, False,
 51            str(), 'text',
 52            tuple(), (0, 1, 2, 'n'),
 53            list(), [0, 1, 2, 'n'],
 54            set(), {0, 1, 2, 'n'},
 55            dict(), {'key': 'value'},
 56        ):
 57            with self.subTest(i=data):
 58                for operation in self.calculator_tests:
 59                    self.assertEqual(
 60                        src.calculator.__getattribute__(operation)(
 61                            data, a_random_number()
 62                        ),
 63                        'brmph?! Numbers only. Try again...'
 64                    )
 65
 66    def test_calculator_w_list_items(self):
 67        # two_numbers = [self.random_first_number, self.random_second_number]
 68        a_dictionary = {
 69            'x': self.random_first_number,
 70            'y': self.random_second_number
 71        }
 72        two_numbers = list(a_dictionary.values())
 73
 74        self.assertEqual(
 75            src.calculator.add(two_numbers[0], two_numbers[1]),
 76            self.random_first_number+self.random_second_number
 77        )
 78        self.assertEqual(
 79            src.calculator.divide(two_numbers[-2], two_numbers[-1]),
 80            self.division_result
 81        )
 82        self.assertEqual(
 83            src.calculator.multiply(two_numbers[1], two_numbers[-1]),
 84            self.random_second_number*self.random_second_number
 85        )
 86        self.assertEqual(
 87            src.calculator.subtract(two_numbers[-2], two_numbers[0]),
 88            self.random_first_number-self.random_first_number
 89        )
 90
 91        for operation in self.calculator_tests:
 92            with self.subTest(operation=operation):
 93                self.assertEqual(
 94                    src.calculator.__getattribute__(operation)(
 95                        *two_numbers
 96                    ),
 97                    self.calculator_tests[operation]
 98                )
 99
100    def test_calculator_w_dictionary_items(self):
101        two_numbers = {
102            'first_input': self.random_first_number,
103            'second_input': self.random_second_number,
104        }
105
106        self.assertEqual(
107            src.calculator.add(
108                two_numbers['first_input'],
109                two_numbers['second_input']
110            ),
111            self.random_first_number+self.random_second_number
112        )
113        self.assertEqual(
114            src.calculator.divide(
115                two_numbers['first_input'],
116                two_numbers['second_input']
117            ),
118            self.division_result
119        )
120        self.assertEqual(
121            src.calculator.multiply(
122                two_numbers['second_input'],
123                two_numbers['second_input']
124            ),
125            self.random_second_number*self.random_second_number
126        )
127        self.assertEqual(
128            src.calculator.subtract(
129                two_numbers['first_input'],
130                two_numbers['first_input']
131            ),
132            self.random_first_number-self.random_first_number
133        )
134
135        for operation in self.calculator_tests:
136            with self.subTest(operation=operation):
137                self.assertEqual(
138                    src.calculator.__getattribute__(operation)(
139                        **two_numbers
140                    ),
141                    self.calculator_tests[operation]
142                )
143
144    def test_calculator_raises_type_error_when_given_more_than_two_inputs(self):
145        for operation in self.calculator_tests:
146            with (
147                self.subTest(operation=operation),
148                self.assertRaises(TypeError),
149            ):
150                src.calculator.__getattribute__(operation)(
151                    *[0, 1, 2]
152                )
153
154
155# Exceptions seen
156# AssertionError
157# NameError
158# AttributeError
159# TypeError
160# ZeroDivisionError
161# SyntaxError

how to make a calculator 8: solutions

the solutions in calculator/src/calculator.py from how to make a calculator 8

 1def check_input(function):
 2    def wrapper(first_input, second_input):
 3        if (
 4            isinstance(
 5                first_input,
 6                (dict, set, list, tuple, str, bool)
 7            ) or
 8            first_input is None
 9        ):
10            return 'brmph?! Numbers only. Try again...'
11        return function(first_input, second_input)
12    return wrapper
13
14
15@check_input
16def add(first_input, second_input):
17    return first_input + second_input
18
19
20@check_input
21def divide(first_input, second_input):
22    return first_input / second_input
23
24
25@check_input
26def multiply(first_input=None, second_input=None):
27    return first_input * second_input
28
29
30@check_input
31def subtract(first_input, second_input):
32    return first_input - second_input