feat: 增加小区经纬度匹配
This commit is contained in:
+70
-1
@@ -27,6 +27,7 @@ class PipelineTest(unittest.TestCase):
|
||||
for source_type in main.EXPECTED_TYPES:
|
||||
create_archive(root, source_type, COMPLETE_WINDOW)
|
||||
create_archive(root, main.EXPECTED_TYPES[0], INCOMPLETE_WINDOW)
|
||||
create_cell_data_sources(root)
|
||||
store = RecordingStore()
|
||||
|
||||
result = main.process(main.LocalSource(root), output, lookback_days=3, store=store)
|
||||
@@ -37,17 +38,26 @@ class PipelineTest(unittest.TestCase):
|
||||
with (result / f"interference_summary_{COMPLETE_WINDOW}.csv").open(encoding="utf-8-sig", newline="") as file:
|
||||
rows = list(csv.DictReader(file))
|
||||
self.assertEqual(len(rows), 7)
|
||||
self.assertEqual(list(rows[0]), ["hour_start", "hour_end", "cgi", "cell_name", "interference_dbm"])
|
||||
self.assertEqual(
|
||||
list(rows[0]),
|
||||
["hour_start", "hour_end", "cgi", "cell_name", "interference_dbm", "longitude", "latitude"],
|
||||
)
|
||||
rows_by_type = {row["cell_name"].removesuffix("-小区"): row for row in rows}
|
||||
self.assertEqual(rows_by_type["5G干扰监控"]["cgi"], "460-00-200-1")
|
||||
self.assertEqual(rows_by_type["700M干扰监控"]["cgi"], "460-00-200-1")
|
||||
for source_type in set(main.EXPECTED_TYPES) - {"5G干扰监控", "700M干扰监控"}:
|
||||
self.assertEqual(rows_by_type[source_type]["cgi"], "460-00-100-1")
|
||||
self.assertTrue(all(row["interference_dbm"] == "-100.5" for row in rows))
|
||||
self.assertEqual(rows_by_type["5G干扰监控"]["longitude"], "113.123456")
|
||||
self.assertEqual(rows_by_type["5G干扰监控"]["latitude"], "22.654321")
|
||||
self.assertTrue(all(not row["longitude"] and not row["latitude"] for row in rows if row["cgi"] == "460-00-100-1"))
|
||||
|
||||
manifest = json.loads((result / "manifest.json").read_text(encoding="utf-8"))
|
||||
self.assertEqual(manifest["source_file_count"], 7)
|
||||
self.assertEqual(manifest["cell_data_file_count"], 5)
|
||||
self.assertEqual(manifest["summary_rows"], 7)
|
||||
self.assertEqual(manifest["coordinate_matched_rows"], 2)
|
||||
self.assertEqual(manifest["coordinate_unmatched_rows"], 5)
|
||||
self.assertEqual(len(manifest["warnings"]), 1)
|
||||
self.assertIn(INCOMPLETE_WINDOW, manifest["warnings"][0])
|
||||
self.assertNotIn("source_types", manifest)
|
||||
@@ -78,6 +88,30 @@ class PipelineTest(unittest.TestCase):
|
||||
("2026-07-30 23:00:00", "2026-07-31 00:00:00"),
|
||||
)
|
||||
|
||||
def test_latest_dated_cell_data_file_is_selected(self) -> None:
|
||||
entries = [
|
||||
{"name": "江门5G小区信息表20260727.xlsx", "path": "/old.xlsx", "is_dir": False},
|
||||
{"name": "江门5G小区信息表20260728.xlsx", "path": "/latest.xlsx", "is_dir": False},
|
||||
{"name": "说明.txt", "path": "/说明.txt", "is_dir": False},
|
||||
]
|
||||
|
||||
selected = main.select_latest_cell_data_file(entries, "/cell-data")
|
||||
|
||||
self.assertEqual(selected["path"], "/latest.xlsx")
|
||||
|
||||
def test_cell_data_schema_change_is_rejected(self) -> None:
|
||||
raw = create_cell_data_workbook(include_latitude=False)
|
||||
|
||||
with self.assertRaisesRegex(main.ProcessingError, "missing columns.*纬度"):
|
||||
main.parse_cell_data_workbook(raw, "bad.xlsx")
|
||||
|
||||
def test_conflicting_cell_data_coordinates_are_rejected(self) -> None:
|
||||
first = create_cell_data_workbook(longitude=113.1)
|
||||
second = create_cell_data_workbook(longitude=113.2)
|
||||
|
||||
with self.assertRaisesRegex(main.ProcessingError, "Conflicting CellData coordinates"):
|
||||
main.load_cell_coordinates([("first.xlsx", first), ("second.xlsx", second)])
|
||||
|
||||
def test_mysql_store_replaces_same_hour_and_deletes_other_hours(self) -> None:
|
||||
connection = FakeConnection(datetime(2026, 7, 31, 10), same_hour_rows=7, old_rows=20)
|
||||
store = main.MySQLSummaryStore(connect_factory=lambda: connection)
|
||||
@@ -89,11 +123,15 @@ class PipelineTest(unittest.TestCase):
|
||||
self.assertEqual(result["refreshed_rows"], 7)
|
||||
self.assertEqual(result["old_rows_deleted"], 20)
|
||||
self.assertEqual(connection.cursor_instance.inserted[0][0], datetime(2026, 7, 31, 10))
|
||||
self.assertIsNone(connection.cursor_instance.inserted[0][4])
|
||||
self.assertIsNone(connection.cursor_instance.inserted[0][5])
|
||||
self.assertTrue(connection.committed)
|
||||
self.assertFalse(connection.rolled_back)
|
||||
self.assertTrue(connection.closed)
|
||||
self.assertNotIn("source_type", " ".join(connection.cursor_instance.queries))
|
||||
self.assertNotIn("source_path", " ".join(connection.cursor_instance.queries))
|
||||
self.assertTrue(any("ADD COLUMN `longitude`" in query for query in connection.cursor_instance.queries))
|
||||
self.assertTrue(any("ADD COLUMN `latitude`" in query for query in connection.cursor_instance.queries))
|
||||
|
||||
def test_mysql_store_refuses_to_replace_a_newer_hour(self) -> None:
|
||||
connection = FakeConnection(datetime(2026, 7, 31, 11))
|
||||
@@ -169,6 +207,9 @@ class FakeCursor:
|
||||
def fetchone(self) -> tuple[datetime | None]:
|
||||
return (self.latest_time,)
|
||||
|
||||
def fetchall(self) -> list[tuple[str]]:
|
||||
return [(name,) for name in ("metric_time", "cgi", "cell_name", "interference_dbm")]
|
||||
|
||||
def close(self) -> None:
|
||||
self.closed = True
|
||||
|
||||
@@ -224,6 +265,8 @@ def database_row() -> dict[str, str]:
|
||||
"cgi": "460-00-200-1",
|
||||
"cell_name": "测试小区",
|
||||
"interference_dbm": "-100.5",
|
||||
"longitude": "",
|
||||
"latitude": "",
|
||||
}
|
||||
|
||||
|
||||
@@ -273,5 +316,31 @@ def mock_row(source_type: str, window: str) -> list[object]:
|
||||
return [values[column] for column in header]
|
||||
|
||||
|
||||
def create_cell_data_sources(root: Path) -> None:
|
||||
raw = create_cell_data_workbook()
|
||||
for index, configured_directory in enumerate(main.CELL_DATA_DIRECTORIES, start=1):
|
||||
directory = root / Path(configured_directory.lstrip("/"))
|
||||
directory.mkdir(parents=True, exist_ok=True)
|
||||
(directory / f"江门小区信息表{index}-20260728.xlsx").write_bytes(raw)
|
||||
|
||||
|
||||
def create_cell_data_workbook(longitude: float = 113.123456, include_latitude: bool = True) -> bytes:
|
||||
workbook = Workbook()
|
||||
sheet = workbook.active
|
||||
sheet.title = "小区信息表"
|
||||
header = ["小区名称", "eNB/gNB", "CI", "经度"]
|
||||
if include_latitude:
|
||||
header.append("纬度")
|
||||
sheet.append(header)
|
||||
row: list[object] = ["测试小区", 200, 1, longitude]
|
||||
if include_latitude:
|
||||
row.append(22.654321)
|
||||
sheet.append(row)
|
||||
content = io.BytesIO()
|
||||
workbook.save(content)
|
||||
workbook.close()
|
||||
return content.getvalue()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
||||
Reference in New Issue
Block a user