fix:批量修复了一些问题

This commit is contained in:
shangfangjian
2026-09-19 22:51:35 +08:00
parent 835d7217d0
commit 8e6ad5394e
44 changed files with 4921 additions and 395 deletions
+176
View File
@@ -0,0 +1,176 @@
"""测试 bzzoiro 事件规范化:基于 fixtures/bzzoiro_event.json 的真实字段映射。
运行(需先 pip-sync requirements-dev.txt):
pytest tests/test_bzzoiro_normalize.py -v
若真实 bzzoiro 字段名与样例不同,断言会失败 —— 这正是本测试的目的:
锁定 normalize_bzzoiro 所依赖的字段名,避免上游静默变更导致数据丢失。
"""
from __future__ import annotations
import json
from pathlib import Path
import pytest
from src.data.config import LEAGUE_NAMES
from src.data.normalize import normalize_bzzoiro
FIXTURE_DIR = Path(__file__).resolve().parent / "fixtures"
def load_event() -> dict:
with open(FIXTURE_DIR / "bzzoiro_event.json", encoding="utf-8") as f:
return json.load(f)
class TestBzzoiroNormalize:
"""验证 normalize_bzzoiro 对 fixture 样例的解析结果。"""
def test_basic_fields(self):
"""基础字段:日期、状态、对阵、进球。"""
m = normalize_bzzoiro(load_event(), "E0")
assert m is not None
assert m.home_team == "Home United FC"
assert m.away_team == "Away City FC"
assert m.match_status == "finished"
assert m.home_goals == 2
assert m.away_goals == 1
assert m.home_ht_goals == 1
assert m.away_ht_goals == 0
def test_shots_mapping(self):
"""射门数映射到 home_shots / away_shots。"""
m = normalize_bzzoiro(load_event(), "E0")
assert m.home_shots == 14
assert m.away_shots == 8
def test_shots_on_target_mapping(self):
"""射正数映射到 home_shots_on_target / away_shots_on_target。"""
m = normalize_bzzoiro(load_event(), "E0")
assert m.home_shots_on_target == 5
assert m.away_shots_on_target == 3
def test_corners_mapping(self):
"""角球映射。"""
m = normalize_bzzoiro(load_event(), "E0")
assert m.home_corners == 6
assert m.away_corners == 4
def test_possession_mapping(self):
"""控球率:API 提供 home 值。"""
m = normalize_bzzoiro(load_event(), "E0")
assert m.home_possession == 58.5
def test_xg_mapping(self):
"""xG 映射到 home_xg / away_xg。"""
m = normalize_bzzoiro(load_event(), "E0")
assert m.home_xg == 1.85
assert m.away_xg == 0.92
def test_cards_mapping(self):
"""黄牌、红牌映射。"""
m = normalize_bzzoiro(load_event(), "E0")
assert m.home_yellow_cards == 2
assert m.away_yellow_cards == 3
assert m.home_red_cards == 0
assert m.away_red_cards == 0
def test_fallback_aliases(self):
"""回退别名:shots_home → home_shots, xg_home → home_xg。"""
raw = {
"event_date": "2026-09-12T19:00:00+00:00",
"status": "finished",
"home_team": "FC Alpha",
"away_team": "FC Beta",
"home_goals": 1,
"away_goals": 1,
"shots_home": 10, "shots_away": 5,
"sot_home": 4, "sot_away": 2,
"corners_home": 3, "corners_away": 2,
"possession": 55.0,
"xg_home": 1.2, "xg_away": 0.8,
"yellow_cards_home": 1, "yellow_cards_away": 2,
"red_cards_home": 0, "red_cards_away": 1,
}
m = normalize_bzzoiro(raw, "SP1")
assert m is not None
assert m.home_shots == 10
assert m.away_shots == 5
assert m.home_shots_on_target == 4
assert m.away_shots_on_target == 2
assert m.home_corners == 3
assert m.away_corners == 2
assert m.home_possession == 55.0
assert m.home_xg == 1.2
assert m.away_xg == 0.8
assert m.home_yellow_cards == 1
assert m.away_yellow_cards == 2
assert m.home_red_cards == 0
assert m.away_red_cards == 1
def test_missing_stats_still_normalizes(self):
"""缺少统计字段时仍应解析基础数据,统计字段为 None(不伪造)。"""
raw = {
"event_date": "2026-09-12T19:00:00+00:00",
"status": "finished",
"home_team": "FC One",
"away_team": "FC Two",
"home_goals": 3,
"away_goals": 0,
}
m = normalize_bzzoiro(raw, "D1")
assert m is not None
assert m.home_goals == 3
assert m.away_goals == 0
# 无数据字段保持 None,不伪造
assert m.home_shots is None
assert m.home_xg is None
assert m.home_possession is None
def test_unknown_status_drops(self):
"""未知状态 → 丢弃(None)。"""
raw = {
"event_date": "2026-09-12T19:00:00+00:00",
"status": "weird_status",
"home_team": "A",
"away_team": "B",
}
assert normalize_bzzoiro(raw, "E0") is None
def test_invalid_date_drops(self):
"""无效日期 → 丢弃(None)。"""
raw = {
"event_date": "not-a-date",
"status": "finished",
"home_team": "A",
"away_team": "B",
"home_goals": 1,
"away_goals": 0,
}
assert normalize_bzzoiro(raw, "E0") is None
def test_same_team_drops(self):
"""主客队同名(规范化后) → 丢弃(None)。"""
raw = {
"event_date": "2026-09-12T19:00:00+00:00",
"status": "finished",
"home_team": "Same FC",
"away_team": "Same FC",
"home_goals": 1,
"away_goals": 0,
}
assert normalize_bzzoiro(raw, "E0") is None
# ── 真实响应校验(占位,待替换后取消 skip) ─────────────────────────
@pytest.mark.skip(reason="待提供真实 bzzoiro event 响应后替换 fixture 并取消 skip")
def test_real_response_matches_fixture_structure():
"""真实响应应能被 fixture 结构覆盖(字段名一致)。"""
# 真实响应粘贴于此,验证 normalize_bzzoiro 解析成功
real_response = {}
if not real_response:
pytest.skip("未提供真实响应")
m = normalize_bzzoiro(real_response, "E0")
assert m is not None