Files
hunjing/backend/tests/services/test_character_template_config.py
T
2026-08-21 16:00:13 +08:00

136 lines
5.2 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""人物模板配置加载与 Config→DB 同步测试。"""
from __future__ import annotations
import pytest
from app.core.config import settings
from app.db.session import AsyncSessionLocal
from app.repositories import characters as character_repo
from app.repositories.json_utils import loads_dict
from app.services.character_templates import get_default_template, load_character_templates
def test_load_templates_from_example():
""".example.yaml 加载成功且含 default 模板。"""
templates = load_character_templates()
assert "default" in templates
cfg = templates["default"]
assert cfg.key == "default"
assert cfg.name == "魂镜"
assert cfg.display_name == "魂镜"
assert cfg.language == "zh-CN"
assert cfg.privacy_level == "normal"
assert cfg.profile["background"] == "默认人物"
assert cfg.profile["speaking_style"] == "温和、清晰、简洁"
assert cfg.profile["temperament"] == "沉静而温暖"
assert isinstance(cfg.profile["hobbies"], list)
assert "哲学" in cfg.profile["hobbies"]
assert isinstance(cfg.profile["values"], list)
assert "真诚" in cfg.profile["values"]
assert cfg.model_policy["memory_extraction_model_hint"] == "memory-extraction"
assert cfg.model_policy["personality_analysis_model_hint"] == "personality-analysis"
assert cfg.model_policy["embedding_model_hint"] == "embedding"
def test_get_default_template():
"""取 default 模板配置成功。"""
cfg = get_default_template()
assert cfg.key == "default"
assert cfg.name == "魂镜"
@pytest.mark.asyncio
async def test_ensure_default_system_template_creates_from_config():
"""第一次调用 → 按 config 创建系统模板并写入 DB。"""
from app.services.characters import ensure_default_system_template
async with AsyncSessionLocal() as session:
existing = await character_repo.get_system_template_by_key(session, "default")
if existing:
await session.delete(existing)
await session.flush()
template = await ensure_default_system_template(session)
assert template is not None
assert template.name == "魂镜"
assert template.display_name == "魂镜"
assert template.language == "zh-CN"
assert template.privacy_level == "normal"
assert template.template_key == "default"
assert template.is_system_template is True
assert template.owner_scope == "system"
assert template.status == "active"
profile = loads_dict(template.profile_json)
assert profile.get("background") == "默认人物"
assert profile.get("temperament") == "沉静而温暖"
assert isinstance(profile.get("hobbies"), list)
assert isinstance(profile.get("values"), list)
assert isinstance(profile.get("birthday"), str) # _ensure_default_birthday 兜底
policy = loads_dict(template.model_policy_json)
assert policy.get("default_chat_model_hint") == settings.default_model_hint
assert policy.get("memory_extraction_model_hint") == "memory-extraction"
assert policy.get("personality_analysis_model_hint") == "personality-analysis"
assert policy.get("embedding_model_hint") == "embedding"
await session.rollback()
@pytest.mark.asyncio
async def test_ensure_default_system_template_updates_changed_fields():
"""已有模板时 config 字段变化 → 覆盖更新。"""
from app.services.characters import ensure_default_system_template
async with AsyncSessionLocal() as session:
template = await ensure_default_system_template(session)
await session.flush()
template_id = template.id
template.name = "旧名覆盖测试"
await session.flush()
template2 = await ensure_default_system_template(session)
assert template2.name == "魂镜" # 被 config 覆盖回来
assert template2.id == template_id # 同一条记录
await session.rollback()
@pytest.mark.asyncio
async def test_template_resync_no_spurious_updates():
"""config 与 DB 一致时同步不应触发无意义更新。"""
from app.services.characters import ensure_default_system_template
async with AsyncSessionLocal() as session:
template = await ensure_default_system_template(session)
await session.flush()
template2 = await ensure_default_system_template(session)
assert template2.id == template.id
await session.rollback()
@pytest.mark.asyncio
async def test_create_character_uses_new_defaults():
"""create_character 使用 ``_MODEL_POLICY_CREATE_DEFAULTS``。"""
from app.schemas.character import CreateCharacterRequest
from app.services.characters import create_character
async with AsyncSessionLocal() as session:
character = await create_character(
session,
CreateCharacterRequest(name="测试人物"),
)
assert character is not None
assert character.name == "测试人物"
assert character.status == "wuji"
# create_character 返回 CharacterResponse,model_policy 是 dict
assert "default_chat_model_hint" in character.model_policy
assert "memory_extraction_model_hint" in character.model_policy
await session.rollback()