@@ -600,3 +600,70 @@ def test_hard_block_takes_priority_over_api_failure(self) -> None:
600600 source_checks = checks ,
601601 )
602602 assert result .level == RiskLevel .HARD_BLOCK
603+
604+
605+ # ---------------------------------------------------------------------------
606+ # Q1: zero median_estimated_rows must not raise ZeroDivisionError
607+ # ---------------------------------------------------------------------------
608+
609+
610+ class TestRiskEvaluatorZeroMedian :
611+ """Q1: history with median_estimated_rows=0.0 must not crash."""
612+
613+ def test_zero_median_history_does_not_raise (self ) -> None :
614+ """Feed history with median_estimated_rows=0.0, expect no exception."""
615+ history = HistoryStats (
616+ n = 5 ,
617+ median_elapsed_min = 30.0 ,
618+ median_estimated_rows = 0.0 ,
619+ success_rate = 1.0 ,
620+ )
621+ # Must not raise ZeroDivisionError
622+ result = evaluate (
623+ design = {"status" : "analyzing" },
624+ history = history ,
625+ config = _default_config (),
626+ source_checks = _good_source_checks (estimated_rows = 1_000_000 ),
627+ )
628+ assert result .level in {RiskLevel .HIGH , RiskLevel .MEDIUM , RiskLevel .LOW }
629+
630+ def test_zero_median_history_flags_uninformative (self ) -> None :
631+ """Confirm the flag signals why extrapolation was skipped."""
632+ history = HistoryStats (
633+ n = 5 ,
634+ median_elapsed_min = 30.0 ,
635+ median_estimated_rows = 0.0 ,
636+ success_rate = 1.0 ,
637+ )
638+ result = evaluate (
639+ design = {"status" : "analyzing" },
640+ history = history ,
641+ config = _default_config (),
642+ source_checks = _good_source_checks (estimated_rows = 1_000_000 ),
643+ )
644+ assert "history_uninformative" in result .flags
645+
646+
647+ # ---------------------------------------------------------------------------
648+ # Q2: assert replaced with ValueError for -O safety
649+ # ---------------------------------------------------------------------------
650+
651+
652+ class TestRiskEvaluatorAssertReplacement :
653+ """Q2: runtime invariants must raise ValueError, not AssertionError."""
654+
655+ def test_invalid_input_raises_value_error_not_assertion (self ) -> None :
656+ """Trigger the condition that used to assert, confirm ValueError."""
657+ history = HistoryStats (
658+ n = 5 ,
659+ median_elapsed_min = None , # violates invariant
660+ median_estimated_rows = 1_000_000.0 ,
661+ success_rate = 1.0 ,
662+ )
663+ with pytest .raises (ValueError ):
664+ evaluate (
665+ design = {"status" : "analyzing" },
666+ history = history ,
667+ config = _default_config (),
668+ source_checks = _good_source_checks (),
669+ )
0 commit comments