1import unittest
2
3import solution
4
5
6class TestSanity(unittest.TestCase):
7 """Check if the CM is present."""
8
9 def test_protected_section(self):
10 self.assertIn('ProtectedSection', dir(solution), 'Убеди се, че класът "ProtectedSection" е наличен с точно това име.')
11 self.assertTrue(isinstance(solution.ProtectedSection, type), 'Убеди се, че "ProtectedSection" е клас.')
12
13
14if __name__ == '__main__':
15 unittest.main()
1import unittest
2
3import solution
4
5
6class TestSolution(unittest.TestCase):
7 """Test ProtectedSection."""
8
9 ERROR_TEXT = 'Ако ползваш AI генератори, ще влезеш в черния списък!'
10
11 @staticmethod
12 def assertEqualException(found, expected):
13 assert type(expected) is type(found), ('Wrong exception type. '
14 f'{type(expected)} expected, '
15 f'{type(found)} found.')
16 assert str(expected) == str(found), ('Wrong exception text. '
17 f'"{str(expected)}" expected, '
18 f'"{str(found)}" found.')
19
20 def test_solution(self):
21 """Test everything in a single test case. Only 100% gives a point."""
22
23 # Empty input with no exception
24 with solution.ProtectedSection() as cm:
25 pass
26 self.assertIsNone(cm.exception)
27
28 # Empty input with exception
29 with self.assertRaises(KeyError):
30 with solution.ProtectedSection() as cm:
31 raise KeyError(self.ERROR_TEXT)
32 self.assertIsNone(cm.exception)
33
34 # Only logged input with one parameter and no exception
35 with solution.ProtectedSection(log=(ValueError,)) as cm:
36 pass
37 self.assertIsNone(cm.exception)
38
39 # Only logged input with one parameter and exception
40 with solution.ProtectedSection(log=(Exception,)) as cm:
41 raise Exception(self.ERROR_TEXT)
42 self.assertEqualException(cm.exception, Exception(self.ERROR_TEXT))
43
44 # Only suppressed input with one parameter and no exception
45 with solution.ProtectedSection(suppress=(KeyError,)) as cm:
46 pass
47 self.assertIsNone(cm.exception)
48
49 # Only suppressed input with one parameter and exception
50 with solution.ProtectedSection(suppress=(Exception,)) as cm:
51 raise Exception(self.ERROR_TEXT)
52 self.assertIsNone(cm.exception)
53
54 # Only logged input with multiple parameters and no exception
55 with solution.ProtectedSection(log=(ValueError, IndexError)) as cm:
56 pass
57 self.assertIsNone(cm.exception)
58
59 # Only logged input with multiple parameters and exception
60 with solution.ProtectedSection(log=(TypeError, IndexError)) as cm:
61 raise IndexError(self.ERROR_TEXT)
62 self.assertEqualException(cm.exception, IndexError(self.ERROR_TEXT))
63
64 # Only suppressed input with multiple parameters and no exception
65 with solution.ProtectedSection(suppress=(ValueError, IndexError)) as cm:
66 pass
67 self.assertIsNone(cm.exception)
68
69 # Only suppressed input with multiple parameters and exception
70 with solution.ProtectedSection(suppress=(TypeError, IndexError)) as cm:
71 raise IndexError(self.ERROR_TEXT)
72 self.assertIsNone(cm.exception)
73
74 # Only logged input with multiple parameters and different exception
75 with self.assertRaises(ValueError):
76 with solution.ProtectedSection(log=(TypeError, IndexError)) as cm:
77 raise ValueError(self.ERROR_TEXT)
78 self.assertIsNone(cm.exception)
79
80 # Only supressed input with multiple parameters and different exception
81 with self.assertRaises(ZeroDivisionError):
82 with solution.ProtectedSection(suppress=(TypeError, IndexError)) as cm:
83 raise ZeroDivisionError(self.ERROR_TEXT)
84 self.assertIsNone(cm.exception)
85
86 # Mixed input with multiple parameters and no exception
87 with solution.ProtectedSection(log=(ZeroDivisionError, ValueError), suppress=(TypeError, IndexError)) as cm:
88 pass
89 self.assertIsNone(cm.exception)
90
91 # Mixed input with multiple parameters and exception from log
92 with solution.ProtectedSection(log=(ZeroDivisionError, ValueError), suppress=(TypeError, IndexError)) as cm:
93 raise ZeroDivisionError(self.ERROR_TEXT)
94 self.assertEqualException(cm.exception, ZeroDivisionError(self.ERROR_TEXT))
95
96 # Mixed input with multiple parameters and exception from suppress
97 with solution.ProtectedSection(log=(ZeroDivisionError, ValueError), suppress=(TypeError, IndexError)) as cm:
98 raise TypeError(self.ERROR_TEXT)
99 self.assertIsNone(cm.exception)
100
101 # Text log priority over suppress
102 with solution.ProtectedSection(log=(ImportError, ), suppress=(ImportError, )) as cm:
103 raise ImportError(self.ERROR_TEXT)
104 self.assertEqualException(cm.exception, ImportError(self.ERROR_TEXT))
105
106 # Test nested expressions with inner salenting
107 with solution.ProtectedSection(log=(MemoryError, ), suppress=(MemoryError, )) as cm1:
108 with solution.ProtectedSection(log=(MemoryError, ), suppress=(MemoryError, )) as cm2:
109 raise MemoryError(self.ERROR_TEXT)
110 self.assertIsNone(cm1.exception)
111 self.assertEqualException(cm2.exception, MemoryError(self.ERROR_TEXT))
112
113 # Test nested expressions with outer salenting
114 with solution.ProtectedSection(log=(MemoryError, ), suppress=(MemoryError, )) as cm1:
115 with solution.ProtectedSection(log=(IndexError, ), suppress=(IndexError, )) as cm2:
116 raise MemoryError(self.ERROR_TEXT)
117 self.assertEqualException(cm1.exception, MemoryError(self.ERROR_TEXT))
118 self.assertIsNone(cm2.exception)
119
120 def test_special_cases(self):
121 """Test special cases to show you that you missed something."""
122 # Ensure an isntance can be reused
123 protected_section = solution.ProtectedSection(log=(ZeroDivisionError, IndexError))
124 with protected_section as cm:
125 x = 1 / 0
126 with protected_section as cm:
127 x = 1
128 self.assertIsNone(cm.exception)
129
130 # Ensure the exceptions' types match exactly, not by inheritance
131 with solution.ProtectedSection(log=(Exception, ), suppress=(ZeroDivisionError, )) as cm:
132 raise ZeroDivisionError(self.ERROR_TEXT)
133 self.assertIsNone(cm.exception)
134
135if __name__ == '__main__':
136 unittest.main()
Виктор Бечев
09.11.2024 18:42Вярно, не гледам внимателно.
Трябва да отпечата `None`. Но понеже не сме го уточнили и дискусията се развива доста късно - вероятно няма да ви вземем точката ако само това ви липсва.
|
Илиан Запрянов
09.11.2024 17:54@Виктор_Бечев, идеята ми е, че TypeError в случая е в suppress, тоест нямаме err.exception. Тогава при отпечатване на err.exception трябва да отпечата None или тази в предишния with
|
Георги Кунчев
09.11.2024 17:34@Йоан_Байчев, при текущата дефиниция, тъй като инстанцията може да пази само един атрибут `exception`, очаквано е вторият ти блок да презапише изключението и резултатът да е "Text 2".
Да, това е леко неочаквано поведение, но причината е, че дефиницята, която сме направили, не очаква такова използване. В реалния случай би дефинирал две отделни инстанции за отделните блокове.
Ако пък искаме да пазим информация дори с една инстанция, би трябвало да променим изискванията за класа си, защото сега това е случай, който те не могат да поддържат адекватно.
По принцип бих дал звезда на подобен въпрос, защото е граничен случай, който дефиницята ни не поддържа, но тъй като вече получи звезда в собственото си решение, ще оставя това "неозвездено". Ще ти кажа, обаче, "Браво" за въпроса. Наистина граничен случай.
TLDR - Няма да тестваме с този случай, защото е неочаквано използване на класа ни.
ПП: Позволих си да редактирам въпроса ти, за да се визуализира като код. Можеш да използваш бектикове, за да дефинираш блок от код в коментарите си. Още глезотии [тук](https://py-fmi.org/info/showdown)
|
Йоан Байчев
09.11.2024 17:26```
protected_section = ProtectedSection(log=(ValueError, ))
with protected_section as cm1:
raise ValueError('Text 1')
print(cm1.exception)
with protected_section as cm2:
raise ValueError('Text 2')
print(cm2.exception)
print(cm1.exception)
```
Какво се очаква да бъде поведението в такъв случай?
|
Виктор Бечев
09.11.2024 14:38Желателно е да работи правилно за всеки индивидуален контекст.
С други думи, в долният пример се очаква да има `TypeError` втория път.
|
Илиан Запрянов
09.11.2024 14:10Какво трябва да е поведението при преизползване на инстанция?
https://pastebin.com/HCRqcELb
|
|
Илиан Запрянов
08.11.2024 15:31```python
with ProtectedSection(suppress=(Exception,)) as err:
x = 1 / 0
print(err.exception)
# Тук трябва ли да се потисне грешката, тъй като ZeroDivisionError е подклас на Exception
# или трябва да са точните грешки, т.е. да се потисне само при:
with ProtectedSection(suppress=(ZeroDivisionError,)) as err:
x = 1 / 0
print(err.exception)
```
|
|
Никола Георгиев
07.11.2024 22:11Какво става ако възбудената грешка не принадлежи на нито единия тюпъл...
Пример
```
with ProtectedSection(log=(), suppress=()) as err:
x = 1/0
print(err.exception)
```
Вярно ли е че това трябва да се отпечата?
```
Traceback (most recent call last):
File "...", line ..., in ...
x = 1/0
ZeroDivisionError: division by zero
```
|