- 更新 .gitattributes,将 fixtures 目录所有文件纳入 Git LFS - 在 tests/test_readers/conftest.py 中添加静态文件 fixtures - 添加 doc/xls/ppt 静态测试文件(9个文件) - 更新各旧格式解析器测试用例使用静态文件 - 更新一致性测试使用静态文件 - 在 README.md 中添加 fixtures 使用规范 - 同步 delta specs 到主 specs(doc-reader/xls-reader/ppt-reader/reader-testing/test-fixtures) - 归档 add-static-test-fixtures 变更
177 lines
6.9 KiB
Markdown
177 lines
6.9 KiB
Markdown
# Reader Testing Specification
|
||
|
||
## Purpose
|
||
|
||
定义 Reader 实现的测试规范,包括 supports 方法验证、parse 方法测试、特殊字符处理、多 Reader 一致性等。
|
||
|
||
## Requirements
|
||
|
||
### Requirement: Reader supports 方法验证
|
||
每个 Reader MUST 实现 `supports(file_path: str) -> bool` 方法,正确判断是否支持给定输入。
|
||
|
||
#### Scenario: DOCX Reader 识别标准扩展名
|
||
- **WHEN** 调用 DOCX Reader 的 `supports("file.docx")`
|
||
- **THEN** 返回 True
|
||
|
||
#### Scenario: DOCX Reader 识别大写扩展名
|
||
- **WHEN** 调用 DOCX Reader 的 `supports("FILE.DOCX")`
|
||
- **THEN** 返回 True
|
||
|
||
#### Scenario: DOCX Reader 识别 .doc 扩展名
|
||
- **WHEN** 调用 DOCX Reader 的 `supports("file.doc")`
|
||
- **THEN** 返回 True
|
||
|
||
#### Scenario: DOCX Reader 拒绝不支持格式
|
||
- **WHEN** 调用 DOCX Reader 的 `supports("file.pdf")`
|
||
- **THEN** 返回 False
|
||
|
||
#### Scenario: DOCX Reader 支持 URL
|
||
- **WHEN** 调用 DOCX Reader 的 `supports("http://example.com/file.docx")`
|
||
- **THEN** 返回 True
|
||
|
||
#### Scenario: PDF Reader 识别 PDF 文件
|
||
- **WHEN** 调用 PDF Reader 的 `supports("file.pdf")`
|
||
- **THEN** 返回 True
|
||
|
||
#### Scenario: HTML Reader 识别 HTML 文件
|
||
- **WHEN** 调用 HTML Reader 的 `supports("file.html")`
|
||
- **THEN** 返回 True
|
||
|
||
### Requirement: Reader parse 方法正常解析
|
||
每个 Reader MUST 实现 `parse(file_path: str) -> Tuple[Optional[str], List[str]]` 方法,成功解析时返回 Markdown 内容和空失败列表。
|
||
|
||
#### Scenario: DOCX Reader 解析包含段落
|
||
- **WHEN** DOCX Reader 解析包含段落的文件
|
||
- **THEN** 返回的 Markdown 内容包含段落文字
|
||
- **AND** 失败列表为空
|
||
|
||
#### Scenario: DOCX Reader 解析包含标题
|
||
- **WHEN** DOCX Reader 解析包含标题的文件
|
||
- **THEN** 返回的 Markdown 内容包含 `# ` 标记的标题
|
||
|
||
#### Scenario: DOCX Reader 解析包含表格
|
||
- **WHEN** DOCX Reader 解析包含表格的文件
|
||
- **THEN** 返回的 Markdown 内容包含表格中的关键文字
|
||
|
||
#### Scenario: DOCX Reader 解析包含列表
|
||
- **WHEN** DOCX Reader 解析包含列表的文件
|
||
- **THEN** 返回的 Markdown 内容包含列表项文字
|
||
|
||
#### Scenario: PDF Reader 解析基本内容
|
||
- **WHEN** PDF Reader 解析包含文字的 PDF
|
||
- **THEN** 返回的 Markdown 内容包含关键文字
|
||
|
||
#### Scenario: HTML Reader 解析网页内容
|
||
- **WHEN** HTML Reader 解析包含内容的 HTML 文件
|
||
- **THEN** 返回的 Markdown 内容包含网页关键文字
|
||
|
||
### Requirement: Reader 解析结果核心文字一致性
|
||
同一文件使用不同 Reader 解析时,MUST 保持核心文字内容一致(样式和格式可以不同)。
|
||
|
||
#### Scenario: DOCX 多 Reader 一致性
|
||
- **WHEN** 同一 DOCX 文件被 python-docx、markitdown、docling 等 Reader 解析
|
||
- **THEN** 所有输出的 Markdown 都包含相同的核心文字内容
|
||
|
||
#### Scenario: PDF 多 Reader 一致性
|
||
- **WHEN** 同一 PDF 文件被 pypdf、markitdown、docling 等 Reader 解析
|
||
- **THEN** 所有输出的 Markdown 都包含相同的核心文字内容
|
||
|
||
### Requirement: Reader 处理特殊字符
|
||
Reader MUST 正确处理包含特殊字符的内容。
|
||
|
||
#### Scenario: 处理中文字符
|
||
- **WHEN** 文件包含中文内容
|
||
- **THEN** 解析后的 Markdown 正确包含中文
|
||
|
||
#### Scenario: 处理 Emoji 表情
|
||
- **WHEN** 文件包含 Emoji(如 😀🎉)
|
||
- **THEN** 解析后的 Markdown 正确包含 Emoji
|
||
|
||
#### Scenario: 处理特殊符号
|
||
- **WHEN** 文件包含特殊符号(©®™°±)
|
||
- **THEN** 解析后的 Markdown 正确包含这些符号
|
||
|
||
#### Scenario: 处理 RTL 文本
|
||
- **WHEN** 文件包含阿拉伯文等 RTL 文本
|
||
- **THEN** 解析后的 Markdown 正确包含 RTL 文本
|
||
|
||
#### Scenario: 处理混合文本
|
||
- **WHEN** 文件包含混合内容(如 "Hello你好🎉")
|
||
- **THEN** 解析后的 Markdown 正确包含混合内容
|
||
|
||
#### Scenario: 处理零宽字符
|
||
- **WHEN** 文件包含零宽字符(\u200b\u200c\u200d)
|
||
- **THEN** 解析后的 Markdown 正确处理这些字符
|
||
|
||
#### Scenario: 处理超长文本
|
||
- **WHEN** 文件包含超长文本(如 100000 个字符)
|
||
- **THEN** Reader 能够成功解析
|
||
|
||
### Requirement: Reader 独立测试
|
||
每个 Reader 实现 MUST 有独立的测试文件,不使用参数化测试。
|
||
|
||
#### Scenario: 每个 DOCX Reader 有独立测试
|
||
- **WHEN** 查看 test_readers/test_docx/ 目录
|
||
- **THEN** 存在 test_python_docx.py、test_markitdown.py、test_docling.py 等独立文件
|
||
|
||
#### Scenario: 每个 PDF Reader 有独立测试
|
||
- **WHEN** 查看 test_readers/test_pdf/ 目录
|
||
- **THEN** 存在 test_pypdf.py、test_markitdown.py、test_docling.py 等独立文件
|
||
|
||
### Requirement: 旧格式文档测试覆盖
|
||
doc/xls/ppt 旧格式文档 MUST 有与新格式(docx/xlsx/pptx)一致的测试覆盖。
|
||
|
||
#### Scenario: doc 有一致性测试
|
||
- **WHEN** 查看 `tests/test_readers/test_doc/`
|
||
- **THEN** 存在 `test_consistency.py` 测试所有 DOC Readers 解析结果一致性
|
||
|
||
#### Scenario: xls 有一致性测试
|
||
- **WHEN** 查看 `tests/test_readers/test_xls/`
|
||
- **THEN** 存在 `test_consistency.py` 测试所有 XLS Readers 解析结果一致性
|
||
|
||
#### Scenario: ppt 有一致性测试
|
||
- **WHEN** 查看 `tests/test_readers/test_ppt/`
|
||
- **THEN** 存在 `test_consistency.py` 测试所有 PPT Readers 解析结果一致性
|
||
|
||
#### Scenario: doc 各解析器独立测试
|
||
- **WHEN** 查看 `tests/test_readers/test_doc/`
|
||
- **THEN** 每个解析器有独立测试文件(如 `test_markitdown_doc.py`、`test_pypandoc_doc.py`)
|
||
|
||
#### Scenario: xls 各解析器独立测试
|
||
- **WHEN** 查看 `tests/test_readers/test_xls/`
|
||
- **THEN** 每个解析器有独立测试文件(如 `test_markitdown_xls.py`、`test_unstructured_xls.py`、`test_pandas_xls.py`)
|
||
|
||
#### Scenario: ppt 各解析器独立测试
|
||
- **WHEN** 查看 `tests/test_readers/test_ppt/`
|
||
- **THEN** 每个解析器有独立测试文件(如 `test_markitdown_ppt.py`)
|
||
|
||
### Requirement: 旧格式测试使用静态文件
|
||
旧格式文档测试 MUST 使用静态测试文件,而非尝试自动化创建。
|
||
|
||
#### Scenario: doc 测试使用静态文件
|
||
- **WHEN** 运行 doc 相关测试
|
||
- **THEN** 测试从 `tests/test_readers/fixtures/doc/` 读取静态文件
|
||
|
||
#### Scenario: xls 测试使用静态文件
|
||
- **WHEN** 运行 xls 相关测试
|
||
- **THEN** 测试从 `tests/test_readers/fixtures/xls/` 读取静态文件
|
||
|
||
#### Scenario: ppt 测试使用静态文件
|
||
- **WHEN** 运行 ppt 相关测试
|
||
- **THEN** 测试从 `tests/test_readers/fixtures/ppt/` 读取静态文件
|
||
|
||
### Requirement: 静态文件缺失时优雅跳过
|
||
当静态测试文件不存在时,测试 MUST 优雅跳过,而非失败。
|
||
|
||
#### Scenario: doc 静态文件不存在时跳过
|
||
- **WHEN** `simple.doc` 不存在
|
||
- **THEN** 相关测试使用 `pytest.skip()` 跳过
|
||
|
||
#### Scenario: xls 静态文件不存在时跳过
|
||
- **WHEN** `simple.xls` 不存在
|
||
- **THEN** 相关测试使用 `pytest.skip()` 跳过
|
||
|
||
#### Scenario: ppt 静态文件不存在时跳过
|
||
- **WHEN** `simple.ppt` 不存在
|
||
- **THEN** 相关测试使用 `pytest.skip()` 跳过
|