Spaces:
Sleeping
Sleeping
| import os | |
| import sys | |
| import time | |
| import subprocess | |
| import requests | |
| import socket | |
| from contextlib import closing | |
| # Ensure project root is in path | |
| PROJECT_ROOT = os.path.abspath(os.path.join(os.path.dirname(__file__), '..')) | |
| sys.path.insert(0, PROJECT_ROOT) | |
| import pytest | |
| from fastapi.testclient import TestClient | |
| from app.main import app | |
| def find_free_port(): | |
| with closing(socket.socket(socket.AF_INET, socket.SOCK_STREAM)) as s: | |
| s.bind(('', 0)) | |
| s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) | |
| return s.getsockname()[1] | |
| def client(): | |
| """ | |
| Test client for the FastAPI app. | |
| """ | |
| return TestClient(app) | |
| def test_server(): | |
| """ | |
| Starts a uvicorn server in a subprocess for E2E tests. | |
| Yields the base URL (e.g., http://127.0.0.1:8001). | |
| """ | |
| port = find_free_port() | |
| host = "127.0.0.1" | |
| base_url = f"http://{host}:{port}" | |
| env = os.environ.copy() | |
| env["PYTHONPATH"] = PROJECT_ROOT # Ensure standard imports work | |
| log_path = f"/tmp/test_server_{port}.log" | |
| log_file = open(log_path, "w") | |
| proc = subprocess.Popen( | |
| [sys.executable, "-m", "uvicorn", "app.main:app", "--host", host, "--port", str(port)], | |
| env=env, | |
| stdout=log_file, | |
| stderr=subprocess.STDOUT, | |
| cwd=PROJECT_ROOT # Start from project root | |
| ) | |
| # Health check loop | |
| start_time = time.time() | |
| while time.time() - start_time < 10: | |
| try: | |
| resp = requests.get(f"{base_url}/api/health") | |
| if resp.status_code == 200: | |
| break | |
| except requests.ConnectionError: | |
| time.sleep(0.1) | |
| else: | |
| # Timeout | |
| print(f"Server failed to start. Logs in {log_path}") | |
| proc.kill() | |
| log_file.close() | |
| raise RuntimeError("Test server failed to start") | |
| yield base_url | |
| # Teardown | |
| proc.terminate() | |
| try: | |
| proc.wait(timeout=2) | |
| except subprocess.TimeoutExpired: | |
| proc.kill() | |
| log_file.close() | |
| # Read and print logs if failed (or always for debugging now) | |
| try: | |
| with open(log_path, "r") as f: | |
| print(f"\n--- TEST SERVER LOGS ({port}) ---\n") | |
| print(f.read()) | |
| print(f"\n--- END LOGS ---\n") | |
| except: | |
| pass | |
| # Clean up log file | |
| # Clean up log file | |
| if os.path.exists(log_path): | |
| try: | |
| os.remove(log_path) | |
| except: | |
| pass | |