Files
resume-agent/backend/tests/test_builder_candidate_rewrite.py
T
hypandClaude ae2d9b128d feat: builder 简历生成 + 轻度优化 + 简历导入交付副本
自内部仓库剥离深度优化与 RAG 知识库后的交付版本:
- Builder 对话式简历生成(FSM + 意图路由 LLM 兜底增强)
- 条目级轻度优化:事实覆盖门禁 + STAR/bullet 修复链,功能/简介/成果与技术栈同级保护
- 简历导入:DOCX/PDF 解析、结构归一、手机号脱敏
- PostgreSQL 运行时 + Alembic 迁移链

Co-Authored-By: Claude <noreply@anthropic.com>
2026-08-05 11:08:30 +08:00

112 lines
4.3 KiB
Python

"""Candidate rewrite guards for the Builder light optimization (截图1/截图2 回归)."""
from __future__ import annotations
from typing import Any
from app.builder_conversation import _candidate_rewrite
class _StaticExpander:
def __init__(self, optimized: str) -> None:
self.optimized = optimized
def expand(self, entry: dict[str, Any], *, context: dict[str, Any]) -> dict[str, Any]:
return {"optimized_description": self.optimized, "source": "test"}
class _Agent:
def __init__(self, optimized: str) -> None:
self.expander = _StaticExpander(optimized)
def test_candidate_rewrite_does_not_inject_identity_into_education_description() -> None:
"""Identity fields have their own card slots; never merge them into the narrative (截图2)."""
proposal = _candidate_rewrite(
_Agent("在学校中学习数据结构、计算机视觉等课程。"),
{"job_type": "campus"},
{
"school": "东莞城市学院",
"major": "软件工程",
"degree": "本科",
"description": "在学校中学习数据结构、计算机视觉等课程。",
},
"education",
)
assert proposal["optimized_description"] == "在学校中学习数据结构、计算机视觉等课程。"
assert "东莞城市学院" not in proposal["optimized_description"]
def test_candidate_rewrite_reports_uncovered_facts_without_appending() -> None:
"""Uncovered user facts are reported, not stitched onto the candidate (截图1 关键词尾巴)."""
proposal = _candidate_rewrite(
_Agent("完成数据库课程项目并参与实验室实践。"),
{"job_type": "campus", "target_position": "backend engineer"},
{"description": "完成数据库课程项目。GPA: 4.3/5.0,排名前百分之10。"},
"education",
)
assert proposal["optimized_description"] == "完成数据库课程项目并参与实验室实践。"
assert proposal["uncovered_facts"] == ["GPA: 4.3/5.0", "排名前百分之10"]
def test_candidate_rewrite_reports_other_uncovered_user_facts() -> None:
original = (
"完成数据库课程项目,使用 Python 和 SQL 实现信息查询。"
"获得校级一等奖学金,服务 300 名学生。"
)
proposal = _candidate_rewrite(
_Agent("参与学习与实践活动。"),
{"job_type": "campus"},
{"description": original},
"education",
)
assert proposal["optimized_description"] == "参与学习与实践活动。"
for fact in ("完成数据库课程项目", "Python", "SQL", "获得校级一等奖学金", "服务 300 名学生"):
assert fact in proposal["uncovered_facts"]
def test_candidate_rewrite_reports_no_uncovered_facts_when_candidate_covers_all() -> None:
proposal = _candidate_rewrite(
_Agent("完成数据库课程项目。GPA: 4.3/5.0。"),
{"job_type": "campus"},
{"description": "完成数据库课程项目。GPA: 4.3/5.0。"},
"education",
)
assert proposal["uncovered_facts"] == []
def test_candidate_rewrite_reports_dropped_function_modules() -> None:
"""功能模块/平台简介被吞时必须进入未覆盖报告(只保留技术栈不算覆盖)。"""
original = (
"全栈 AI 求职助手平台,包含 5 大功能模块:\n"
"1. AI 对话式简历生成助手\n"
"2. 简历导入 (PDF/DOCX 智能解析)\n"
"技术栈: Next.js + React"
)
proposal = _candidate_rewrite(
_Agent("• 前端采用 Next.js 与 React 实现响应式界面。"),
{"job_type": "campus"},
{"description": original},
"project_experience",
)
assert any("AI 对话式简历生成助手" in fact for fact in proposal["uncovered_facts"])
assert any("简历导入" in fact for fact in proposal["uncovered_facts"])
assert not any("Next.js" in fact for fact in proposal["uncovered_facts"])
def test_candidate_rewrite_tolerates_covered_fragments_without_false_positives() -> None:
original = "1. AI 对话式简历生成助手\n2. 简历导入智能解析"
proposal = _candidate_rewrite(
_Agent("负责 AI 对话式简历生成助手与简历导入智能解析两大模块。"),
{"job_type": "campus"},
{"description": original},
"project_experience",
)
assert proposal["uncovered_facts"] == []