from app.services.data_service import DataService def test_prediction_basic_holdout_mae() -> None: ds = DataService() ds.load_data() assert ds.df is not None df = ds.df.dropna( subset=[ "weave", "blend", "Greige EPI", "Greige PPI", "FINISH EPI", "FINISH PPI", ] ).copy() sample = df.sample(n=min(120, len(df)), random_state=42) abs_epi_errors = [] abs_ppi_errors = [] valid = 0 for _, row in sample.iterrows(): payload = { "weave": row["weave"], "blend": row["blend"], "warp_count": float(row["warp_count"]) if row["warp_count"] == row["warp_count"] else None, "weft_count": float(row["weft_count"]) if row["weft_count"] == row["weft_count"] else None, "finish_epi": float(row["FINISH EPI"]), "finish_ppi": float(row["FINISH PPI"]), "target_gsm": float(row["FINISH GSM"]) if row["FINISH GSM"] == row["FINISH GSM"] else None, } out = ds.predict_construction(payload) rec = out.get("recommendation", {}) if rec.get("greige_epi") is None or rec.get("greige_ppi") is None: continue valid += 1 abs_epi_errors.append(abs(float(rec["greige_epi"]) - float(row["Greige EPI"]))) abs_ppi_errors.append(abs(float(rec["greige_ppi"]) - float(row["Greige PPI"]))) assert valid >= 80 mae_epi = sum(abs_epi_errors) / len(abs_epi_errors) mae_ppi = sum(abs_ppi_errors) / len(abs_ppi_errors) assert mae_epi < 45 assert mae_ppi < 20 def test_validation_report_endpoint_logic() -> None: ds = DataService() ds.load_data() report = ds.get_validation_report(sample_size=120, seed=9) assert "mae" in report assert report["scored_rows"] >= 80 assert report["mae"]["greige_epi"] < 35 assert report["mae"]["greige_ppi"] < 15