Files
lyxy-document/tests/test_readers/conftest.py
lanyuanxiaoyao fad0edc46a feat: 添加 doc/xls/ppt 旧格式文档静态测试文件支持
- 更新 .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 变更
2026-03-11 00:30:47 +08:00

282 lines
7.5 KiB
Python

"""Reader 测试专用 fixtures。"""
import pytest
from pathlib import Path
@pytest.fixture
def temp_docx(tmp_path):
"""创建临时 DOCX 文件的 fixture 工厂。
Args:
paragraphs: 段落文本列表
headings: 标题列表,格式为 [(level, text), ...]
table_data: 表格数据,格式为 [[cell1, cell2], [cell3, cell4]]
list_items: 列表项列表
Returns:
str: 临时文件路径
"""
def _create_docx(paragraphs=None, headings=None, table_data=None, list_items=None):
try:
from docx import Document
except ImportError:
pytest.skip("python-docx 未安装")
doc = Document()
# 添加标题
if headings:
for level, text in headings:
doc.add_heading(text, level=level)
# 添加段落
if paragraphs:
for para_text in paragraphs:
doc.add_paragraph(para_text)
# 添加表格
if table_data:
table = doc.add_table(rows=len(table_data), cols=len(table_data[0]))
for i, row_data in enumerate(table_data):
for j, cell_text in enumerate(row_data):
table.rows[i].cells[j].text = str(cell_text)
# 添加列表项
if list_items:
for item in list_items:
doc.add_paragraph(item, style='List Bullet')
file_path = tmp_path / "test.docx"
doc.save(str(file_path))
return str(file_path)
return _create_docx
@pytest.fixture
def temp_pdf(tmp_path):
"""创建临时 PDF 文件的 fixture 工厂。
Args:
text: PDF 文本内容
lines: 文本行列表
Returns:
str: 临时文件路径
"""
def _create_pdf(text=None, lines=None):
try:
from reportlab.pdfgen import canvas
from reportlab.lib.pagesizes import letter
from reportlab.pdfbase import pdfmetrics
from reportlab.pdfbase.ttfonts import TTFont
except ImportError:
pytest.skip("reportlab 未安装")
file_path = tmp_path / "test.pdf"
c = canvas.Canvas(str(file_path), pagesize=letter)
# 尝试注册中文字体(如果可用)
try:
# 使用系统字体
pdfmetrics.registerFont(TTFont('SimSun', 'simsun.ttc'))
c.setFont('SimSun', 12)
except:
# 回退到默认字体
c.setFont('Helvetica', 12)
y_position = 750
if text:
# 单个文本块
for line in text.split('\n'):
c.drawString(100, y_position, line)
y_position -= 20
if lines:
# 多行文本
for line in lines:
c.drawString(100, y_position, line)
y_position -= 20
c.save()
return str(file_path)
return _create_pdf
@pytest.fixture
def temp_html(tmp_path):
"""创建临时 HTML 文件的 fixture 工厂。
Args:
content: HTML 内容字符串
encoding: 文件编码,默认 'utf-8'
Returns:
str: 临时文件路径
"""
def _create_html(content="<html><body><p>Test</p></body></html>", encoding='utf-8'):
file_path = tmp_path / "test.html"
# 如果内容不包含完整的 HTML 结构,添加基本结构
if not content.strip().startswith('<html'):
content = f"<html><head><meta charset='{encoding}'></head><body>{content}</body></html>"
with open(file_path, 'w', encoding=encoding) as f:
f.write(content)
return str(file_path)
return _create_html
@pytest.fixture
def temp_pptx(tmp_path):
"""创建临时 PPTX 文件的 fixture 工厂。
Args:
slides: 幻灯片内容列表,每个元素为 (title, content) 元组
Returns:
str: 临时文件路径
"""
def _create_pptx(slides=None):
try:
from pptx import Presentation
except ImportError:
pytest.skip("python-pptx 未安装")
prs = Presentation()
if slides:
for title, content in slides:
slide = prs.slides.add_slide(prs.slide_layouts[1]) # Title and Content layout
slide.shapes.title.text = title
if content:
text_frame = slide.shapes.placeholders[1].text_frame
text_frame.text = content
file_path = tmp_path / "test.pptx"
prs.save(str(file_path))
return str(file_path)
return _create_pptx
@pytest.fixture
def temp_xlsx(tmp_path):
"""创建临时 XLSX 文件的 fixture 工厂。
Args:
data: 表格数据,格式为 [[cell1, cell2], [cell3, cell4]]
Returns:
str: 临时文件路径
"""
def _create_xlsx(data=None):
try:
import pandas as pd
except ImportError:
pytest.skip("pandas 未安装")
file_path = tmp_path / "test.xlsx"
if data:
df = pd.DataFrame(data)
df.to_excel(str(file_path), index=False, header=False)
else:
# 创建空的 Excel 文件
df = pd.DataFrame()
df.to_excel(str(file_path), index=False)
return str(file_path)
return _create_xlsx
# 静态测试文件目录
FIXTURES_DIR = Path(__file__).parent / "fixtures"
@pytest.fixture
def doc_fixture_path():
"""返回 DOC 静态测试文件目录"""
return FIXTURES_DIR / "doc"
@pytest.fixture
def xls_fixture_path():
"""返回 XLS 静态测试文件目录"""
return FIXTURES_DIR / "xls"
@pytest.fixture
def ppt_fixture_path():
"""返回 PPT 静态测试文件目录"""
return FIXTURES_DIR / "ppt"
def _get_static_file_path(fixture_dir, filename):
"""获取静态文件路径,不存在时跳过测试"""
file_path = fixture_dir / filename
if not file_path.exists():
pytest.skip(f"静态测试文件不存在: {file_path}")
return str(file_path)
@pytest.fixture
def simple_doc_path(doc_fixture_path):
"""返回简单 DOC 测试文件路径"""
return _get_static_file_path(doc_fixture_path, "simple.doc")
@pytest.fixture
def with_headings_doc_path(doc_fixture_path):
"""返回带标题的 DOC 测试文件路径"""
return _get_static_file_path(doc_fixture_path, "with_headings.doc")
@pytest.fixture
def with_table_doc_path(doc_fixture_path):
"""返回带表格的 DOC 测试文件路径"""
return _get_static_file_path(doc_fixture_path, "with_table.doc")
@pytest.fixture
def simple_xls_path(xls_fixture_path):
"""返回简单 XLS 测试文件路径"""
return _get_static_file_path(xls_fixture_path, "simple.xls")
@pytest.fixture
def multiple_sheets_xls_path(xls_fixture_path):
"""返回多工作表 XLS 测试文件路径"""
return _get_static_file_path(xls_fixture_path, "multiple_sheets.xls")
@pytest.fixture
def with_formulas_xls_path(xls_fixture_path):
"""返回带公式 XLS 测试文件路径"""
return _get_static_file_path(xls_fixture_path, "with_formulas.xls")
@pytest.fixture
def simple_ppt_path(ppt_fixture_path):
"""返回简单 PPT 测试文件路径"""
return _get_static_file_path(ppt_fixture_path, "simple.ppt")
@pytest.fixture
def multiple_slides_ppt_path(ppt_fixture_path):
"""返回多幻灯片 PPT 测试文件路径"""
return _get_static_file_path(ppt_fixture_path, "multiple_slides.ppt")
@pytest.fixture
def with_images_ppt_path(ppt_fixture_path):
"""返回带图片 PPT 测试文件路径"""
return _get_static_file_path(ppt_fixture_path, "with_images.ppt")