MogensR commited on
Commit
7b77141
·
1 Parent(s): 2f84e70

Update tests/pytest.ini

Browse files
Files changed (1) hide show
  1. tests/pytest.ini +53 -356
tests/pytest.ini CHANGED
@@ -1,356 +1,53 @@
1
- """
2
- Tests for API endpoints and WebSocket functionality.
3
- """
4
-
5
- import pytest
6
- import json
7
- import base64
8
- from unittest.mock import Mock, patch, MagicMock
9
- from fastapi.testclient import TestClient
10
- import numpy as np
11
- import cv2
12
-
13
- from api.api_server import app, ProcessingRequest, ProcessingResponse
14
- from api.websocket import WebSocketHandler, WSMessage, MessageType
15
-
16
-
17
- class TestAPIEndpoints:
18
- """Test REST API endpoints."""
19
-
20
- @pytest.fixture
21
- def client(self):
22
- """Create test client."""
23
- return TestClient(app)
24
-
25
- @pytest.fixture
26
- def auth_headers(self):
27
- """Create authentication headers."""
28
- # Mock authentication for testing
29
- return {"Authorization": "Bearer test-token"}
30
-
31
- def test_root_endpoint(self, client):
32
- """Test root endpoint."""
33
- response = client.get("/")
34
- assert response.status_code == 200
35
- data = response.json()
36
- assert "name" in data
37
- assert data["name"] == "BackgroundFX Pro API"
38
-
39
- def test_health_check(self, client):
40
- """Test health check endpoint."""
41
- response = client.get("/health")
42
- assert response.status_code == 200
43
- data = response.json()
44
- assert data["status"] == "healthy"
45
- assert "services" in data
46
-
47
- @patch('api.api_server.verify_token')
48
- def test_process_image_endpoint(self, mock_verify, client, auth_headers, sample_image):
49
- """Test image processing endpoint."""
50
- mock_verify.return_value = "test-user"
51
-
52
- # Create test image file
53
- _, buffer = cv2.imencode('.jpg', sample_image)
54
-
55
- files = {"file": ("test.jpg", buffer.tobytes(), "image/jpeg")}
56
- data = {
57
- "background": "blur",
58
- "quality": "high"
59
- }
60
-
61
- with patch('api.api_server.process_image_task'):
62
- response = client.post(
63
- "/api/v1/process/image",
64
- headers=auth_headers,
65
- files=files,
66
- data=data
67
- )
68
-
69
- assert response.status_code == 200
70
- result = response.json()
71
- assert "job_id" in result
72
- assert result["status"] == "processing"
73
-
74
- @patch('api.api_server.verify_token')
75
- def test_process_video_endpoint(self, mock_verify, client, auth_headers, sample_video):
76
- """Test video processing endpoint."""
77
- mock_verify.return_value = "test-user"
78
-
79
- with open(sample_video, 'rb') as f:
80
- files = {"file": ("test.mp4", f.read(), "video/mp4")}
81
-
82
- data = {
83
- "background": "office",
84
- "quality": "medium"
85
- }
86
-
87
- with patch('api.api_server.process_video_task'):
88
- response = client.post(
89
- "/api/v1/process/video",
90
- headers=auth_headers,
91
- files=files,
92
- data=data
93
- )
94
-
95
- assert response.status_code == 200
96
- result = response.json()
97
- assert "job_id" in result
98
-
99
- @patch('api.api_server.verify_token')
100
- def test_batch_processing_endpoint(self, mock_verify, client, auth_headers):
101
- """Test batch processing endpoint."""
102
- mock_verify.return_value = "test-user"
103
-
104
- batch_request = {
105
- "items": [
106
- {"id": "1", "input_path": "/tmp/img1.jpg", "output_path": "/tmp/out1.jpg"},
107
- {"id": "2", "input_path": "/tmp/img2.jpg", "output_path": "/tmp/out2.jpg"}
108
- ],
109
- "parallel": True,
110
- "priority": "normal"
111
- }
112
-
113
- with patch('api.api_server.process_batch_task'):
114
- response = client.post(
115
- "/api/v1/batch",
116
- headers=auth_headers,
117
- json=batch_request
118
- )
119
-
120
- assert response.status_code == 200
121
- result = response.json()
122
- assert "job_id" in result
123
-
124
- @patch('api.api_server.verify_token')
125
- def test_job_status_endpoint(self, mock_verify, client, auth_headers):
126
- """Test job status endpoint."""
127
- mock_verify.return_value = "test-user"
128
-
129
- job_id = "test-job-123"
130
-
131
- with patch.object(app.state.job_manager, 'get_job') as mock_get:
132
- mock_get.return_value = ProcessingResponse(
133
- job_id=job_id,
134
- status="completed",
135
- progress=1.0
136
- )
137
-
138
- response = client.get(
139
- f"/api/v1/job/{job_id}",
140
- headers=auth_headers
141
- )
142
-
143
- assert response.status_code == 200
144
- result = response.json()
145
- assert result["job_id"] == job_id
146
- assert result["status"] == "completed"
147
-
148
- @patch('api.api_server.verify_token')
149
- def test_streaming_endpoints(self, mock_verify, client, auth_headers):
150
- """Test streaming endpoints."""
151
- mock_verify.return_value = "test-user"
152
-
153
- # Start stream
154
- stream_request = {
155
- "source": "0",
156
- "stream_type": "webcam",
157
- "output_format": "hls"
158
- }
159
-
160
- with patch.object(app.state.video_processor, 'start_stream_processing') as mock_start:
161
- mock_start.return_value = True
162
-
163
- response = client.post(
164
- "/api/v1/stream/start",
165
- headers=auth_headers,
166
- json=stream_request
167
- )
168
-
169
- assert response.status_code == 200
170
- result = response.json()
171
- assert result["status"] == "streaming"
172
-
173
- # Stop stream
174
- with patch.object(app.state.video_processor, 'stop_stream_processing'):
175
- response = client.get(
176
- "/api/v1/stream/stop",
177
- headers=auth_headers
178
- )
179
-
180
- assert response.status_code == 200
181
-
182
-
183
- class TestWebSocket:
184
- """Test WebSocket functionality."""
185
-
186
- @pytest.fixture
187
- def ws_handler(self):
188
- """Create WebSocket handler."""
189
- return WebSocketHandler()
190
-
191
- def test_websocket_connection(self, ws_handler, mock_websocket):
192
- """Test WebSocket connection handling."""
193
- # Test connection acceptance
194
- async def test_connect():
195
- await ws_handler.handle_connection(mock_websocket)
196
-
197
- # Would need async test runner for full test
198
- assert mock_websocket.accept.called or True # Simplified for sync test
199
-
200
- def test_message_parsing(self, ws_handler):
201
- """Test WebSocket message parsing."""
202
- message_data = {
203
- "type": "process_frame",
204
- "data": {"frame": "base64_data"}
205
- }
206
-
207
- message = WSMessage.from_dict(message_data)
208
-
209
- assert message.type == MessageType.PROCESS_FRAME
210
- assert message.data["frame"] == "base64_data"
211
-
212
- def test_frame_encoding_decoding(self, ws_handler, sample_image):
213
- """Test frame encoding and decoding."""
214
- # Encode frame
215
- _, buffer = cv2.imencode('.jpg', sample_image)
216
- encoded = base64.b64encode(buffer).decode('utf-8')
217
-
218
- # Decode frame
219
- decoded = ws_handler.frame_processor._decode_frame(encoded)
220
-
221
- assert decoded is not None
222
- assert decoded.shape == sample_image.shape
223
-
224
- def test_session_management(self, ws_handler):
225
- """Test client session management."""
226
- mock_ws = MagicMock()
227
-
228
- # Add session
229
- async def test_add():
230
- session = await ws_handler.session_manager.add_session(mock_ws, "test-client")
231
- assert session.client_id == "test-client"
232
-
233
- # Would need async test runner for full test
234
- assert ws_handler.session_manager is not None
235
-
236
- def test_message_routing(self, ws_handler):
237
- """Test message routing."""
238
- messages = [
239
- WSMessage(type=MessageType.PING, data={}),
240
- WSMessage(type=MessageType.UPDATE_CONFIG, data={"quality": "high"}),
241
- WSMessage(type=MessageType.START_STREAM, data={"source": 0})
242
- ]
243
-
244
- for msg in messages:
245
- assert msg.type in MessageType
246
- assert isinstance(msg.to_dict(), dict)
247
-
248
- def test_statistics_tracking(self, ws_handler):
249
- """Test WebSocket statistics."""
250
- stats = ws_handler.get_statistics()
251
-
252
- assert "uptime" in stats
253
- assert "total_connections" in stats
254
- assert "active_connections" in stats
255
- assert "total_frames_processed" in stats
256
-
257
-
258
- class TestAPIIntegration:
259
- """Integration tests for API."""
260
-
261
- @pytest.mark.integration
262
- def test_full_image_processing_flow(self, client, sample_image, temp_dir):
263
- """Test complete image processing flow."""
264
- # Skip authentication for integration test
265
- with patch('api.api_server.verify_token', return_value="test-user"):
266
- # Upload image
267
- _, buffer = cv2.imencode('.jpg', sample_image)
268
- files = {"file": ("test.jpg", buffer.tobytes(), "image/jpeg")}
269
-
270
- response = client.post(
271
- "/api/v1/process/image",
272
- files=files,
273
- data={"background": "blur", "quality": "low"}
274
- )
275
-
276
- assert response.status_code == 200
277
- job_data = response.json()
278
- job_id = job_data["job_id"]
279
-
280
- # Check job status
281
- response = client.get(f"/api/v1/job/{job_id}")
282
-
283
- # Would need actual processing for full test
284
- assert response.status_code in [200, 404]
285
-
286
- @pytest.mark.integration
287
- @pytest.mark.slow
288
- def test_concurrent_requests(self, client):
289
- """Test handling concurrent requests."""
290
- import concurrent.futures
291
-
292
- def make_request():
293
- response = client.get("/health")
294
- return response.status_code
295
-
296
- with concurrent.futures.ThreadPoolExecutor(max_workers=10) as executor:
297
- futures = [executor.submit(make_request) for _ in range(10)]
298
- results = [f.result() for f in concurrent.futures.as_completed(futures)]
299
-
300
- assert all(status == 200 for status in results)
301
-
302
- @pytest.mark.integration
303
- def test_error_handling(self, client):
304
- """Test API error handling."""
305
- # Test invalid endpoint
306
- response = client.get("/api/v1/invalid")
307
- assert response.status_code == 404
308
-
309
- # Test missing authentication
310
- response = client.get("/api/v1/stats")
311
- assert response.status_code in [401, 422] # Unauthorized or validation error
312
-
313
- # Test invalid file format
314
- with patch('api.api_server.verify_token', return_value="test-user"):
315
- files = {"file": ("test.txt", b"text content", "text/plain")}
316
- response = client.post(
317
- "/api/v1/process/image",
318
- files=files,
319
- headers={"Authorization": "Bearer test"}
320
- )
321
- assert response.status_code == 400
322
-
323
-
324
- class TestAPIPerformance:
325
- """Performance tests for API."""
326
-
327
- @pytest.mark.slow
328
- def test_response_time(self, client, performance_timer):
329
- """Test API response times."""
330
- endpoints = ["/", "/health"]
331
-
332
- for endpoint in endpoints:
333
- with performance_timer as timer:
334
- response = client.get(endpoint)
335
-
336
- assert response.status_code == 200
337
- assert timer.elapsed < 0.1 # Should respond in under 100ms
338
-
339
- @pytest.mark.slow
340
- def test_file_upload_performance(self, client, performance_timer):
341
- """Test file upload performance."""
342
- # Create a 1MB test file
343
- large_data = np.random.randint(0, 255, (1024, 1024, 3), dtype=np.uint8)
344
- _, buffer = cv2.imencode('.jpg', large_data)
345
-
346
- with patch('api.api_server.verify_token', return_value="test-user"):
347
- with patch('api.api_server.process_image_task'):
348
- with performance_timer as timer:
349
- response = client.post(
350
- "/api/v1/process/image",
351
- files={"file": ("large.jpg", buffer.tobytes(), "image/jpeg")},
352
- headers={"Authorization": "Bearer test"}
353
- )
354
-
355
- assert response.status_code == 200
356
- assert timer.elapsed < 2.0 # Should handle 1MB in under 2 seconds
 
1
+ [pytest]
2
+ # Pytest configuration for BackgroundFX Pro
3
+
4
+ # Test discovery
5
+ testpaths = tests
6
+ python_files = test_*.py
7
+ python_classes = Test*
8
+ python_functions = test_*
9
+
10
+ # Markers
11
+ markers =
12
+ slow: marks tests as slow (deselect with '-m "not slow"')
13
+ gpu: marks tests that require GPU
14
+ integration: marks integration tests
15
+ unit: marks unit tests
16
+ api: marks API tests
17
+ models: marks model-related tests
18
+ pipeline: marks pipeline tests
19
+ performance: marks performance tests
20
+
21
+ # Coverage
22
+ addopts =
23
+ --verbose
24
+ --strict-markers
25
+ --tb=short
26
+ --cov=.
27
+ --cov-report=html
28
+ --cov-report=term-missing
29
+ --cov-config=.coveragerc
30
+
31
+ # Logging
32
+ log_cli = true
33
+ log_cli_level = INFO
34
+ log_cli_format = %(asctime)s [%(levelname)8s] %(message)s
35
+ log_cli_date_format = %Y-%m-%d %H:%M:%S
36
+
37
+ # Warnings
38
+ filterwarnings =
39
+ ignore::DeprecationWarning
40
+ ignore::PendingDeprecationWarning
41
+ ignore::FutureWarning:torch.*
42
+
43
+ # Timeout
44
+ timeout = 300
45
+
46
+ # Parallel execution (optional, requires pytest-xdist)
47
+ # addopts = -n auto
48
+
49
+ # Environment variables for testing
50
+ env =
51
+ TESTING = 1
52
+ DEVICE = cpu
53
+ LOG_LEVEL = WARNING