89 lines
2.6 KiB
Python
89 lines
2.6 KiB
Python
|
|
import pytest
|
||
|
|
from unittest.mock import MagicMock, patch
|
||
|
|
import sys
|
||
|
|
from app.services.routing_optimizer import RoutingOptimizer
|
||
|
|
|
||
|
|
# Mock OR-Tools if not installed in the test environment
|
||
|
|
try:
|
||
|
|
from ortools.constraint_solver import routing_enums_pb2
|
||
|
|
from ortools.constraint_solver import pywrapcp
|
||
|
|
HAS_ORTOOLS = True
|
||
|
|
except ImportError:
|
||
|
|
HAS_ORTOOLS = False
|
||
|
|
|
||
|
|
@pytest.mark.asyncio
|
||
|
|
async def test_routing_optimizer_initialization():
|
||
|
|
optimizer = RoutingOptimizer()
|
||
|
|
assert optimizer.has_ortools == HAS_ORTOOLS
|
||
|
|
|
||
|
|
@pytest.mark.asyncio
|
||
|
|
async def test_optimize_daily_routes_fallback():
|
||
|
|
# Force fallback by mocking has_ortools to False
|
||
|
|
optimizer = RoutingOptimizer()
|
||
|
|
optimizer.has_ortools = False
|
||
|
|
|
||
|
|
depot_location = (40.7128, -74.0060) # NYC
|
||
|
|
deliveries = [
|
||
|
|
{
|
||
|
|
'id': 'd1',
|
||
|
|
'location': (40.730610, -73.935242), # Brooklyn
|
||
|
|
'weight_kg': 100
|
||
|
|
},
|
||
|
|
{
|
||
|
|
'id': 'd2',
|
||
|
|
'location': (40.758896, -73.985130), # Times Square
|
||
|
|
'weight_kg': 50
|
||
|
|
}
|
||
|
|
]
|
||
|
|
|
||
|
|
result = await optimizer.optimize_daily_routes(deliveries, depot_location)
|
||
|
|
|
||
|
|
assert result['status'] == 'success'
|
||
|
|
assert result['algorithm_used'] == 'fallback_sequential'
|
||
|
|
assert len(result['routes']) == 1
|
||
|
|
assert len(result['routes'][0]['stops']) == 4 # Start + 2 deliveries + End
|
||
|
|
|
||
|
|
@pytest.mark.asyncio
|
||
|
|
async def test_optimize_daily_routes_vrp():
|
||
|
|
if not HAS_ORTOOLS:
|
||
|
|
pytest.skip("OR-Tools not installed")
|
||
|
|
|
||
|
|
optimizer = RoutingOptimizer()
|
||
|
|
|
||
|
|
depot_location = (40.7128, -74.0060) # NYC
|
||
|
|
deliveries = [
|
||
|
|
{
|
||
|
|
'id': 'd1',
|
||
|
|
'location': (40.730610, -73.935242), # Brooklyn
|
||
|
|
'weight_kg': 100
|
||
|
|
},
|
||
|
|
{
|
||
|
|
'id': 'd2',
|
||
|
|
'location': (40.758896, -73.985130), # Times Square
|
||
|
|
'weight_kg': 50
|
||
|
|
},
|
||
|
|
{
|
||
|
|
'id': 'd3',
|
||
|
|
'location': (40.7829, -73.9654), # Central Park
|
||
|
|
'weight_kg': 200
|
||
|
|
}
|
||
|
|
]
|
||
|
|
|
||
|
|
# Run optimization
|
||
|
|
result = await optimizer.optimize_daily_routes(deliveries, depot_location)
|
||
|
|
|
||
|
|
assert result['status'] == 'success'
|
||
|
|
assert result['algorithm_used'] == 'ortools_vrp'
|
||
|
|
assert len(result['routes']) >= 1
|
||
|
|
|
||
|
|
# Check if all deliveries are covered
|
||
|
|
delivery_ids = []
|
||
|
|
for route in result['routes']:
|
||
|
|
for stop in route['stops']:
|
||
|
|
if 'delivery_id' in stop and not stop.get('location') == 'depot':
|
||
|
|
delivery_ids.append(stop['delivery_id'])
|
||
|
|
|
||
|
|
assert 'd1' in delivery_ids
|
||
|
|
assert 'd2' in delivery_ids
|
||
|
|
assert 'd3' in delivery_ids
|