conftest.py
1 """ 2 Configuration globale pour les tests pytest de l'API d'inférence multi-session. 3 """ 4 5 import pytest 6 import os 7 import requests 8 import time 9 import sys 10 from pathlib import Path 11 12 # Ajouter le répertoire racine du projet au PYTHONPATH 13 # Cette ligne résout le problème d'importation des modules 14 project_root = Path(__file__).parent.parent.absolute() 15 if str(project_root) not in sys.path: 16 sys.path.insert(0, str(project_root)) 17 print(f"Ajout du chemin racine au sys.path: {project_root}") 18 19 # URL de base de l'API (ajuster selon l'environnement) 20 BASE_URL = os.environ.get("API_BASE_URL", "http://localhost:8000") 21 22 # Variables partagées entre les tests 23 shared_data = { 24 "user": None, 25 "token": None, 26 "api_key": None 27 } 28 29 @pytest.fixture(scope="session", autouse=True) 30 def check_api_availability(): 31 """Vérifie si l'API est disponible avant d'exécuter les tests.""" 32 try: 33 response = requests.get(f"{BASE_URL}/api/health", timeout=5) 34 if response.status_code != 200: 35 pytest.skip(f"L'API n'est pas disponible ou a retourné un statut non-OK: {response.status_code}") 36 except requests.exceptions.RequestException: 37 pytest.skip("L'API n'est pas accessible") 38 39 @pytest.fixture(scope="session") 40 def api_url(): 41 """Retourne l'URL de base de l'API.""" 42 return BASE_URL 43 44 @pytest.fixture(scope="session") 45 def api_key(): 46 """Retourne une clé API valide pour les tests.""" 47 # Essayer d'utiliser une clé API fournie via variable d'environnement 48 api_key = os.environ.get("TEST_API_KEY") 49 if api_key: 50 return api_key 51 52 # Si aucune clé API n'est fournie, essayer de créer un utilisateur et une clé API 53 if not shared_data["api_key"]: 54 try: 55 # Créer un utilisateur 56 import random 57 import string 58 random_suffix = ''.join(random.choices(string.ascii_lowercase + string.digits, k=8)) 59 username = f"testuser_{random_suffix}" 60 61 user_data = { 62 "username": username, 63 "email": f"{username}@example.com", 64 "password": "Password123!", 65 "full_name": "Test User" 66 } 67 68 response = requests.post(f"{BASE_URL}/auth/register", json=user_data) 69 if response.status_code != 201: 70 pytest.skip(f"Impossible de créer un utilisateur de test: {response.text}") 71 72 user_info = response.json() 73 shared_data["user"] = user_info 74 75 # Se connecter pour obtenir un token 76 login_data = { 77 "username": username, 78 "password": "Password123!" 79 } 80 81 response = requests.post(f"{BASE_URL}/auth/token", data=login_data) 82 if response.status_code != 200: 83 pytest.skip(f"Impossible d'obtenir un token: {response.text}") 84 85 token_info = response.json() 86 shared_data["token"] = token_info["access_token"] 87 88 # Créer une clé API 89 headers = { 90 "Authorization": f"Bearer {shared_data['token']}" 91 } 92 93 key_data = { 94 "name": "Test API Key" 95 } 96 97 response = requests.post(f"{BASE_URL}/auth/api-keys", json=key_data, headers=headers) 98 if response.status_code != 201: 99 pytest.skip(f"Impossible de créer une clé API: {response.text}") 100 101 api_key_info = response.json() 102 shared_data["api_key"] = api_key_info["key"] 103 104 except Exception as e: 105 pytest.skip(f"Erreur lors de la création d'une clé API de test: {e}") 106 107 return shared_data["api_key"] 108 109 @pytest.fixture(scope="session") 110 def auth_headers(api_key): 111 """Retourne les headers d'authentification avec une clé API.""" 112 return { 113 "X-API-Key": api_key 114 } 115 116 @pytest.fixture(scope="session") 117 def wait_for_completion(): 118 """Fonction utilitaire pour attendre la fin d'une tâche.""" 119 def _wait_for_completion(task_id, auth_headers, max_retries=30, interval=10): 120 """Attend la fin d'une tâche et retourne son résultat.""" 121 for i in range(max_retries): 122 response = requests.get(f"{BASE_URL}/api/inference/{task_id}", headers=auth_headers) 123 assert response.status_code == 200 124 125 data = response.json() 126 127 if data["status"] == "failed": 128 pytest.fail(f"La tâche a échoué: {data.get('error', 'Erreur inconnue')}") 129 130 if data["status"] == "completed": 131 return data 132 133 print(f"Attente de la fin de la tâche... Progression: {data.get('progress', 0):.0f}% (tentative {i+1}/{max_retries})") 134 135 time.sleep(interval) 136 137 pytest.fail(f"La tâche n'est pas terminée après {max_retries} tentatives") 138 139 return _wait_for_completion