99520c69d7
1.新增后端测试 2.增加了后端的加密 3.增加了i18n(国际化)
88 lines
3.5 KiB
Python
88 lines
3.5 KiB
Python
"""Pytest 全局 fixture:把 Ray Actor 句柄、PostgresDatabase、loguru 等重副作用模块替换成可控的 stub。"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import sys
|
|
import types
|
|
from typing import Any, Dict, Optional
|
|
from unittest.mock import AsyncMock, MagicMock
|
|
|
|
import pytest
|
|
|
|
|
|
# ─────────────────────────────────────────────────────────────────────────────
|
|
# Ray actor 句柄存根:测试期不真正连 Ray,由 conftest 注入名字 -> AsyncMock 句柄
|
|
# ─────────────────────────────────────────────────────────────────────────────
|
|
|
|
|
|
class _FakeActorRegistry:
|
|
"""模拟 ``ray.get_actor`` 行为:测试可往里塞名字 -> AsyncMock。"""
|
|
|
|
def __init__(self) -> None:
|
|
self._actors: Dict[str, Any] = {}
|
|
|
|
def register(self, name: str, handle: Any) -> None:
|
|
self._actors[name] = handle
|
|
|
|
def get(self, name: str, namespace: str = "kilostar"): # noqa: ARG002
|
|
if name not in self._actors:
|
|
raise ValueError(f"FakeActorRegistry: actor {name!r} not registered")
|
|
return self._actors[name]
|
|
|
|
def clear(self) -> None:
|
|
self._actors.clear()
|
|
|
|
|
|
@pytest.fixture
|
|
def fake_actors(monkeypatch) -> _FakeActorRegistry:
|
|
"""把 ``kilostar.utils.ray_hook._get_cached_actor_handle`` 的实现替换为 fake registry。
|
|
|
|
用法::
|
|
|
|
def test_xxx(fake_actors):
|
|
gsm = AsyncMock()
|
|
gsm.get_tool_config.remote = AsyncMock(return_value={"api_key": "k"})
|
|
fake_actors.register("global_state_machine", types.SimpleNamespace(global_state_machine=gsm))
|
|
"""
|
|
registry = _FakeActorRegistry()
|
|
|
|
from kilostar.utils import ray_hook
|
|
|
|
ray_hook.clear_actor_cache()
|
|
original = ray_hook._get_cached_actor_handle
|
|
|
|
def _stub(actor_name: str):
|
|
return registry.get(actor_name)
|
|
|
|
_stub.cache_clear = lambda: None # type: ignore[attr-defined]
|
|
monkeypatch.setattr(ray_hook, "_get_cached_actor_handle", _stub)
|
|
yield registry
|
|
registry.clear()
|
|
monkeypatch.setattr(ray_hook, "_get_cached_actor_handle", original)
|
|
ray_hook.clear_actor_cache()
|
|
|
|
|
|
@pytest.fixture
|
|
def gsm_handle(fake_actors) -> MagicMock:
|
|
"""快捷 fixture:注册一个名为 ``global_state_machine`` 的 actor,返回其内部 mock。
|
|
|
|
内部 mock 的方法默认全部是 ``AsyncMock``,调用 ``.remote(...)`` 会按 AsyncMock 规则返回。
|
|
"""
|
|
gsm = MagicMock()
|
|
container = types.SimpleNamespace(global_state_machine=gsm)
|
|
fake_actors.register("global_state_machine", container)
|
|
return gsm
|
|
|
|
|
|
# ─────────────────────────────────────────────────────────────────────────────
|
|
# 工具:构造一个 ``MCP_AVAILABLE`` 关闭的 mcp_helper 状态
|
|
# ─────────────────────────────────────────────────────────────────────────────
|
|
|
|
|
|
@pytest.fixture
|
|
def mcp_unavailable(monkeypatch):
|
|
from kilostar.utils import mcp_helper
|
|
|
|
monkeypatch.setattr(mcp_helper, "_MCP_AVAILABLE", False)
|
|
yield
|