"""app.utils.meituan_city.get_meituan_city 经纬度→美团城市 反查测试。 覆盖 get_meituan_city 的分支(test_geo.py 只覆盖底层 get_city): - 主要城市 → 正确省份 + 非空 city_id(+ 直辖市/省会命中中文城市名) - 非中国境内坐标 → city_id 为空(接口据此降级返空) - 返回 dict 结构 / 类型 - 坐标量化(~1km)后近点命中同一缓存结果 - 返回的是缓存副本(调用方原地修改不污染缓存) """ from __future__ import annotations import pytest from app.utils.meituan_city import get_meituan_city # (标签, 纬度, 经度, 期望省份名, 期望城市名) _CASES = [ ("北京", 39.9042, 116.4074, "北京市", "北京市"), ("上海", 31.2304, 121.4737, "上海市", "上海市"), ("广州", 23.1291, 113.2644, "广东省", "广州市"), ("深圳", 22.5431, 114.0579, "广东省", "深圳市"), ("成都", 30.5728, 104.0668, "四川省", "成都市"), ("杭州", 30.2741, 120.1551, "浙江省", "杭州市"), ("武汉", 30.5928, 114.3055, "湖北省", "武汉市"), ("郑州", 34.7466, 113.6253, "河南省", "郑州市"), ("厦门", 24.4798, 118.0894, "福建省", "厦门市"), ("青岛", 36.0671, 120.3826, "山东省", "青岛市"), ] @pytest.mark.parametrize("label,lat,lon,exp_province,exp_city", _CASES) def test_major_city_resolves(label: str, lat: float, lon: float, exp_province: str, exp_city: str) -> None: r = get_meituan_city(lat, lon) assert r["province_name"] == exp_province, f"{label}: province {r!r}" assert r["city_name"] == exp_city, f"{label}: city {r!r}" assert r["city_id"], f"{label}: city_id 不应为空 {r!r}" def test_non_china_returns_empty_city_id() -> None: """境外/远洋坐标 → city_id 空(接口据此返回 degraded 空列表)。""" r = get_meituan_city(0.0, -140.0) # 太平洋中部 assert r["city_id"] == "", f"境外不应给出 city_id: {r!r}" def test_return_shape_and_types() -> None: r = get_meituan_city(39.9042, 116.4074) for key in ("city_id", "city_name", "province_name"): assert key in r and isinstance(r[key], str) def test_quantized_coords_hit_same_result() -> None: """相距 <1km(round 到 2 位小数后相同)的两点应解析出同一城市。""" a = get_meituan_city(39.9042, 116.4074) b = get_meituan_city(39.9031, 116.4066) # round 后同为 (39.90, 116.41) assert a == b def test_result_is_defensive_copy() -> None: """返回的是缓存副本:原地修改不应污染后续查询。""" first = get_meituan_city(31.2304, 121.4737) first["city_id"] = "TAMPERED" second = get_meituan_city(31.2304, 121.4737) assert second["city_id"] != "TAMPERED"