""" Tests for codebase fixes: confidence cap, validator, thresholds, schema validation """ import json import sys from pathlib import Path sys.path.insert(0, str(Path(__file__).parent.parent)) from api.app.models.schemas import HealthResponse, StructuredAnalysisRequest from api.app.services.extraction import predict_disease_simple as api_predict from scripts.chat import predict_disease_simple as cli_predict from src.biomarker_validator import BiomarkerValidator # ============================================================================ # Confidence cap tests # ============================================================================ class TestConfidenceCap: """Verify confidence never exceeds 1.0""" def test_api_confidence_capped_at_one(self): # Glucose>126 (+0.4), Glucose>180 (+0.2), HbA1c>=6.5 (+0.5) = 1.1 raw result = api_predict({"Glucose": 200, "HbA1c": 7.0}) assert result["confidence"] <= 1.0 def test_cli_confidence_capped_at_one(self): result = cli_predict({"Glucose": 200, "HbA1c": 7.0}) assert result["confidence"] <= 1.0 def test_confidence_is_exactly_one_for_high_diabetes(self): result = api_predict({"Glucose": 200, "HbA1c": 7.0}) assert result["confidence"] == 1.0 def test_confidence_not_capped_when_below_one(self): result = api_predict({"Glucose": 130}) assert result["confidence"] == 0.4 # ============================================================================ # Updated critical threshold tests # ============================================================================ class TestCriticalThresholds: """Verify biomarker_references.json has clinically appropriate critical thresholds""" def setup_method(self): config_path = Path(__file__).parent.parent / "config" / "biomarker_references.json" with open(config_path) as f: self.refs = json.load(f)["biomarkers"] def test_glucose_critical_high_is_emergency(self): assert self.refs["Glucose"]["critical_high"] >= 300 def test_glucose_critical_low_is_emergency(self): assert self.refs["Glucose"]["critical_low"] <= 54 def test_hba1c_critical_high_is_emergency(self): assert self.refs["HbA1c"]["critical_high"] >= 10 def test_troponin_critical_high_above_normal(self): normal_max = self.refs["Troponin"]["normal_range"]["max"] assert self.refs["Troponin"]["critical_high"] > normal_max def test_bmi_critical_high_is_morbid(self): assert self.refs["BMI"]["critical_high"] >= 40 def test_systolic_bp_critical_high_is_crisis(self): assert self.refs["Systolic Blood Pressure"]["critical_high"] >= 180 def test_diastolic_bp_critical_low_is_shock(self): assert self.refs["Diastolic Blood Pressure"]["critical_low"] <= 40 # ============================================================================ # Validator threshold removal tests # ============================================================================ class TestValidatorNoThreshold: """Verify validator flags all out-of-range values (no 15% threshold)""" def setup_method(self): self.validator = BiomarkerValidator() def test_slightly_high_glucose_is_flagged(self): """Glucose=105 is above normal max=100 — should be HIGH, not NORMAL""" flag = self.validator.validate_biomarker("Glucose", 105.0) assert flag.status == "HIGH" def test_slightly_low_hemoglobin_is_flagged(self): """Hemoglobin=13.0 for male (min=13.5) should be LOW""" flag = self.validator.validate_biomarker("Hemoglobin", 13.0, gender="male") assert flag.status == "LOW" def test_normal_glucose_stays_normal(self): flag = self.validator.validate_biomarker("Glucose", 90.0) assert flag.status == "NORMAL" def test_critical_high_glucose_flagged(self): flag = self.validator.validate_biomarker("Glucose", 500.0) assert flag.status == "CRITICAL_HIGH" def test_high_glucose_200_not_critical(self): """Glucose=200 is above normal but below critical_high=400""" flag = self.validator.validate_biomarker("Glucose", 200.0) assert flag.status == "HIGH" # ============================================================================ # Pydantic schema validation tests # ============================================================================ class TestSchemaValidation: """Verify Pydantic models enforce constraints correctly""" def test_structured_request_rejects_empty_biomarkers(self): import pytest with pytest.raises(Exception): StructuredAnalysisRequest(biomarkers={}) def test_structured_request_accepts_valid_biomarkers(self): req = StructuredAnalysisRequest(biomarkers={"Glucose": 100.0}) assert req.biomarkers == {"Glucose": 100.0} def test_health_response_uses_llm_status_field(self): resp = HealthResponse( status="healthy", timestamp="2025-01-01T00:00:00", llm_status="connected", vector_store_loaded=True, available_models=["test"], uptime_seconds=100.0, version="1.0.0", ) assert resp.llm_status == "connected"