from pathlib import Path import pytest from core.basic.character import createCharacter from core.basic.equipment import get_equipment CHARACTER_ROOT = Path(__file__).resolve().parents[2] / "core" / "character" / "GF" DEFAULT_ALTER = "GF.swordman_male.weapon_master" RESULT_KEYS = {"uuid", "skills", "info", "suits", "buffer"} EQUIP_PARTS = { "武器", "副武器", "称号", "上衣", "头肩", "下装", "腰带", "鞋", "手镯", "项链", "戒指", "辅助装备", "魔法石", "耳环", } KNOWN_BROKEN_ALTERS = { } def _discover_alters() -> list[str]: alters = [] for path in sorted(CHARACTER_ROOT.rglob("*.py")): if path.name == "__init__.py": continue text = path.read_text(encoding="utf-8") if "classChange" not in text: continue relative = path.relative_to(CHARACTER_ROOT).with_suffix("") alters.append("GF." + ".".join(relative.parts)) return alters def _character_params(): params = [] for alter in _discover_alters(): marks = [] if alter in KNOWN_BROKEN_ALTERS: marks.append(pytest.mark.xfail(reason=KNOWN_BROKEN_ALTERS[alter], strict=True)) params.append(pytest.param(alter, id=alter, marks=marks)) return params def _equipment_part(equ) -> str | None: if equ.itemType == "武器": return "武器" if equ.itemDetailType in EQUIP_PARTS: return equ.itemDetailType return None def _equipment_params(): params = [] for equ in get_equipment("0").equs: part = _equipment_part(equ) if part is None: continue params.append(pytest.param(equ, part, id=f"{part}:{equ.id}:{equ.name}")) return params def _assert_calc_result_shape(result: dict): assert isinstance(result, dict) assert RESULT_KEYS.issubset(result) assert isinstance(result["skills"], list) assert isinstance(result["info"], list) @pytest.mark.parametrize("alter", _character_params()) def test_all_gf_characters_can_calculate_with_minimal_config(alter, minimal_calc_config): character = createCharacter(alter, "0") assert character is not None, f"createCharacter returned None for alter={alter}" _assert_calc_result_shape(character.calc(minimal_calc_config)) @pytest.mark.parametrize(("equ", "part"), _equipment_params()) def test_all_equipment_can_calculate_when_equipped_once(equ, part, minimal_calc_config): config = minimal_calc_config.copy() config["equips"] = { part: value.copy() for part, value in minimal_calc_config["equips"].items() } config["equips"][part] = { **config["equips"][part], "id": equ.id, } character = createCharacter(DEFAULT_ALTER, "0") assert character is not None _assert_calc_result_shape(character.calc(config))