168 lines
5.9 KiB
Python
168 lines
5.9 KiB
Python
def test_canonical_engine_prefers_settlement_station_over_later_nearby_row():
|
|
from web.services.canonical_engine import build_canonical_temperature_from_observations
|
|
|
|
canonical = build_canonical_temperature_from_observations(
|
|
"shenzhen",
|
|
[
|
|
{
|
|
"source": "hko_obs",
|
|
"city": "shenzhen",
|
|
"station_code": "HKO",
|
|
"station_name": "Hong Kong Observatory",
|
|
"value": 27.6,
|
|
"value_unit": "c",
|
|
"observed_at": "2026-06-14T01:00:00+00:00",
|
|
"fetched_at": "2026-06-14T01:05:00+00:00",
|
|
"status": "ok",
|
|
"payload": {"source_label": "HKO"},
|
|
"updated_at_ts": 2000.0,
|
|
},
|
|
{
|
|
"source": "hko_obs",
|
|
"city": "shenzhen",
|
|
"station_code": "LFS",
|
|
"station_name": "Lau Fau Shan",
|
|
"value": 28.1,
|
|
"value_unit": "c",
|
|
"observed_at": "2026-06-14T01:00:00+00:00",
|
|
"fetched_at": "2026-06-14T01:05:00+00:00",
|
|
"status": "ok",
|
|
"payload": {"source_label": "HKO"},
|
|
"updated_at_ts": 1000.0,
|
|
},
|
|
],
|
|
)
|
|
|
|
assert canonical is not None
|
|
assert canonical["city"] == "shenzhen"
|
|
assert canonical["value"] == 28.1
|
|
assert canonical["source"] == "hko_obs"
|
|
assert canonical["source_role"] == "settlement_official"
|
|
assert canonical["station_code"] == "LFS"
|
|
assert canonical["station_name"] == "Lau Fau Shan"
|
|
assert canonical["freshness_status"] == "fresh"
|
|
assert canonical["freshness_sec"] == 300
|
|
|
|
|
|
def test_canonical_engine_ignores_failed_latest_rows():
|
|
from web.services.canonical_engine import build_canonical_temperature_from_observations
|
|
|
|
canonical = build_canonical_temperature_from_observations(
|
|
"qingdao",
|
|
[
|
|
{
|
|
"source": "amsc_awos",
|
|
"city": "qingdao",
|
|
"station_code": "ZSQD",
|
|
"value": None,
|
|
"value_unit": "c",
|
|
"observed_at": "",
|
|
"fetched_at": "2026-06-14T01:05:00+00:00",
|
|
"status": "timeout",
|
|
"payload": {"error": "timeout"},
|
|
"updated_at_ts": 2000.0,
|
|
},
|
|
{
|
|
"source": "madis_hfmetar",
|
|
"city": "qingdao",
|
|
"station_code": "ZSQD",
|
|
"station_name": "Qingdao Jiaodong",
|
|
"value": 24.0,
|
|
"value_unit": "c",
|
|
"observed_at": "2026-06-14T01:00:00+00:00",
|
|
"fetched_at": "2026-06-14T01:05:00+00:00",
|
|
"status": "ok",
|
|
"payload": {"source_label": "MADIS HFMETAR"},
|
|
"updated_at_ts": 1000.0,
|
|
},
|
|
],
|
|
)
|
|
|
|
assert canonical is not None
|
|
assert canonical["source"] == "madis_hfmetar"
|
|
assert canonical["value"] == 24.0
|
|
|
|
|
|
def test_canonical_engine_prefers_mgm_over_metar_for_turkish_city():
|
|
from web.services.canonical_engine import build_canonical_temperature_from_observations
|
|
|
|
canonical = build_canonical_temperature_from_observations(
|
|
"ankara",
|
|
[
|
|
{
|
|
"source": "metar",
|
|
"city": "ankara",
|
|
"station_code": "LTAC",
|
|
"station_name": "Ankara Esenboga",
|
|
"value": 14.0,
|
|
"value_unit": "c",
|
|
"observed_at": "2026-06-15T14:20:00+00:00",
|
|
"fetched_at": "2026-06-15T14:21:00+00:00",
|
|
"status": "ok",
|
|
"payload": {"source_label": "METAR"},
|
|
"updated_at_ts": 10.0,
|
|
},
|
|
{
|
|
"source": "mgm",
|
|
"city": "ankara",
|
|
"station_code": "17128",
|
|
"station_name": "Esenboga Airport",
|
|
"value": 19.0,
|
|
"value_unit": "c",
|
|
"observed_at": "2026-06-15T14:20:00+00:00",
|
|
"fetched_at": "2026-06-15T14:21:00+00:00",
|
|
"status": "ok",
|
|
"payload": {"source_label": "MGM"},
|
|
"updated_at_ts": 9.0,
|
|
},
|
|
],
|
|
)
|
|
|
|
assert canonical is not None
|
|
assert canonical["source"] == "mgm"
|
|
assert canonical["source_label"] == "MGM"
|
|
assert canonical["value"] == 19.0
|
|
|
|
|
|
def test_canonical_engine_builds_realtime_event_from_canonical():
|
|
from web.services.canonical_engine import build_realtime_event_from_canonical
|
|
|
|
event = build_realtime_event_from_canonical(
|
|
{
|
|
"city": "shenzhen",
|
|
"value": 28.1,
|
|
"temp_symbol": "°C",
|
|
"source": "hko_obs",
|
|
"station_code": "LFS",
|
|
"station_name": "Lau Fau Shan",
|
|
"observed_at": "2026-06-14T01:00:00+00:00",
|
|
"freshness_sec": 300,
|
|
"freshness_status": "fresh",
|
|
"confidence": 0.9,
|
|
"max_so_far": 28.6,
|
|
"signed_gap": 1.2,
|
|
"gap_to_target": -1.2,
|
|
"touch_distance": 0.0,
|
|
"edge": 0.07,
|
|
"edge_percent": 7.0,
|
|
}
|
|
)
|
|
|
|
assert event is not None
|
|
assert event["type"] == "city_observation_patch.v1"
|
|
assert event["city"] == "shenzhen"
|
|
assert event["source"] == "hko_obs"
|
|
assert event["obs_time"] == "2026-06-14T01:00:00Z"
|
|
assert event["payload"]["temp"] == 28.1
|
|
assert event["payload"]["station_code"] == "LFS"
|
|
assert event["payload"]["station_label"] == "Lau Fau Shan"
|
|
assert event["payload"]["unit"] == "celsius"
|
|
assert event["payload"]["freshness_status"] == "fresh"
|
|
assert event["payload"]["confidence"] == 0.9
|
|
assert event["payload"]["max_so_far"] == 28.6
|
|
assert event["payload"]["signed_gap"] == 1.2
|
|
assert event["payload"]["gap_to_target"] == -1.2
|
|
assert event["payload"]["touch_distance"] == 0.0
|
|
assert event["payload"]["edge"] == 0.07
|
|
assert event["payload"]["edge_percent"] == 7.0
|