"""评价指标体系 API 集成测试。""" from fastapi.testclient import TestClient class TestWeightComputeAPI: """权重计算 API 测试。""" def test_compute_weights_success(self, client: TestClient, auth_headers: dict): """POST /evaluation/weights/compute 应返回权重计算结果。""" resp = client.post( "/api/v1/evaluation/weights/compute", json={ "fund_type": "early_vc", "fund_lifecycle": "investment", "company_stage": "a", "industry": "ai", "strategy": "growth", "investor_type": "investor", }, headers=auth_headers, ) assert resp.status_code == 200 data = resp.json()["data"] assert "weights" in data assert "enabled_dimensions" in data assert "disabled_dimensions" in data assert "custom_metrics" in data # 权重总和应接近 100 total = sum(data["weights"].values()) assert abs(total - 100.0) < 1.0 def test_compute_weights_no_auth(self, client: TestClient): """未认证应返回 401。""" resp = client.post( "/api/v1/evaluation/weights/compute", json={ "fund_type": "early_vc", "company_stage": "a", "industry": "ai", }, ) assert resp.status_code == 401 def test_compute_weights_hardware_disables_ai(self, client: TestClient, auth_headers: dict): """硬科技赛道应禁用 AI 维度。""" resp = client.post( "/api/v1/evaluation/weights/compute", json={ "fund_type": "early_vc", "fund_lifecycle": "investment", "company_stage": "a", "industry": "hardware", }, headers=auth_headers, ) assert resp.status_code == 200 data = resp.json()["data"] assert "ai_commercial" in data["disabled_dimensions"] assert "ai_cost" in data["disabled_dimensions"] class TestTemplateAPI: """评价模板 API 测试。""" def test_list_templates_empty(self, client: TestClient, auth_headers: dict): """无模板时应返回空列表。""" resp = client.get("/api/v1/evaluation/templates", headers=auth_headers) assert resp.status_code == 200 assert isinstance(resp.json()["data"], list) def test_list_templates_no_auth(self, client: TestClient): """未认证应返回 401。""" resp = client.get("/api/v1/evaluation/templates") assert resp.status_code == 401 def test_create_template_auto_weights(self, client: TestClient, auth_headers: dict): """创建模板时不传权重应自动计算。""" resp = client.post( "/api/v1/evaluation/templates", json={ "name": "测试模板-早期VC-AI", "fund_type": "early_vc", "fund_lifecycle": "investment", "company_stage": "a", "industry": "ai", "strategy": "growth", }, headers=auth_headers, ) assert resp.status_code == 200 data = resp.json()["data"] assert "id" in data assert "weights" in data def test_create_template_with_custom_weights(self, client: TestClient, auth_headers: dict): """创建模板时传自定义权重应使用自定义权重。""" resp = client.post( "/api/v1/evaluation/templates", json={ "name": "自定义权重模板", "fund_type": "early_vc", "fund_lifecycle": "growth", "company_stage": "b", "industry": "saas", "strategy": "value", "weights_json": {"financial": 40, "product_tech": 30, "market_compete": 30}, }, headers=auth_headers, ) assert resp.status_code == 200 data = resp.json()["data"] assert data["weights"]["financial"] == 40 def test_get_template_by_id(self, client: TestClient, auth_headers: dict): """根据 ID 获取模板详情。""" # 先创建 create_resp = client.post( "/api/v1/evaluation/templates", json={ "name": "查询测试模板", "fund_type": "pe", "fund_lifecycle": "growth", "company_stage": "c", "industry": "fintech", }, headers=auth_headers, ) template_id = create_resp.json()["data"]["id"] # 再查询 resp = client.get(f"/api/v1/evaluation/templates/{template_id}", headers=auth_headers) assert resp.status_code == 200 data = resp.json()["data"] assert data["name"] == "查询测试模板" assert data["fund_type"] == "pe" def test_get_template_not_found(self, client: TestClient, auth_headers: dict): """查询不存在的模板应返回 404。""" resp = client.get( "/api/v1/evaluation/templates/nonexistent-id", headers=auth_headers, ) assert resp.status_code == 200 assert resp.json()["code"] == 404 def test_list_templates_with_filter(self, client: TestClient, auth_headers: dict): """按基金类型筛选模板。""" # 创建两个不同类型模板 client.post( "/api/v1/evaluation/templates", json={ "name": "筛选-早期VC", "fund_type": "early_vc", "company_stage": "a", "industry": "ai", }, headers=auth_headers, ) client.post( "/api/v1/evaluation/templates", json={ "name": "筛选-PE", "fund_type": "pe", "company_stage": "b", "industry": "saas", }, headers=auth_headers, ) resp = client.get( "/api/v1/evaluation/templates?fund_type=pe", headers=auth_headers, ) assert resp.status_code == 200 data = resp.json()["data"] for tmpl in data: assert tmpl["fund_type"] == "pe" class TestScoreCalculateAPI: """评分计算 API 测试。""" def test_calculate_score_without_template(self, client: TestClient, auth_headers: dict, company_id: str): """无模板时计算评分应使用默认计算。""" resp = client.post( "/api/v1/evaluation/score", json={ "company_id": company_id, "structured_data": { "revenue": {"yoy_change": "30"}, "cash_balance": {"runway_months": 18}, "burn_rate": {"trend": "down"}, }, }, headers=auth_headers, ) assert resp.status_code == 200 data = resp.json()["data"] assert "total_score" in data assert "dimension_scores" in data def test_calculate_score_no_auth(self, client: TestClient): """未认证应返回 401。""" resp = client.post( "/api/v1/evaluation/score", json={"company_id": "test", "structured_data": {}}, ) assert resp.status_code == 401 def test_calculate_score_with_template(self, client: TestClient, auth_headers: dict, company_id: str): """使用模板计算评分。""" # 先创建模板 tmpl_resp = client.post( "/api/v1/evaluation/templates", json={ "name": "评分测试模板", "fund_type": "early_vc", "company_stage": "a", "industry": "ai", }, headers=auth_headers, ) template_id = tmpl_resp.json()["data"]["id"] # 使用模板计算评分 resp = client.post( "/api/v1/evaluation/score", json={ "company_id": company_id, "template_id": template_id, "structured_data": { "revenue": {"yoy_change": "25"}, "cash_balance": {"runway_months": 15}, "burn_rate": {"trend": "down"}, "headcount": {"new_hires": 3, "departures": 1}, }, }, headers=auth_headers, ) assert resp.status_code == 200 data = resp.json()["data"] assert "score_id" in data assert "total_score" in data assert data["template"] is not None assert data["template"]["id"] == template_id class TestScoreHistoryAPI: """评分历史 API 测试。""" def test_list_scores_empty(self, client: TestClient, auth_headers: dict): """无评分记录时应返回空列表。""" resp = client.get("/api/v1/evaluation/scores", headers=auth_headers) assert resp.status_code == 200 assert isinstance(resp.json()["data"], list) def test_list_scores_no_auth(self, client: TestClient): """未认证应返回 401。""" resp = client.get("/api/v1/evaluation/scores") assert resp.status_code == 401 class TestFundAPI: """基金管理 API 测试。""" def test_list_funds_empty(self, client: TestClient, auth_headers: dict): """无基金时应返回空列表。""" resp = client.get("/api/v1/evaluation/funds", headers=auth_headers) assert resp.status_code == 200 assert isinstance(resp.json()["data"], list) def test_create_fund(self, client: TestClient, auth_headers: dict): """创建基金。""" resp = client.post( "/api/v1/evaluation/funds", json={ "name": "测试基金一期", "fund_type": "early_vc", "strategy": "growth", "established_date": "2023-01-01", "total_lifespan_months": 84, "investment_period_months": 48, "primary_market": "china_mainland", }, headers=auth_headers, ) assert resp.status_code == 200 data = resp.json()["data"] assert "id" in data assert data["current_lifecycle"] == "investment" def test_create_fund_no_auth(self, client: TestClient): """未认证应返回 401。""" resp = client.post( "/api/v1/evaluation/funds", json={"name": "test", "fund_type": "early_vc"}, ) assert resp.status_code == 401