"""Pruebas del esquema estructurado y la validación que reemplaza a limpiarRespuesta.""" from __future__ import annotations import pytest from pydantic import ValidationError from app.schemas import ( Diferencial, InterpretacionClinica, PeticionInterpretacion, ) def test_interpretacion_valida(): inter = InterpretacionClinica( interpretacion="Anemia microcítica compatible con ferropenia.", diferenciales=[ Diferencial(nombre="Ferropenia", probabilidad="alta", evidencia=["VCM bajo"], citas=["Thrall, 3ª ed., p. 210"]) ], siguientes_pruebas=["Perfil de hierro"], confianza="media", requiere_derivacion=True, ) assert inter.idioma == "es" assert inter.diferenciales[0].probabilidad == "alta" def test_interpretacion_rechaza_vacia(): with pytest.raises(ValidationError): InterpretacionClinica(interpretacion=" ") def test_probabilidad_invalida_rechazada(): with pytest.raises(ValidationError): Diferencial(nombre="X", probabilidad="segurísima") def test_peticion_limita_a_4_imagenes(): pet = PeticionInterpretacion( paciente={"especie": "canino"}, imagenes=[f"data:image/png;base64,AAAA{i}" for i in range(10)], ) assert len(pet.imagenes) == 4 def test_json_schema_generable_para_tool_use(): # El cliente Claude/medGemma pasa este schema como salida estructurada. esquema = InterpretacionClinica.model_json_schema() assert "diferenciales" in esquema["properties"] assert esquema["properties"]["requiere_derivacion"]["type"] == "boolean" def test_el_esquema_estructurado_exige_contenido(): """El esquema por defecto admite `{"interpretacion": "..."}` con todo lo demás vacío; el endurecido se lo pide explícitamente al modelo.""" from app.schemas import esquema_estructurado esquema = esquema_estructurado() for campo in ("hallazgos_clave", "diferenciales", "siguientes_pruebas"): assert esquema["properties"][campo]["minItems"] == 1 assert campo in esquema["required"] def test_el_esquema_por_defecto_sigue_siendo_permisivo(): """La ruta de prosa construye la interpretación sin campos estructurados y debe validar.""" from app.schemas import InterpretacionClinica interp = InterpretacionClinica(interpretacion="Sólo prosa.") assert interp.diferenciales == [] def test_analitos_medidos_es_opcional(): """Retrocompatible: una petición de un cliente que no lo manda sigue siendo válida, y el prompt y la guarda de invención se apagan solos ante la lista vacía.""" pet = PeticionInterpretacion.model_validate({"paciente": {"especie": "canino"}}) assert pet.analitos_medidos == [] def test_analitos_medidos_conserva_las_claves(): pet = PeticionInterpretacion.model_validate( {"paciente": {"especie": "felino"}, "analitos_medidos": ["calc", "fosf", "creat"]} ) assert pet.analitos_medidos == ["calc", "fosf", "creat"]