classes: tests and solutions

classes tests

the code from 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 from 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 4: tests

the code from booleans/tests/test_booleans.py from booleans 4: inheritance

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

how to make a calculator 8: tests

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

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