""" Unit tests for ScriptGenerator. [AC-IDS-04, AC-IDS-11] Test script generation for flexible mode. """ import asyncio import pytest from app.services.flow.script_generator import ScriptGenerator class MockLLMClient: """Mock LLM client for testing.""" def __init__(self, response: str = "您好,请问怎么称呼您?", delay: float = 0): self._response = response self._delay = delay async def generate_text(self, prompt: str) -> str: if self._delay > 0: await asyncio.sleep(self._delay) return self._response async def generate(self, messages: list) -> "MockResponse": if self._delay > 0: await asyncio.sleep(self._delay) return MockResponse(self._response) class MockResponse: """Mock LLM response.""" def __init__(self, content: str): self.content = content class TestScriptGenerator: """[AC-IDS-04, AC-IDS-11] Test cases for ScriptGenerator.""" @pytest.mark.asyncio async def test_generate_fixed_mode_returns_fallback(self): """Test that fixed mode returns fallback content.""" generator = ScriptGenerator(llm_client=None) result = await generator.generate( intent="获取用户姓名", intent_description="礼貌询问用户姓名", constraints=["必须礼貌"], context=None, history=None, fallback="请问怎么称呼您?", ) assert result == "请问怎么称呼您?" @pytest.mark.asyncio async def test_generate_with_llm_client(self): """Test script generation with LLM client.""" llm_client = MockLLMClient(response="您好,请问您贵姓?") generator = ScriptGenerator(llm_client=llm_client) result = await generator.generate( intent="获取用户姓名", intent_description="礼貌询问用户姓名", constraints=["必须礼貌", "语气自然"], context={"inputs": [{"step": 1, "input": "我想咨询"}]}, history=[{"role": "user", "content": "我想咨询"}], fallback="请问怎么称呼您?", ) assert result == "您好,请问您贵姓?" @pytest.mark.asyncio async def test_generate_timeout_fallback(self): """Test that timeout returns fallback content.""" llm_client = MockLLMClient(response="生成的话术", delay=6.0) generator = ScriptGenerator(llm_client=llm_client) result = await generator.generate( intent="获取用户姓名", intent_description=None, constraints=None, context=None, history=None, fallback="请问怎么称呼您?", ) assert result == "请问怎么称呼您?" @pytest.mark.asyncio async def test_generate_exception_fallback(self): """Test that exception returns fallback content.""" class FailingLLMClient: async def generate_text(self, prompt: str) -> str: raise RuntimeError("LLM service unavailable") generator = ScriptGenerator(llm_client=FailingLLMClient()) result = await generator.generate( intent="获取用户姓名", intent_description=None, constraints=None, context=None, history=None, fallback="请问怎么称呼您?", ) assert result == "请问怎么称呼您?" def test_build_prompt_basic(self): """Test prompt building with basic parameters.""" generator = ScriptGenerator(llm_client=None) prompt = generator._build_prompt( intent="获取用户姓名", intent_description=None, constraints=None, context=None, history=None, ) assert "获取用户姓名" in prompt assert "步骤目标" in prompt def test_build_prompt_with_description(self): """Test prompt building with intent description.""" generator = ScriptGenerator(llm_client=None) prompt = generator._build_prompt( intent="获取用户姓名", intent_description="需要获取用户的真实姓名用于后续身份确认", constraints=None, context=None, history=None, ) assert "获取用户姓名" in prompt assert "需要获取用户的真实姓名用于后续身份确认" in prompt assert "详细说明" in prompt def test_build_prompt_with_constraints(self): """Test prompt building with constraints.""" generator = ScriptGenerator(llm_client=None) prompt = generator._build_prompt( intent="获取用户姓名", intent_description=None, constraints=["必须礼貌", "语气自然", "不要生硬"], context=None, history=None, ) assert "约束条件" in prompt assert "- 必须礼貌" in prompt assert "- 语气自然" in prompt assert "- 不要生硬" in prompt def test_build_prompt_with_history(self): """Test prompt building with conversation history.""" generator = ScriptGenerator(llm_client=None) prompt = generator._build_prompt( intent="获取用户姓名", intent_description=None, constraints=None, context=None, history=[ {"role": "user", "content": "你好"}, {"role": "assistant", "content": "您好,有什么可以帮您?"}, {"role": "user", "content": "我想咨询"}, ], ) assert "对话历史" in prompt assert "用户: 你好" in prompt assert "客服: 您好,有什么可以帮您?" in prompt def test_build_prompt_with_context(self): """Test prompt building with session context.""" generator = ScriptGenerator(llm_client=None) prompt = generator._build_prompt( intent="获取用户姓名", intent_description=None, constraints=None, context={ "inputs": [ {"step": 1, "input": "我想咨询产品"}, {"step": 2, "input": "手机"}, ] }, history=None, ) assert "已收集信息" in prompt assert "步骤1: 我想咨询产品" in prompt assert "步骤2: 手机" in prompt def test_build_prompt_complete(self): """Test prompt building with all parameters.""" generator = ScriptGenerator(llm_client=None) prompt = generator._build_prompt( intent="获取用户姓名", intent_description="需要获取用户的真实姓名", constraints=["必须礼貌", "语气自然"], context={"inputs": [{"step": 1, "input": "咨询"}]}, history=[{"role": "user", "content": "你好"}], ) assert "步骤目标" in prompt assert "详细说明" in prompt assert "约束条件" in prompt assert "对话历史" in prompt assert "已收集信息" in prompt assert "不超过200字" in prompt