Spaces:
Sleeping
Sleeping
| """ | |
| Tests for engine/grader.py — Oracle grading formulas. | |
| """ | |
| import pytest | |
| import sys | |
| import os | |
| sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) | |
| from engine.grader import Grader | |
| class TestSafetyMultiplier: | |
| def test_no_violations(self): | |
| assert Grader.compute_safety_multiplier([], "easy") == 1.0 | |
| assert Grader.compute_safety_multiplier([], "medium") == 1.0 | |
| assert Grader.compute_safety_multiplier([], "hard") == 1.0 | |
| def test_production_violation(self): | |
| violations = ["Deleted production/critical resource i-abc123"] | |
| assert Grader.compute_safety_multiplier(violations, "easy") == 0.0 | |
| assert Grader.compute_safety_multiplier(violations, "medium") == 0.0 | |
| assert Grader.compute_safety_multiplier(violations, "hard") == 0.0 | |
| def test_critical_violation(self): | |
| violations = ["Deleted critical resource i-abc123"] | |
| assert Grader.compute_safety_multiplier(violations, "easy") == 0.0 | |
| def test_staging_violation_medium(self): | |
| violations = ["Deleted staging resource vol-abc123"] | |
| assert Grader.compute_safety_multiplier(violations, "medium") == 0.7 | |
| assert Grader.compute_safety_multiplier(violations, "hard") == 0.7 | |
| class TestFinalScore: | |
| def test_perfect_easy(self): | |
| """Perfect easy score: save everything, no violations.""" | |
| score = Grader.compute_final_score( | |
| actual_savings=100.0, | |
| optimal_savings=100.0, | |
| steps_taken=10, | |
| safety_violations=[], | |
| difficulty="easy", | |
| ) | |
| assert score == 1.0 | |
| def test_zero_savings(self): | |
| score = Grader.compute_final_score( | |
| actual_savings=0.0, | |
| optimal_savings=100.0, | |
| steps_taken=5, | |
| safety_violations=[], | |
| difficulty="easy", | |
| ) | |
| assert score == 0.0 | |
| def test_partial_savings_easy(self): | |
| score = Grader.compute_final_score( | |
| actual_savings=60.0, | |
| optimal_savings=100.0, | |
| steps_taken=5, | |
| safety_violations=[], | |
| difficulty="easy", | |
| ) | |
| assert 0.55 <= score <= 0.65 # 60% savings | |
| def test_production_violation_zeroes_score(self): | |
| score = Grader.compute_final_score( | |
| actual_savings=100.0, | |
| optimal_savings=100.0, | |
| steps_taken=5, | |
| safety_violations=["Deleted production resource i-abc"], | |
| difficulty="easy", | |
| ) | |
| assert score == 0.0 | |
| def test_medium_step_penalty(self): | |
| """Medium has 0.005 per step penalty.""" | |
| score_few = Grader.compute_final_score( | |
| actual_savings=100.0, | |
| optimal_savings=100.0, | |
| steps_taken=5, | |
| safety_violations=[], | |
| difficulty="medium", | |
| ) | |
| score_many = Grader.compute_final_score( | |
| actual_savings=100.0, | |
| optimal_savings=100.0, | |
| steps_taken=20, | |
| safety_violations=[], | |
| difficulty="medium", | |
| ) | |
| assert score_few > score_many | |
| assert abs(score_few - score_many - 15 * 0.005) < 0.001 | |
| def test_hard_step_penalty(self): | |
| """Hard has 0.003 per step penalty.""" | |
| score = Grader.compute_final_score( | |
| actual_savings=100.0, | |
| optimal_savings=100.0, | |
| steps_taken=10, | |
| safety_violations=[], | |
| difficulty="hard", | |
| ) | |
| expected = 1.0 - (10 * 0.003) # 0.97 | |
| assert abs(score - expected) < 0.001 | |
| def test_hard_cascade_penalty(self): | |
| """Hard subtracts cascade penalty from savings.""" | |
| score_no_cascade = Grader.compute_final_score( | |
| actual_savings=100.0, | |
| optimal_savings=100.0, | |
| steps_taken=5, | |
| safety_violations=[], | |
| difficulty="hard", | |
| cascade_penalty=0.0, | |
| ) | |
| score_with_cascade = Grader.compute_final_score( | |
| actual_savings=100.0, | |
| optimal_savings=100.0, | |
| steps_taken=5, | |
| safety_violations=[], | |
| difficulty="hard", | |
| cascade_penalty=20.0, | |
| ) | |
| assert score_no_cascade > score_with_cascade | |
| def test_score_clamped_to_0_1(self): | |
| """Scores should always be in [0, 1].""" | |
| # Very negative case | |
| score = Grader.compute_final_score( | |
| actual_savings=0.0, | |
| optimal_savings=100.0, | |
| steps_taken=200, | |
| safety_violations=[], | |
| difficulty="medium", | |
| ) | |
| assert score >= 0.0 | |
| # Very positive case (shouldn't exceed 1) | |
| score = Grader.compute_final_score( | |
| actual_savings=200.0, | |
| optimal_savings=100.0, | |
| steps_taken=1, | |
| safety_violations=[], | |
| difficulty="easy", | |
| ) | |
| assert score <= 1.0 | |
| def test_zero_optimal_savings(self): | |
| """Edge case: optimal_savings = 0 should return 0.""" | |
| score = Grader.compute_final_score( | |
| actual_savings=50.0, | |
| optimal_savings=0.0, | |
| steps_taken=5, | |
| safety_violations=[], | |
| difficulty="easy", | |
| ) | |
| assert score == 0.0 | |