"""FileService 结构化摄入测试(任务 16)。 覆盖:xlsx 多子表切分 + 空单元格保留(无列错位);csv 网格;缺库降级安全。 """ from __future__ import annotations import os import tempfile import pytest from services.file_service import FileService, ParsedDocument, TableGrid def _make_sl0010_xlsx(path): from openpyxl import Workbook wb = Workbook() ws = wb.active ws.title = "Sheet1" # 物理特性子表 ws.append(["物理特性检测结果"]) ws.append(["批号", "涂布厚度/mm", "膜厚/mm", "溶化时限/s"]) ws.append(["SL-0010-20μg", 0.5, 0.05, 60]) ws.append(["SL-0010-40μg", None, 0.07, 74]) # 涂布厚度空单元格 ws.append([]) # 空行分隔 # 有关物质子表 ws.append(["有关物质检测结果"]) ws.append(["样品名称", "保留时间min", "总杂%"]) ws.append(["SL-0010-20μg", 25.44, 0.0]) wb.save(path) def test_excel_structured_preserves_empty_cells_and_segments(): fd, path = tempfile.mkstemp(suffix=".xlsx") os.close(fd) try: _make_sl0010_xlsx(path) doc = FileService().parse_structured(path) assert isinstance(doc, ParsedDocument) # 两张子表被切分 assert len(doc.tables) == 2 phys = doc.tables[0] assert phys.title == "物理特性检测结果" # 数据行:40μg 行的涂布厚度保留为 None(不塌缩),列对齐 row40 = [r for r in phys.rows if r and r[0] == "SL-0010-40μg"][0] assert row40[1] is None # 涂布厚度空 assert row40[2] == "0.07" # 膜厚仍在第 2 列 finally: os.remove(path) def test_csv_structured_grid(): fd, path = tempfile.mkstemp(suffix=".csv") os.close(fd) try: with open(path, "w", encoding="utf-8-sig", newline="") as f: f.write("批号,膜厚,水分\nSL-0010-20μg,0.05,5.3\n") doc = FileService().parse_structured(path) assert len(doc.tables) == 1 assert doc.tables[0].rows[0] == ["批号", "膜厚", "水分"] finally: os.remove(path) def test_structured_degrades_safely_when_format_unavailable(): # 用一个不支持依赖的格式名模拟:构造一个 import_checker 永远返回 False。 svc = FileService(import_checker=lambda name: False) fd, path = tempfile.mkstemp(suffix=".xlsx") os.close(fd) try: _make_sl0010_xlsx(path) doc = svc.parse_structured(path) # 依赖不可用 → 不抛异常,返回 ParsedDocument(tables 可能为空) assert isinstance(doc, ParsedDocument) assert doc.tables == [] finally: os.remove(path) def test_pdf_dependency_is_pymupdf(): from services.file_service import _FORMAT_DEPENDENCY, FORMAT_PDF assert _FORMAT_DEPENDENCY[FORMAT_PDF] == "fitz"