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