Files
lingniu-vehicle-ingest/vehicle-map/tests/test_server.py
T

90 lines
4.5 KiB
Python

import importlib.util
from pathlib import Path
import tempfile
import unittest
from unittest.mock import patch
SPEC = importlib.util.spec_from_file_location("vehicle_map_server", Path(__file__).parents[1] / "server.py")
server = importlib.util.module_from_spec(SPEC)
SPEC.loader.exec_module(server)
class DashboardTest(unittest.TestCase):
def test_dashboard_aggregates_public_vehicle_and_station_data(self):
def fake_post(path, body):
if path.endswith("realtime/query"):
return [
{"vin": "VIN1", "motionStatus": "driving", "speedKmh": 18, "activeToday": True, "online": True},
{"vin": "VIN2", "motionStatus": "idle", "speedKmh": 0, "activeToday": True, "online": True},
{"vin": "VIN3", "motionStatus": "offline", "speedKmh": 0, "activeToday": False, "online": False},
]
if path.endswith("mileage/query"):
return [
{"vin": "VIN1", "status": "NORMAL", "dailyMileageKm": 12.345},
{"vin": "VIN2", "status": "NORMAL", "dailyMileageKm": 7.655},
{"vin": "VIN3", "status": "NO_DATA", "dailyMileageKm": None},
]
if path.endswith("hydrogen-stations/query"):
return [{"id": "1", "cooperative": True}, {"id": "2", "cooperative": False}]
raise AssertionError(path)
with patch.object(server, "_post_open_platform", side_effect=fake_post):
with patch.object(server, "_cache", {}):
result = server._load_dashboard()
self.assertEqual(result["summary"]["totalVehicles"], 3)
self.assertEqual(result["summary"]["onlineVehicles"], 2)
self.assertEqual(result["summary"]["drivingVehicles"], 1)
self.assertEqual(result["summary"]["todayMileageKm"], 20.0)
self.assertEqual(result["summary"]["totalStations"], 2)
self.assertEqual(result["summary"]["cooperativeStations"], 1)
self.assertEqual(result["vehicles"][0]["dailyMileageKm"], 12.345)
self.assertEqual(result["vehicles"][2]["dailyMileageKm"], 0)
def test_static_asset_version_is_a_content_fingerprint(self):
self.assertEqual(len(server.STATIC_ASSET_VERSION), 16)
self.assertRegex(server.STATIC_ASSET_VERSION, r"^[0-9a-f]{16}$")
index_template = (Path(__file__).parents[1] / "index.html").read_text(encoding="utf-8")
self.assertEqual(index_template.count("__ASSET_VERSION__"), 2)
def test_default_cache_window_is_two_minutes(self):
self.assertEqual(server.DASHBOARD_CACHE_SECONDS, 120)
self.assertEqual(server.STATION_CACHE_SECONDS, 120)
def test_cache_reuses_dashboard_snapshot_within_window(self):
calls = []
with patch.object(server, "_cache", {}):
first = server._cached("dashboard", 120, lambda: calls.append("load") or {"version": 1})
second = server._cached("dashboard", 120, lambda: calls.append("load") or {"version": 2})
self.assertEqual(calls, ["load"])
self.assertEqual(first, second)
def test_station_region_comes_from_gps_reverse_geocode_and_persists_by_coordinate(self):
station = {
"longitude": 113.200001,
"latitude": 23.100001,
"province": "错误省份",
"city": "错误城市",
"district": "错误区县",
}
with tempfile.TemporaryDirectory() as directory:
cache_path = Path(directory) / "station-geocode.json"
with patch.object(server, "STATION_GEOCODE_CACHE_PATH", cache_path), \
patch.object(server, "_station_geocode_cache", None), \
patch.object(server, "_station_geocode_cache_dirty", False), \
patch.object(server, "_reverse_geocode_station", return_value={
"province": "广东省", "city": "广州市", "district": "黄埔区", "adcode": "440112"
}) as reverse:
first = server._stations_with_gps_regions([station])[0]
second = server._stations_with_gps_regions([dict(station, province="仍然错误")])[0]
self.assertEqual(first["province"], "广东省")
self.assertEqual(first["city"], "广州市")
self.assertEqual(first["district"], "黄埔区")
self.assertEqual(second["province"], "广东省")
self.assertEqual(reverse.call_count, 1)
self.assertTrue(cache_path.exists())
if __name__ == "__main__":
unittest.main()