File size: 6,151 Bytes
fcf8749
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
"""
Unit tests for workload score calculations.
Tests route difficulty and workload score functions.
"""

import pytest
from app.services.workload import (
    calculate_route_difficulty,
    estimate_route_time,
    calculate_workload,
    RouteMetrics,
)


class TestRouteDifficulty:
    """Tests for route difficulty calculation."""
    
    def test_difficulty_base(self):
        """Minimal route should have base difficulty."""
        result = calculate_route_difficulty(
            total_weight_kg=0.0,
            num_stops=0,
            avg_fragility=1.0,
        )
        # Base difficulty is 1.0
        assert result >= 1.0
    
    def test_difficulty_increases_with_weight(self):
        """Higher weight should increase difficulty."""
        light = calculate_route_difficulty(10.0, 5, 1.0)
        heavy = calculate_route_difficulty(50.0, 5, 1.0)
        assert heavy > light
    
    def test_difficulty_increases_with_stops(self):
        """More stops should increase difficulty."""
        few_stops = calculate_route_difficulty(20.0, 3, 1.0)
        many_stops = calculate_route_difficulty(20.0, 15, 1.0)
        assert many_stops > few_stops
    
    def test_difficulty_increases_with_fragility(self):
        """Higher fragility should increase difficulty."""
        low_fragility = calculate_route_difficulty(20.0, 5, 1.0)
        high_fragility = calculate_route_difficulty(20.0, 5, 5.0)
        assert high_fragility > low_fragility
    
    def test_difficulty_realistic_route(self):
        """Test realistic route parameters."""
        result = calculate_route_difficulty(
            total_weight_kg=45.0,
            num_stops=12,
            avg_fragility=2.5,
        )
        # Should be a moderate difficulty
        assert 1.0 < result < 10.0


class TestEstimateRouteTime:
    """Tests for route time estimation."""
    
    def test_time_base(self):
        """Empty route should have base time."""
        result = estimate_route_time(0, 0)
        assert result >= 30  # Base time is 30 minutes
    
    def test_time_increases_with_packages(self):
        """More packages should increase time."""
        few = estimate_route_time(5, 3)
        many = estimate_route_time(25, 3)
        assert many > few
    
    def test_time_increases_with_stops(self):
        """More stops should increase time."""
        few_stops = estimate_route_time(10, 3)
        many_stops = estimate_route_time(10, 12)
        assert many_stops > few_stops
    
    def test_time_with_distance(self):
        """Distance should add to time."""
        no_distance = estimate_route_time(10, 5, 0.0)
        with_distance = estimate_route_time(10, 5, 30.0)
        assert with_distance > no_distance
    
    def test_time_realistic_route(self):
        """Test realistic route."""
        result = estimate_route_time(
            num_packages=20,
            num_stops=10,
        )
        # Should take 2-3 hours
        assert 90 < result < 180


class TestWorkloadScore:
    """Tests for workload score calculation."""
    
    def test_workload_dict_input(self):
        """Test with dictionary input."""
        route = {
            "num_packages": 20,
            "total_weight_kg": 40.0,
            "route_difficulty_score": 2.0,
            "estimated_time_minutes": 120,
        }
        result = calculate_workload(route)
        assert result > 0
    
    def test_workload_dataclass_input(self):
        """Test with RouteMetrics dataclass input."""
        route = RouteMetrics(
            num_packages=20,
            total_weight_kg=40.0,
            num_stops=10,
            route_difficulty_score=2.0,
            estimated_time_minutes=120,
        )
        result = calculate_workload(route)
        assert result > 0
    
    def test_workload_formula(self):
        """Verify workload formula calculation."""
        route = {
            "num_packages": 10,
            "total_weight_kg": 20.0,
            "route_difficulty_score": 1.0,
            "estimated_time_minutes": 60,
        }
        # Default weights: a=1.0, b=0.5, c=10.0, d=0.2
        # Expected: 1.0*10 + 0.5*20 + 10.0*1 + 0.2*60 = 10 + 10 + 10 + 12 = 42
        result = calculate_workload(route)
        assert abs(result - 42.0) < 0.1
    
    def test_workload_custom_weights(self):
        """Test with custom weights."""
        route = {
            "num_packages": 10,
            "total_weight_kg": 10.0,
            "route_difficulty_score": 1.0,
            "estimated_time_minutes": 60,
        }
        custom_weights = {"a": 2.0, "b": 1.0, "c": 5.0, "d": 0.5}
        # Expected: 2.0*10 + 1.0*10 + 5.0*1 + 0.5*60 = 20 + 10 + 5 + 30 = 65
        result = calculate_workload(route, custom_weights)
        assert abs(result - 65.0) < 0.1
    
    def test_workload_empty_route(self):
        """Empty route should have minimal workload."""
        route = {
            "num_packages": 0,
            "total_weight_kg": 0.0,
            "route_difficulty_score": 0.0,
            "estimated_time_minutes": 0,
        }
        result = calculate_workload(route)
        assert result == 0.0
    
    def test_workload_heavy_route(self):
        """Heavy route should have high workload."""
        route = {
            "num_packages": 50,
            "total_weight_kg": 100.0,
            "route_difficulty_score": 4.0,
            "estimated_time_minutes": 300,
        }
        result = calculate_workload(route)
        # Should be significant
        assert result > 100
    
    def test_workload_comparison(self):
        """Harder routes should have higher workload."""
        easy_route = {
            "num_packages": 10,
            "total_weight_kg": 15.0,
            "route_difficulty_score": 1.0,
            "estimated_time_minutes": 60,
        }
        hard_route = {
            "num_packages": 30,
            "total_weight_kg": 60.0,
            "route_difficulty_score": 3.5,
            "estimated_time_minutes": 180,
        }
        easy_workload = calculate_workload(easy_route)
        hard_workload = calculate_workload(hard_route)
        assert hard_workload > easy_workload