"""P1-A 回归测试: ingest 联赛级 inserted/updated 必须读 leagues[code],而非顶层 r.get("inserted")。 运行: pytest tests/test_p1_a_ingest_league_counts.py -v (纯函数测试,无 DB/网络依赖。) """ from src.api.routes.ingest import _accumulate_ingest_result class TestAccumulateIngestResult: """P1-A: _accumulate_ingest_result 联赛级计数必须来自 r["leagues"][code]。""" def _merged(self): return {"leagues": {}, "total_inserted": 0, "total_updated": 0, "errors": []} def test_league_counts_read_from_leagues_key(self): """核心: 联赛级 inserted/updated 应来自 leagues[code],而非顶层 inserted/updated。""" merged = self._merged() r = { # 顶层无 inserted/updated 键(只有 total_*) "total_inserted": 5, "total_updated": 2, "errors": [], "leagues": {"E0": {"inserted": 3, "updated": 1, "rows": 4, "errors": []}}, } _accumulate_ingest_result(merged, "E0", r) # 顶层总计 assert merged["total_inserted"] == 5 assert merged["total_updated"] == 2 # 联赛级计数来自 leagues["E0"],而非顶层 assert merged["leagues"]["E0"]["inserted"] == 3, "联赛 inserted 必须来自 leagues[code]" assert merged["leagues"]["E0"]["updated"] == 1, "联赛 updated 必须来自 leagues[code]" def test_does_not_read_top_level_inserted(self): """防御: 若 r 误含顶层 inserted 键,不得影响联赛级计数。""" merged = self._merged() r = { "total_inserted": 5, "total_updated": 2, "inserted": 999, # 错误的顶层键(旧代码可能读这个) "updated": 999, "errors": [], "leagues": {"E0": {"inserted": 3, "updated": 1}}, } _accumulate_ingest_result(merged, "E0", r) # 必须忽略顶层 inserted/updated,使用 leagues["E0"] assert merged["leagues"]["E0"]["inserted"] == 3 assert merged["leagues"]["E0"]["updated"] == 1 def test_missing_league_key_defaults_to_zero(self): """r["leagues"] 无该 code 时,默认 0 不抛错。""" merged = self._merged() r = {"total_inserted": 1, "total_updated": 0, "errors": [], "leagues": {}} _accumulate_ingest_result(merged, "E0", r) assert merged["leagues"]["E0"]["inserted"] == 0 assert merged["total_inserted"] == 1 def test_multiple_calls_accumulate(self): """多次调用应累加到同一联赛。""" merged = self._merged() r1 = {"total_inserted": 3, "total_updated": 1, "errors": [], "leagues": {"E0": {"inserted": 3, "updated": 1}}} r2 = {"total_inserted": 2, "total_updated": 0, "errors": [], "leagues": {"E0": {"inserted": 2, "updated": 0}}} _accumulate_ingest_result(merged, "E0", r1) _accumulate_ingest_result(merged, "E0", r2) assert merged["leagues"]["E0"]["inserted"] == 5 assert merged["leagues"]["E0"]["updated"] == 1 assert merged["total_inserted"] == 5