import unittest from unittest.mock import patch from evolution.mvp import Finding, Sample, can_publish_candidate, evaluate_samples class EvolutionMvpTest(unittest.TestCase): def test_evaluate_detects_risk_without_transfer(self): samples = [ Sample( customer_id="c1", acc_id="shop", in_ts="2026-02-28 10:00:00", in_text="我要投诉并退款,你们骗人", out_ts="2026-02-28 10:00:10", out_text="这个我不清楚,稍后再说", latency_sec=10, ) ] findings = evaluate_samples(samples) kinds = {f.kind for f in findings} self.assertIn("risk_not_transferred", kinds) self.assertIn("weak_reply", kinds) def test_publish_gate(self): samples = [ Sample( customer_id=f"c{i}", acc_id="shop", in_ts="2026-02-28 10:00:00", in_text="你好", out_ts="2026-02-28 10:00:05", out_text="您好", latency_sec=5, ) for i in range(35) ] findings: list[Finding] = [] policy = { "publish_gate": { "min_sample_count": 30, "max_high_findings_rate": 0.1, "max_ai_fail_rate": 5.0, "max_transfer_rate": 45.0, } } with patch("utils.metrics_tracker.get_runtime_summary", return_value={"rates": {"ai_fail_rate": 1.0, "transfer_rate": 10.0}}): ok, report = can_publish_candidate(samples, findings, runtime_hours=24, policy=policy) self.assertTrue(ok) self.assertEqual(report["sample_count"], 35) if __name__ == "__main__": unittest.main(verbosity=2)