""" test_api.py =========== Script de prueba para verificar todos los endpoints de la API. Requiere que la API esté corriendo: python app.py Ejecutar: python test_api.py """ import json import random import numpy as np import requests BASE_URL = "http://127.0.0.1:5000" CLASS_NAMES = [ "T-shirt/top", "Trouser", "Pullover", "Dress", "Coat", "Sandal", "Shirt", "Sneaker", "Bag", "Ankle boot", ] def separator(title: str): print(f"\n{'─'*60}") print(f" {title}") print(f"{'─'*60}") # ── 1. /health ──────────────────────────────────────────────────────────────── separator("GET /health") try: r = requests.get(f"{BASE_URL}/health", timeout=5) print(f"Status HTTP: {r.status_code}") print(json.dumps(r.json(), indent=2, ensure_ascii=False)) except Exception as e: print(f"❌ Error: {e}") # ── 2. /model/info ──────────────────────────────────────────────────────────── separator("GET /model/info") try: r = requests.get(f"{BASE_URL}/model/info", timeout=5) print(f"Status HTTP: {r.status_code}") print(json.dumps(r.json(), indent=2, ensure_ascii=False)) except Exception as e: print(f"❌ Error: {e}") # ── 3. /predict — imagen aleatoria ──────────────────────────────────────────── separator("POST /predict (imagen aleatoria 784 píxeles)") try: pixels = [random.randint(0, 255) for _ in range(784)] payload = {"pixels": pixels} r = requests.post(f"{BASE_URL}/predict", json=payload, timeout=10) print(f"Status HTTP: {r.status_code}") resp = r.json() # Mostrar solo top-3 probabilidades para no saturar la consola top3 = sorted(resp.get("probabilities", {}).items(), key=lambda x: -x[1])[:3] print(f" Predicción : {resp.get('class_name')} (id={resp.get('class_id')})") print(f" Confianza : {resp.get('confidence'):.2%}") print(f" Top-3 probs: {dict(top3)}") print(f" Inferencia : {resp.get('inference_ms')} ms") except Exception as e: print(f"❌ Error: {e}") # ── 4. /predict — payload inválido (menos de 784) ───────────────────────────── separator("POST /predict (validación: 100 píxeles → debe fallar)") try: pixels = [128] * 100 r = requests.post(f"{BASE_URL}/predict", json={"pixels": pixels}, timeout=5) print(f"Status HTTP: {r.status_code} (esperado 400)") print(json.dumps(r.json(), indent=2, ensure_ascii=False)) except Exception as e: print(f"❌ Error: {e}") # ── 5. /predict/batch ───────────────────────────────────────────────────────── separator("POST /predict/batch (3 imágenes aleatorias)") try: batch = [[random.randint(0, 255) for _ in range(784)] for _ in range(3)] r = requests.post(f"{BASE_URL}/predict/batch", json={"images": batch}, timeout=30) print(f"Status HTTP: {r.status_code}") resp = r.json() print(f" Total imágenes : {resp.get('count')}") print(f" Inferencia : {resp.get('inference_ms')} ms") for i, result in enumerate(resp.get("results", [])): print(f" [{i}] {result['class_name']:15s} confianza={result['confidence']:.2%}") except Exception as e: print(f"❌ Error: {e}") # ── 6. /predict con datos reales de Fashion-MNIST ───────────────────────────── separator("POST /predict (imagen real de Fashion-MNIST via sklearn)") try: from sklearn.datasets import fetch_openml print(" Cargando 5 muestras de Fashion-MNIST para verificación real...") X_real, y_real = fetch_openml( "Fashion-MNIST", version=1, return_X_y=True, as_frame=False ) sample_idx = [0, 1000, 5000, 10000, 20000] correct = 0 for idx in sample_idx: pixels = X_real[idx].tolist() true_lbl = int(y_real[idx]) r = requests.post(f"{BASE_URL}/predict", json={"pixels": pixels}, timeout=10) pred_id = r.json().get("class_id") match = "✅" if pred_id == true_lbl else "❌" if pred_id == true_lbl: correct += 1 print(f" [{idx:>6}] Real: {CLASS_NAMES[true_lbl]:15s} | " f"Pred: {CLASS_NAMES[pred_id]:15s} {match}") print(f"\n Correctas: {correct}/{len(sample_idx)}") except ImportError: print(" sklearn no disponible en este entorno para la prueba real.") except Exception as e: print(f"❌ Error: {e}") print(f"\n{'═'*60}") print(" Pruebas finalizadas") print(f"{'═'*60}\n")