""" 场景优化接口测试 """ import pytest from fastapi.testclient import TestClient from unittest.mock import patch, AsyncMock from app.main import app client = TestClient(app) @pytest.fixture def sample_request_data(): """示例请求数据""" return { "existing_scenarios": [ { "name": "会员画像分析", "description": "基于会员消费行为分析用户画像" } ], "data_assets": [ { "name": "会员基础信息表", "description": "存储C端注册用户的核心身份信息", "core_tables": ["t_user_base_01"] } ], "company_info": { "industry": ["零售"], "description": "某连锁生鲜零售企业" } } @pytest.fixture def sample_request_data_with_screenshots(): """示例请求数据(含截图)""" return { "existing_scenarios": [ { "name": "会员画像分析", "description": "基于会员消费行为分析用户画像" } ], "data_assets": [ { "name": "会员基础信息表", "description": "存储C端注册用户的核心身份信息", "core_tables": ["t_user_base_01"] } ], "company_info": { "industry": ["零售"], "description": "某连锁生鲜零售企业" }, "scenario_screenshots": [ "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg==" ] } @pytest.fixture def mock_llm_response(): """模拟大模型响应""" return { "optimization_suggestions": [ { "scenario_name": "会员画像分析", "current_status": "当前仅基于交易数据进行画像,维度单一", "suggestions": [ "增加用户行为轨迹分析,包括浏览、收藏、分享等", "引入第三方数据源,丰富用户标签体系", "优化画像可视化展示,提升用户体验" ], "potential_value": "提升画像准确率20%,增加营销转化率15%" } ] } @pytest.fixture def mock_vision_llm_response(): """模拟视觉大模型响应""" return """场景截图分析结果: 1. 界面布局:整体布局清晰,但信息密度较高,建议优化留白 2. 数据展示:图表类型单一,建议增加更多可视化方式 3. 交互体验:筛选功能不够直观,建议优化交互设计 4. 功能完整性:缺少导出功能,建议添加""" @pytest.mark.asyncio async def test_scenario_optimization_success(sample_request_data, mock_llm_response): """测试场景优化成功""" import json with patch('app.services.scenario_optimization_service.llm_client.call') as mock_call: # 模拟大模型返回 JSON 字符串 mock_call.return_value = json.dumps(mock_llm_response, ensure_ascii=False) response = client.post( "/api/v1/value/scenario-optimization", json=sample_request_data ) assert response.status_code == 200 data = response.json() assert data["success"] is True assert data["code"] == 200 assert "data" in data assert "optimization_suggestions" in data["data"] assert len(data["data"]["optimization_suggestions"]) > 0 @pytest.mark.asyncio async def test_scenario_optimization_with_screenshots(sample_request_data_with_screenshots, mock_llm_response, mock_vision_llm_response): """测试场景优化(含截图)""" import json with patch('app.services.scenario_optimization_service.llm_client.call') as mock_call: with patch('httpx.AsyncClient') as mock_httpx_client: # 模拟大模型返回 JSON 字符串 mock_call.return_value = json.dumps(mock_llm_response, ensure_ascii=False) # 模拟视觉大模型响应 mock_response = AsyncMock() mock_response.status_code = 200 mock_response.raise_for_status = AsyncMock() mock_response.json.return_value = { "choices": [{ "message": { "content": mock_vision_llm_response } }] } # 设置 AsyncClient 的上下文管理器 mock_client_instance = AsyncMock() mock_client_instance.post = AsyncMock(return_value=mock_response) mock_httpx_client.return_value.__aenter__ = AsyncMock(return_value=mock_client_instance) mock_httpx_client.return_value.__aexit__ = AsyncMock(return_value=False) response = client.post( "/api/v1/value/scenario-optimization", json=sample_request_data_with_screenshots ) assert response.status_code == 200 data = response.json() assert data["success"] is True assert "data" in data def test_scenario_optimization_request_validation(): """测试请求验证""" # 测试空场景列表(应该是有效的,因为 existing_scenarios 是必需的但可以是空列表) valid_request = { "existing_scenarios": [], "data_assets": [], "company_info": { "industry": ["零售"], "description": "某连锁生鲜零售企业" } } with patch('app.services.scenario_optimization_service.llm_client.call') as mock_call: import json mock_call.return_value = json.dumps({"optimization_suggestions": []}, ensure_ascii=False) response = client.post( "/api/v1/value/scenario-optimization", json=valid_request ) # 应该返回 200(空场景列表也可以处理) assert response.status_code == 200 def test_scenario_optimization_empty_scenarios(): """测试空场景列表""" request_data = { "existing_scenarios": [], "data_assets": [], "company_info": { "industry": ["零售"], "description": "某连锁生鲜零售企业" } } with patch('app.services.scenario_optimization_service.llm_client.call') as mock_call: import json mock_call.return_value = json.dumps({"optimization_suggestions": []}, ensure_ascii=False) response = client.post( "/api/v1/value/scenario-optimization", json=request_data ) # 应该返回 200(空场景列表也可以处理) assert response.status_code == 200 def test_scenario_optimization_with_options(): """测试带选项的请求""" import json request_data = { "existing_scenarios": [ { "name": "测试场景", "description": "测试描述" } ], "data_assets": [], "options": { "model": "gpt-4", "temperature": 0.5 } } with patch('app.services.scenario_optimization_service.llm_client.call') as mock_call: mock_call.return_value = json.dumps({"optimization_suggestions": []}, ensure_ascii=False) response = client.post( "/api/v1/value/scenario-optimization", json=request_data ) assert response.status_code == 200 if __name__ == "__main__": pytest.main([__file__, "-v"])