diff --git a/main/xiaozhi-server/tests/conftest.py b/main/xiaozhi-server/tests/conftest.py index cb3a0ccc1..2bbb4929c 100644 --- a/main/xiaozhi-server/tests/conftest.py +++ b/main/xiaozhi-server/tests/conftest.py @@ -453,6 +453,27 @@ if not LIVE_API_TESTS: import pytest # noqa: E402 (after conftest hooks so pytest is initialised) +def is_ci() -> bool: + """GitHub Actions 上会带 CI=true""" + value = os.environ.get("CI") + if value is None: + return False + trimmed = value.strip() + return bool(trimmed) and trimmed.lower() != "false" + + +def skip_or_fail(reason: str) -> None: + """本地缺东西就跳过,CI 里缺东西直接让 job 挂掉。 + + 口径跟 manager-api 那边的 IntegrationTestEnvironment 一致:本地没起依赖的 + 机器上跳过就行,不该把构建从绿变成红;CI 里依赖必须真的在,缺了就失败, + 不许静默跳过 —— 静默跳过等于门禁被掏空,还看不出来。 + """ + if is_ci(): + raise RuntimeError(f"CI 环境里{reason},这条用例必须真的跑起来,不能跳过") + pytest.skip(reason) + + def pytest_collection_modifyitems(config, items): """Mock 模式下:``live_api`` 标记的用例要真凭据或真网络,不收,并列出是哪几条。 diff --git a/main/xiaozhi-server/tests/test_llm.py b/main/xiaozhi-server/tests/test_llm.py index 69224f5a4..81b9a0faf 100644 --- a/main/xiaozhi-server/tests/test_llm.py +++ b/main/xiaozhi-server/tests/test_llm.py @@ -32,6 +32,7 @@ from tests.conftest import ( get_provider_type, get_selected_provider_name, has_real_key, + skip_or_fail, ) sys.path.insert(0, str(Path(__file__).resolve().parent.parent)) @@ -111,10 +112,10 @@ def _mock_chat_completions(monkeypatch): def _build_provider(): name = get_selected_provider_name("LLM") if not name: - pytest.skip("selected_module.LLM 未设置") + skip_or_fail("selected_module.LLM 未设置") cfg = get_provider_config("LLM", name) if not cfg: - pytest.skip(f"LLM provider '{name}' 配置缺失") + skip_or_fail(f"LLM provider '{name}' 配置缺失") # 任何模式下:key 是占位符 → 真请求没法发。mock 模式有假接口顶上, # 但占位符本身是中文,httpx 拼 Authorization 头的时候会直接报编码错, @@ -123,19 +124,19 @@ def _build_provider(): if any(x in cfg.get("bot_id", "") for x in ["你的"]) or any( x in cfg.get("user_id", "") for x in ["你的"] ): - pytest.skip("LLM 'CozeLLM' 的 bot_id/user_id 未配置") + skip_or_fail("LLM 'CozeLLM' 的 bot_id/user_id 未配置") elif name == "Ollama": if not cfg.get("model_name"): - pytest.skip("LLM 'Ollama' 的 model_name 未配置") + skip_or_fail("LLM 'Ollama' 的 model_name 未配置") elif not has_real_key(cfg, "api_key"): if LIVE_API_TESTS: - pytest.skip(f"LLM '{name}' 的 api_key 未配置") + skip_or_fail(f"LLM '{name}' 的 api_key 未配置") cfg = dict(cfg) cfg["api_key"] = "mock-api-key" ptype = get_provider_type("LLM", name) if not ptype: - pytest.skip(f"LLM '{name}' 的 type 字段缺失") + skip_or_fail(f"LLM '{name}' 的 type 字段缺失") from core.utils.llm import create_instance return create_instance(ptype, cfg)