TEST_REPORT.md 9.3 KB

验收测试报告

项目: Proposa AI - bid_proposal
测试日期: 2026-07-07
测试人员: 测试工程师(test)


测试概要

测试项 状态 说明
测试1: 模块导入测试 ✅ 通过 所有模块可正确导入
测试2: bid_reader 功能测试 ✅ 通过 PDF读取正常: 76页, 36个表格, 64990字符
测试3: proposal_writer 生成测试 ⚠️ 有警告 DOCX成功生成(38KB),但表格解析有边界错误
测试4: 代码质量检查 ⚠️ 有发现 代码质量良好,发现少量改进点
测试5: Pipeline dry-run测试 ✅ 通过 流程编排逻辑正常

详细测试结果

测试1: 模块导入测试

所有模块均可正确导入,包括:

  • bid_proposal
  • bid_proposal.bid_reader
  • bid_proposal.config
  • bid_proposal.models
  • bid_proposal.pipeline
  • bid_proposal.proposal_generator
  • bid_proposal.proposal_writer
  • bid_proposal.requirement_analyzer
  • bid_proposal.utils

结论: ✅ 通过


测试2: bid_reader 功能测试

指标 结果
输入文件 data/松江区机关事务管理局物业管理服务招标文件.pdf
文件大小 3,033,606 bytes (约2.9MB)
页数 76
表格数 36
文本总字符数 64,990

结论: ✅ 通过


测试3: proposal_writer 生成测试

指标 结果
生成文件 data/test_proposal_output.docx
文件大小 38,332 bytes (38KB)
生成耗时 < 1秒
错误

发现的问题:

  1. 表格分隔行检测Bug ⚠️: Markdown表格的隔行 |---------|---------|stripped.startswith("|---") 误判为表格结束标记,因为 |--------- 的前4个字符是 | - - -,恰好匹配 |---。这导致 _write_table 被提前调用(仅传入表头行),触发 "表格数据不足,跳过表格写入" 警告。

影响范围: 如果内容中某个 Markdown 表格后面紧跟其他非表格内容,该表格会被错误地截断,只有表头被写入 DOCX。

建议修复:

方案1 (推荐): 在 _write_markdown_content 中用正则替换 stripped.startswith("|---") 条件为更精确的匹配:

   # 替换第353行附近的条件
   if stripped.startswith("|") and not re.match(r'^\|[\s\-:]+\|?$', stripped):

方案2: 将 not stripped.startswith("|---") 改为 not re.match(r'^\|[-]{3,}', stripped),只匹配连续的三个以上短横线。

  1. 表格数据校验过于严格: _parse_markdown_tablelen(data) < 2 的判断使得单行表格(仅表头)被过滤。对于某些仅含表头无数据的场景,可以考虑放宽限制。

结论: ⚠️ 有警告 — 功能正常,但表格解析存在边界Bug,建议修复。


测试4: 代码质量检查

4.1 模块文档字符串

文件 行数 代码行 模块Docstring 函数数 类数
__init__.py 6 4 0 0
__main__.py 126 102 2 0
bid_reader.py 128 91 3 1
config.py 56 38 3 1
models.py 133 106 12 6
pipeline.py 127 100 1 0
proposal_generator.py 424 362 8 1
proposal_writer.py 549 414 15 0
requirement_analyzer.py 303 249 6 2
utils.py 105 73 3 0

结论: ✅ 所有文件均有模块级文档字符串。

4.2 异常处理分析

文件 try/except raise 分析
bid_reader.py 4/3 4 良好 — 自定义 BidReadError 异常,表格提取有 graceful degradation
config.py 0/0 0 N/A — 纯数据类 + 环境读取,无需异常处理
models.py 0/0 0 N/A — 纯数据类,无需异常处理
pipeline.py 4/4 6 良好 — 每一步有 try/except,用 RuntimeError 包装
proposal_generator.py 6/6 2 良好 — 有 fallback 机制和重试
proposal_writer.py 0/0 2 ⚠️ write_proposal_docx 声明会抛出 IOError,但未捕获 doc.save() 的异常
requirement_analyzer.py 3/3 5 良好 — 有重试逻辑和分块容错
__main__.py 1/4 0 良好 — 顶层异常按类型分级处理
utils.py 0/0 0 ⚠️ table_to_markdownchunk_text 缺少输入校验

发现的问题:

  1. proposal_writer.pydoc.save() 未保护: 第530行 doc.save(output_path) 在磁盘空间不足或路径不可写时会抛出 OSError/IOError,该异常未被捕获或包装为更明确的错误信息。

  2. utils.pytable_to_markdown 健壮性不足: 函数依赖 hasattr 检查,但如果 cells 内容格式不符预期(如非嵌套列表),会抛出 AttributeError。

4.3 日志覆盖分析

文件 logging.getLogger logger.xxx 调用数 分析
bid_reader.py 6 充分覆盖关键流程节点
pipeline.py 10 充分覆盖每一步
proposal_generator.py 13 充分覆盖
proposal_writer.py 3 偏少:仅入口和出口有日志,表格写入失败有日志
requirement_analyzer.py 10 充分覆盖,含重试日志
__main__.py 14 充分覆盖
__init__.py 0 N/A — 初始化文件
config.py 1 较少但可接受
models.py 0 N/A — 数据类,无需日志
utils.py 0 ⚠️ chunk_text 没有日志

发现的问题:

  1. utils.py 缺少日志: 工具函数模块没有定义 logger,chunk_texttable_to_markdown 的关键路径无日志输出,调试时难以追踪。

  2. proposal_writer.py 日志偏少: 在 _write_markdown_content 中处理各个 Markdown 元素时缺少 DEBUG 级别日志。

4.4 敏感信息检查

检查项 结果
代码中硬编码 API Key ✅ 未发现
代码中硬编码密码/令牌 ✅ 未发现
api_key 参数传递 ✅ 通过函数参数和环境变量传递,无硬编码
.env 或配置文件泄露 N/A — 无此类文件

结论: ✅ 无敏感信息泄露风险。

4.5 代码质量综合评分

维度 评分 说明
代码结构 4/5 模块职责清晰,符合单一职责原则
注释/docstring 5/5 所有模块、类、函数均有详细 docstring
异常处理 3.5/5 主要模块良好,proposal_writerutils.py 有待加强
日志覆盖 3.5/5 主要流程充分,工具函数偏少
命名规范 5/5 符合 Python 命名规范(snake_case, PascalCase)
类型注解 4/5 主要函数有类型注解,部分内部函数缺少

结论: ⚠️ 有发现 — 代码质量总体良好,存在少量需要改进的点。


测试5: Pipeline dry-run 测试

检查项 结果
run_pipeline 函数签名 ✅ 正确
输入PDF文件存在性校验 FileNotFoundError 在文件不存在时抛出的逻辑正确
默认输出路径计算 ✅ 输出路径为 data/松江区机关事务管理局物业管理服务招标文件_投标文件.docx
模块导入 ✅ 所有依赖模块可正确导入
流程步骤逻辑 ✅ 参数校验 → 文件读取 → 分析 → 生成 → DOCX输出,顺序正确

结论: ✅ 通过


综合评估

总体评价

bid_proposal 包整体质量良好,模块结构清晰,文档完善。各模块之间的数据模型对齐,接口兼容。

评分

维度 等级 说明
功能完整性 ⭐⭐⭐⭐☆ 核心功能完整,从PDF读取到DOCX生成流程通顺
代码质量 ⭐⭐⭐⭐☆ 规范良好,少量改进点
健壮性 ⭐⭐⭐☆☆ 主流程有异常处理,但边界情况和工具函数偏弱
可维护性 ⭐⭐⭐⭐⭐ 模块划分清晰,文档注释充分
兼容性 ⭐⭐⭐⭐☆ 数据结构统一,接口对齐

关键问题(建议高优先级修复)

  1. 表格隔行检测Bug (proposal_writer.py:353): stripped.startswith("|---") 误匹配 |---------,导致表格在含有隔行时被截断。

次要改进建议

  1. proposal_writer.py doc.save() 应加 try/except,捕获 IOError 并提供更有意义的错误信息。
  2. utils.py 添加 logger 定义,在关键路径增加 DEBUG 日志,便于调试。
  3. 添加单元测试: 项目目前没有测试目录(tests/),建议为关键函数(_parse_markdown_tablechunk_text_extract_text)添加 pytest 单元测试。
  4. utils.py table_to_markdown 函数增加对异常输入(空对象、异常嵌套结构)的处理。
  5. pyproject.toml 中的依赖列表不完整,缺少 python-docxpdf_table_to_docx 等运行时依赖。

测试数据文件

  • 测试输入PDF: data/松江区机关事务管理局物业管理服务招标文件.pdf (3.0 MB)
  • 测试输出DOCX: data/test_proposal_output.docx (38 KB)
  • 测试依据PDF: data/松江区机关事务管理局物业管理服务项目投标文件.pdf (1.2 MB)

报告生成于 2026-07-07,由 proposa-ai 项目的验收测试脚本自动生成。