Bonosa2 commited on
Commit
79adcde
·
verified ·
1 Parent(s): b281659

Create test_real_functionality.py

Browse files
Files changed (1) hide show
  1. tests/test_real_functionality.py +323 -0
tests/test_real_functionality.py ADDED
@@ -0,0 +1,323 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # tests/test_real_functionality.py
2
+ import pytest
3
+ import sys
4
+ import os
5
+ from PIL import Image
6
+ import numpy as np
7
+
8
+ # Add parent directory to import app
9
+ sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
10
+
11
+ # Import actual functions from app.py
12
+ try:
13
+ from app import (
14
+ preprocess_image_for_ocr,
15
+ clean_extracted_text,
16
+ gradio_generate_soap
17
+ )
18
+ APP_AVAILABLE = True
19
+ except ImportError:
20
+ APP_AVAILABLE = False
21
+
22
+ @pytest.mark.skipif(not APP_AVAILABLE, reason="app.py not available")
23
+ class TestRealFunctionality:
24
+ """Test actual app functions (not mocks)"""
25
+
26
+ def test_clean_extracted_text_real(self):
27
+ """Test the actual clean_extracted_text function"""
28
+ dirty_text = " Line 1 \n\n Line 2 with | pipes \n \n Line_3 "
29
+ clean_text = clean_extracted_text(dirty_text)
30
+
31
+ assert "Line 1" in clean_text
32
+ assert "Line 2 with pipes" in clean_text
33
+ assert "Line 3" in clean_text
34
+ assert "|" not in clean_text
35
+
36
+ def test_preprocess_image_for_ocr_real(self):
37
+ """Test actual image preprocessing"""
38
+ # Create test image
39
+ test_image = Image.new('RGB', (400, 300), color='white')
40
+
41
+ # Test the real function
42
+ result = preprocess_image_for_ocr(test_image)
43
+
44
+ assert isinstance(result, np.ndarray)
45
+ assert len(result.shape) == 2 # Should be grayscale
46
+ assert result.shape[0] >= 300 # Height should be at least 300
47
+ assert result.shape[1] >= 300 # Width should be at least 300
48
+
49
+ def test_gradio_generate_soap_empty_input_real(self):
50
+ """Test actual Gradio function with empty input"""
51
+ result = gradio_generate_soap("", None)
52
+ assert "❌" in result or "Please enter" in result
53
+
54
+ def test_gradio_generate_soap_text_input_real(self):
55
+ """Test actual Gradio function with text input"""
56
+ medical_text = """
57
+ Patient: John Smith, 45-year-old male
58
+ Chief Complaint: Chest pain for 2 hours
59
+ History: Sharp chest pain, 7/10 intensity
60
+ Physical Exam: VS: BP 150/90, HR 110
61
+ Assessment: Chest pain evaluation needed
62
+ Plan: EKG, cardiac enzymes
63
+ """
64
+
65
+ # This will fail if generate_soap_note function isn't loaded
66
+ # but that's good - it tells us the real state of the app
67
+ result = gradio_generate_soap(medical_text, None)
68
+
69
+ # Check if it's an error message or actual SOAP content
70
+ if "❌" not in result:
71
+ # Should contain SOAP sections if successful
72
+ assert any(section in result.upper() for section in
73
+ ["SUBJECTIVE", "OBJECTIVE", "ASSESSMENT", "PLAN"])
74
+
75
+ # tests/test_integration_real.py
76
+ import pytest
77
+ import sys
78
+ import os
79
+ from PIL import Image, ImageDraw, ImageFont
80
+
81
+ sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
82
+
83
+ class TestRealIntegration:
84
+ """Test real integration without mocks"""
85
+
86
+ def test_image_with_text_creation(self):
87
+ """Test creating an image with text for OCR testing"""
88
+ # Create a real image with text
89
+ img = Image.new('RGB', (800, 600), color='white')
90
+ draw = ImageDraw.Draw(img)
91
+
92
+ # Add medical text to image
93
+ medical_text = [
94
+ "Patient: John Doe",
95
+ "Age: 45 years old",
96
+ "Chief Complaint: Chest pain",
97
+ "Vital Signs: BP 140/90",
98
+ "Assessment: Further evaluation needed"
99
+ ]
100
+
101
+ y_position = 50
102
+ for line in medical_text:
103
+ draw.text((50, y_position), line, fill='black')
104
+ y_position += 40
105
+
106
+ # Verify image was created
107
+ assert img.size == (800, 600)
108
+ assert img.mode == 'RGB'
109
+
110
+ # Convert to array to verify content
111
+ img_array = np.array(img)
112
+
113
+ # Should not be all white (has text)
114
+ assert not np.all(img_array == 255)
115
+
116
+ def test_examples_dictionary_structure(self):
117
+ """Test that examples dictionary has proper structure"""
118
+ # Test the actual examples from the app
119
+ try:
120
+ from app import examples
121
+
122
+ # Check required keys exist
123
+ required_keys = ['chest_pain', 'diabetes', 'pediatric']
124
+ for key in required_keys:
125
+ assert key in examples
126
+
127
+ # Check content quality
128
+ for key, content in examples.items():
129
+ assert len(content) > 100 # Substantial content
130
+ assert "Patient:" in content
131
+ assert any(word in content.lower() for word in
132
+ ["complaint", "history", "exam", "assessment", "plan"])
133
+
134
+ except ImportError:
135
+ pytest.skip("examples not available in app.py")
136
+
137
+ def test_file_extensions_validation(self):
138
+ """Test file extension validation logic"""
139
+ allowed_extensions = ['.png', '.jpg', '.jpeg', '.txt', '.doc', '.docx', '.pdf']
140
+
141
+ # Test valid extensions
142
+ valid_files = ['image.png', 'document.pdf', 'notes.txt', 'scan.jpg']
143
+ for filename in valid_files:
144
+ file_ext = os.path.splitext(filename.lower())[1]
145
+ assert file_ext in allowed_extensions
146
+
147
+ # Test invalid extensions
148
+ invalid_files = ['file.xyz', 'document.zip', 'image.bmp']
149
+ for filename in invalid_files:
150
+ file_ext = os.path.splitext(filename.lower())[1]
151
+ assert file_ext not in allowed_extensions
152
+
153
+ # tests/test_error_scenarios_real.py
154
+ import pytest
155
+ import sys
156
+ import os
157
+
158
+ sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
159
+
160
+ class TestRealErrorScenarios:
161
+ """Test real error handling scenarios"""
162
+
163
+ def test_missing_dependencies_handling(self):
164
+ """Test what happens when dependencies are missing"""
165
+ # Test if app handles missing dependencies gracefully
166
+ try:
167
+ import easyocr
168
+ EASYOCR_AVAILABLE = True
169
+ except ImportError:
170
+ EASYOCR_AVAILABLE = False
171
+
172
+ try:
173
+ import pytesseract
174
+ TESSERACT_AVAILABLE = True
175
+ except ImportError:
176
+ TESSERACT_AVAILABLE = False
177
+
178
+ # At least one OCR method should be available for the app to work
179
+ if not EASYOCR_AVAILABLE and not TESSERACT_AVAILABLE:
180
+ pytest.skip("No OCR dependencies available")
181
+
182
+ def test_torch_availability(self):
183
+ """Test PyTorch availability and device detection"""
184
+ import torch
185
+
186
+ # Test device detection logic
187
+ device = "cuda" if torch.cuda.is_available() else "cpu"
188
+ assert device in ["cuda", "cpu"]
189
+
190
+ # Test tensor creation on detected device
191
+ test_tensor = torch.tensor([1, 2, 3], dtype=torch.float32)
192
+ assert test_tensor is not None
193
+
194
+ def test_image_format_handling(self):
195
+ """Test handling of different image formats"""
196
+ from PIL import Image
197
+
198
+ # Test RGB image
199
+ rgb_img = Image.new('RGB', (100, 100), color='white')
200
+ assert rgb_img.mode == 'RGB'
201
+
202
+ # Test grayscale image
203
+ gray_img = Image.new('L', (100, 100), color=128)
204
+ assert gray_img.mode == 'L'
205
+
206
+ # Test RGBA image
207
+ rgba_img = Image.new('RGBA', (100, 100), color=(255, 255, 255, 255))
208
+ assert rgba_img.mode == 'RGBA'
209
+
210
+ # tests/test_performance_real.py
211
+ import pytest
212
+ import time
213
+ import sys
214
+ import os
215
+ from PIL import Image
216
+
217
+ sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
218
+
219
+ class TestRealPerformance:
220
+ """Test actual performance characteristics"""
221
+
222
+ def test_image_preprocessing_speed(self):
223
+ """Test image preprocessing performance"""
224
+ try:
225
+ from app import preprocess_image_for_ocr
226
+
227
+ # Create test image
228
+ test_image = Image.new('RGB', (1000, 800), color='white')
229
+
230
+ # Time the preprocessing
231
+ start_time = time.time()
232
+ result = preprocess_image_for_ocr(test_image)
233
+ end_time = time.time()
234
+
235
+ processing_time = end_time - start_time
236
+
237
+ # Should process reasonably quickly (under 5 seconds)
238
+ assert processing_time < 5.0
239
+ assert result is not None
240
+
241
+ except ImportError:
242
+ pytest.skip("preprocess_image_for_ocr not available")
243
+
244
+ def test_text_cleaning_speed(self):
245
+ """Test text cleaning performance"""
246
+ try:
247
+ from app import clean_extracted_text
248
+
249
+ # Create large text with lots of cleaning needed
250
+ dirty_text = " \n ".join([f"Line {i} with | pipes and _ underscores "
251
+ for i in range(1000)])
252
+
253
+ start_time = time.time()
254
+ clean_text = clean_extracted_text(dirty_text)
255
+ end_time = time.time()
256
+
257
+ processing_time = end_time - start_time
258
+
259
+ # Should clean text quickly (under 1 second)
260
+ assert processing_time < 1.0
261
+ assert len(clean_text) > 0
262
+ assert "|" not in clean_text
263
+
264
+ except ImportError:
265
+ pytest.skip("clean_extracted_text not available")
266
+
267
+ # tests/test_configuration_real.py
268
+ import pytest
269
+ import sys
270
+ import os
271
+
272
+ sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
273
+
274
+ class TestRealConfiguration:
275
+ """Test actual app configuration"""
276
+
277
+ def test_environment_variables(self):
278
+ """Test environment variable handling"""
279
+ # Test HF_TOKEN detection
280
+ hf_token = os.environ.get('HF_TOKEN') or os.environ.get('HUGGINGFACE_TOKEN')
281
+
282
+ # If no token, app should handle gracefully
283
+ if not hf_token:
284
+ # This is fine for testing - app should handle missing tokens
285
+ pass
286
+ else:
287
+ # If token exists, it should be a string
288
+ assert isinstance(hf_token, str)
289
+ assert len(hf_token) > 10 # Tokens should be substantial
290
+
291
+ def test_cuda_device_configuration(self):
292
+ """Test CUDA device configuration"""
293
+ import torch
294
+
295
+ # Test device selection logic
296
+ cuda_visible = os.environ.get("CUDA_VISIBLE_DEVICES", "")
297
+
298
+ if cuda_visible == "":
299
+ # Should fall back to CPU
300
+ expected_device = "cpu"
301
+ elif torch.cuda.is_available():
302
+ expected_device = "cuda"
303
+ else:
304
+ expected_device = "cpu"
305
+
306
+ # Verify device is valid
307
+ assert expected_device in ["cuda", "cpu"]
308
+
309
+ def test_model_configuration(self):
310
+ """Test model configuration parameters"""
311
+ # Test model ID
312
+ model_id = "google/gemma-3n-e2b-it"
313
+ assert isinstance(model_id, str)
314
+ assert "/" in model_id # Should be in format "org/model"
315
+
316
+ # Test model parameters that would be used
317
+ max_new_tokens = 512
318
+ temperature = 0.3
319
+
320
+ assert isinstance(max_new_tokens, int)
321
+ assert max_new_tokens > 0
322
+ assert isinstance(temperature, float)
323
+ assert 0 <= temperature <= 1.0