Spaces:
Sleeping
Sleeping
| """Test reward calculation (cumulative, not per-step clamped).""" | |
| import pytest | |
| from trace.rewards import RewardCalculator, calculate_final_score | |
| from trace.models import Action | |
| def test_cumulative_rewards_not_clamped(): | |
| """Test that rewards accumulate and are not clamped per step.""" | |
| calc = RewardCalculator("easy_cpu_spike", root_cause="traffic_spike") | |
| # Give rewards that normally would be clamped | |
| calc.episode_rewards = [5.0, 5.0, -2.0, 10.0, 5.0] | |
| # Sum should not be clamped (should be 23.0) | |
| total = calc.get_episode_reward() | |
| assert total == 23.0, f"Expected 23.0, got {total}" | |
| # Only at the end is normalization applied | |
| normalized = calc.get_normalized_reward(max_possible=50) | |
| assert 0 <= normalized <= 1, "Normalized should be in [0,1]" | |
| def test_inspection_rewards(): | |
| """Test that inspection actions give rewards.""" | |
| calc = RewardCalculator("easy_cpu_spike", root_cause="traffic_spike") | |
| action = Action(action_type="inspect_logs", target="api_workers", value=None) | |
| reward = calc.calculate_step_reward( | |
| action=action, | |
| is_relevant=True, | |
| solves_issue=False, | |
| incident_resolved=False, | |
| step=0 | |
| ) | |
| assert reward > 0, "Inspection should give positive reward" | |
| def test_duplicate_action_penalty(): | |
| """Test that duplicate recent actions get penalized.""" | |
| calc = RewardCalculator("easy_cpu_spike", root_cause="traffic_spike") | |
| action = Action(action_type="inspect_logs", target="api_workers", value=None) | |
| # First action | |
| first_reward = calc.calculate_step_reward( | |
| action=action, | |
| is_relevant=True, | |
| solves_issue=False, | |
| incident_resolved=False, | |
| step=0 | |
| ) | |
| # Duplicate action (same type+target consecutively) | |
| dup_reward = calc.calculate_step_reward( | |
| action=action, | |
| is_relevant=True, | |
| solves_issue=False, | |
| incident_resolved=False, | |
| step=1 | |
| ) | |
| # Duplicate should get less reward than non-duplicate due to penalty | |
| assert dup_reward < first_reward, "Duplicate should receive less reward than first action" | |
| def test_final_score_calculation(): | |
| """Test outcome-based scoring (no diagnosis_accuracy).""" | |
| # Success in max steps | |
| score = calculate_final_score( | |
| incident_resolved=True, | |
| steps_taken=5, | |
| max_steps=5 | |
| ) | |
| assert score == 0.6, f"Expected 0.6, got {score}" | |
| # Success in half steps | |
| score = calculate_final_score( | |
| incident_resolved=True, | |
| steps_taken=2, | |
| max_steps=5 | |
| ) | |
| expected = 0.6 * 1.0 + 0.4 * (1.0 - 2/5) | |
| assert abs(score - expected) < 0.01, f"Expected {expected}, got {score}" | |
| # Failure | |
| score = calculate_final_score( | |
| incident_resolved=False, | |
| steps_taken=5, | |
| max_steps=5 | |
| ) | |
| assert score == 0.0, f"Expected 0.0, got {score}" | |