File size: 12,163 Bytes
b216c95
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
"""
Unit tests for common.exceptions module

Tests all custom exception classes and their attributes.
"""

import pytest
from common import (
    MedicalTranscriberException,
    AudioFileException,
    TranscriptionException,
    CorrectionException,
    ReportGenerationException,
    ConfigurationException,
    APIException,
    ValidationException,
    KnowledgeBaseException
)


class TestMedicalTranscriberException:
    """Test cases for base MedicalTranscriberException"""
    
    def test_is_exception(self):
        """Should be an Exception subclass"""
        exc = MedicalTranscriberException("Test error")
        assert isinstance(exc, Exception)
    
    def test_with_message(self):
        """Should accept message"""
        msg = "Test error message"
        exc = MedicalTranscriberException(msg)
        assert str(exc) == msg
    
    def test_inheritance(self):
        """All specific exceptions should inherit from base"""
        exceptions = [
            AudioFileException("path", "message"),
            TranscriptionException("message"),
            CorrectionException("message"),
            ReportGenerationException("message"),
            ConfigurationException("message"),
            APIException("endpoint", 404, "message"),
            ValidationException("field", "value", "message"),
            KnowledgeBaseException("message")
        ]
        
        for exc in exceptions:
            assert isinstance(exc, MedicalTranscriberException)


class TestAudioFileException:
    """Test cases for AudioFileException"""
    
    def test_with_default_message(self):
        """Should use default message if not provided"""
        exc = AudioFileException("/path/to/file.wav")
        assert "/path/to/file.wav" in str(exc)
        assert "Invalid audio file" in str(exc)
    
    def test_with_custom_message(self):
        """Should use custom message if provided"""
        exc = AudioFileException("/path/to/file.wav", "File is corrupted")
        assert "File is corrupted" in str(exc)
        assert "/path/to/file.wav" in str(exc)
    
    def test_file_path_attribute(self):
        """Should have file_path attribute"""
        file_path = "/path/to/file.wav"
        exc = AudioFileException(file_path, "Test")
        assert exc.file_path == file_path
    
    def test_message_attribute(self):
        """Should have message attribute"""
        exc = AudioFileException("/path/to/file.wav", "Test message")
        assert "Test message" in exc.message


class TestTranscriptionException:
    """Test cases for TranscriptionException"""
    
    def test_basic_usage(self):
        """Should work with simple message"""
        exc = TranscriptionException("Transcription failed")
        assert "Transcription failed" in str(exc)
    
    def test_inheritance_chain(self):
        """Should be MedicalTranscriberException"""
        exc = TranscriptionException("Test")
        assert isinstance(exc, MedicalTranscriberException)


class TestCorrectionException:
    """Test cases for CorrectionException"""
    
    def test_basic_usage(self):
        """Should work with simple message"""
        exc = CorrectionException("LLM correction failed")
        assert "LLM correction failed" in str(exc)
    
    def test_inheritance_chain(self):
        """Should be MedicalTranscriberException"""
        exc = CorrectionException("Test")
        assert isinstance(exc, MedicalTranscriberException)


class TestReportGenerationException:
    """Test cases for ReportGenerationException"""
    
    def test_basic_usage(self):
        """Should work with simple message"""
        exc = ReportGenerationException("Report generation failed")
        assert "Report generation failed" in str(exc)
    
    def test_inheritance_chain(self):
        """Should be MedicalTranscriberException"""
        exc = ReportGenerationException("Test")
        assert isinstance(exc, MedicalTranscriberException)


class TestConfigurationException:
    """Test cases for ConfigurationException"""
    
    def test_basic_usage(self):
        """Should work with simple message"""
        exc = ConfigurationException("Invalid configuration")
        assert "Invalid configuration" in str(exc)
    
    def test_inheritance_chain(self):
        """Should be MedicalTranscriberException"""
        exc = ConfigurationException("Test")
        assert isinstance(exc, MedicalTranscriberException)


class TestAPIException:
    """Test cases for APIException with status codes"""
    
    def test_with_status_code_and_message(self):
        """Should capture endpoint, status code, and message"""
        exc = APIException("https://api.example.com/v1/chat", 429, "Rate limit exceeded")
        
        assert exc.endpoint == "https://api.example.com/v1/chat"
        assert exc.status_code == 429
        assert "429" in str(exc)
        assert "Rate limit" in str(exc)
    
    def test_error_400(self):
        """Should handle 400 Bad Request"""
        exc = APIException("api/endpoint", 400, "Bad request format")
        assert exc.status_code == 400
        assert "400" in str(exc)
    
    def test_error_401(self):
        """Should handle 401 Unauthorized"""
        exc = APIException("api/endpoint", 401, "Invalid API key")
        assert exc.status_code == 401
        assert "401" in str(exc)
        assert "Invalid API key" in str(exc)
    
    def test_error_429(self):
        """Should handle 429 Rate Limit"""
        exc = APIException("api/endpoint", 429, "Rate limit exceeded")
        assert exc.status_code == 429
        assert "429" in str(exc)
    
    def test_error_500(self):
        """Should handle 500 Internal Server Error"""
        exc = APIException("api/endpoint", 500, "Server error")
        assert exc.status_code == 500
        assert "500" in str(exc)
    
    def test_message_attribute(self):
        """Should have message attribute with full context"""
        exc = APIException("api/endpoint", 404, "Not found")
        assert "404" in exc.message
        assert "api/endpoint" in exc.message
    
    def test_inheritance_chain(self):
        """Should be MedicalTranscriberException"""
        exc = APIException("api", 500, "error")
        assert isinstance(exc, MedicalTranscriberException)


class TestValidationException:
    """Test cases for ValidationException with field context"""
    
    def test_with_field_name(self):
        """Should capture field name"""
        exc = ValidationException("email", "invalid@", "Invalid email format")
        
        assert exc.field == "email"
        assert exc.value == "invalid@"
        assert "email" in str(exc)
    
    def test_default_reason(self):
        """Should use default reason if not provided"""
        exc = ValidationException("username", "ab", "")
        assert "Invalid value" in str(exc)
    
    def test_custom_reason(self):
        """Should use custom reason"""
        exc = ValidationException("age", "-5", "Age must be positive")
        assert "Age must be positive" in str(exc)
    
    def test_audio_file_field(self):
        """Should work with audio_file field"""
        exc = ValidationException("audio_file", "test.xyz", "Unsupported format")
        assert "audio_file" in str(exc)
        assert "test.xyz" in str(exc)
    
    def test_api_key_field(self):
        """Should work with api_key field"""
        exc = ValidationException("api_key", "***", "API key is too short")
        assert "api_key" in str(exc)
    
    def test_inheritance_chain(self):
        """Should be MedicalTranscriberException"""
        exc = ValidationException("field", "value", "reason")
        assert isinstance(exc, MedicalTranscriberException)


class TestKnowledgeBaseException:
    """Test cases for KnowledgeBaseException"""
    
    def test_basic_usage(self):
        """Should work with simple message"""
        exc = KnowledgeBaseException("Knowledge base not found")
        assert "Knowledge base not found" in str(exc)
    
    def test_inheritance_chain(self):
        """Should be MedicalTranscriberException"""
        exc = KnowledgeBaseException("Test")
        assert isinstance(exc, MedicalTranscriberException)


class TestExceptionHandling:
    """Integration tests for exception handling"""
    
    def test_catch_api_exception_by_status_code(self):
        """Should be able to catch and handle by status code"""
        exc = APIException("api/chat", 429, "Rate limit")
        
        try:
            raise exc
        except APIException as e:
            if e.status_code == 429:
                assert True
            else:
                assert False
    
    def test_catch_specific_exceptions(self):
        """Should be able to catch specific exception types"""
        exceptions_to_test = [
            (AudioFileException("/path", "test"), AudioFileException),
            (TranscriptionException("test"), TranscriptionException),
            (CorrectionException("test"), CorrectionException),
            (APIException("api", 500, "error"), APIException),
            (ValidationException("field", "value", "reason"), ValidationException),
        ]
        
        for exc, exc_type in exceptions_to_test:
            try:
                raise exc
            except exc_type:
                assert True
            except Exception:
                assert False
    
    def test_catch_all_as_medical_transcriber_exception(self):
        """Should be able to catch all as base exception"""
        exceptions = [
            AudioFileException("/path", "test"),
            TranscriptionException("test"),
            CorrectionException("test"),
            APIException("api", 500, "error"),
            ValidationException("field", "value", "reason"),
            KnowledgeBaseException("test"),
        ]
        
        for exc in exceptions:
            try:
                raise exc
            except MedicalTranscriberException:
                assert True
            except Exception:
                assert False
    
    def test_exception_chain_preservation(self):
        """Should preserve exception chain"""
        try:
            try:
                raise ValueError("Original error")
            except ValueError as e:
                raise AudioFileException("/path", str(e)) from e
        except AudioFileException as e:
            assert str(e.file_path) == "/path"
    
    def test_multiple_exception_handlers(self):
        """Should work with multiple exception handlers"""
        def test_api_error():
            raise APIException("api", 429, "Rate limited")
        
        def test_validation_error():
            raise ValidationException("field", "value", "Invalid")
        
        try:
            test_api_error()
        except APIException as e:
            assert e.status_code == 429
        except Exception:
            assert False
        
        try:
            test_validation_error()
        except ValidationException as e:
            assert e.field == "field"
        except Exception:
            assert False


class TestExceptionStringRepresentation:
    """Test string representations of exceptions"""
    
    def test_audio_file_exception_string(self):
        """Should have informative string representation"""
        exc = AudioFileException("/path/to/audio.wav", "Corrupted file")
        exc_str = str(exc)
        
        assert "Corrupted file" in exc_str
        assert "/path/to/audio.wav" in exc_str
    
    def test_api_exception_string(self):
        """Should have informative string representation"""
        exc = APIException("api/v1/chat", 401, "Unauthorized")
        exc_str = str(exc)
        
        assert "401" in exc_str
        assert "api/v1/chat" in exc_str
        assert "Unauthorized" in exc_str
    
    def test_validation_exception_string(self):
        """Should have informative string representation"""
        exc = ValidationException("username", "admin", "Username reserved")
        exc_str = str(exc)
        
        assert "username" in exc_str
        assert "admin" in exc_str
        assert "Username reserved" in exc_str