test: 修复 EPUB 缺失依赖测试设计问题
This commit is contained in:
@@ -224,7 +224,15 @@ md-vector-db/
|
|||||||
│ │ ├── db.py # ChromaDB 封装(线程安全)
|
│ │ ├── db.py # ChromaDB 封装(线程安全)
|
||||||
│ │ ├── embedder.py # 嵌入器(Local/OpenAI/Dashscope)
|
│ │ ├── embedder.py # 嵌入器(Local/OpenAI/Dashscope)
|
||||||
│ │ ├── ingest.py # 混合分块 + 入库
|
│ │ ├── ingest.py # 混合分块 + 入库
|
||||||
│ │ └── search.py # 语义检索
|
│ │ ├── search.py # 语义检索
|
||||||
|
│ │ └── splitters/ # 文档分块器包
|
||||||
|
│ │ ├── base.py # Splitter(Protocol) + BaseTextSplitter(ABC)
|
||||||
|
│ │ ├── markdown.py # MarkdownSplitter
|
||||||
|
│ │ ├── text.py # TextSplitter
|
||||||
|
│ │ ├── pdf.py # PDFSplitter
|
||||||
|
│ │ ├── html.py # HTMLSplitter
|
||||||
|
│ │ ├── epub.py # EPUBSplitter
|
||||||
|
│ │ └── registry.py # 扩展名 → Splitter 自动选择
|
||||||
│ ├── server/ # FastAPI HTTP 层
|
│ ├── server/ # FastAPI HTTP 层
|
||||||
│ │ ├── app.py # 路由 + 中间件
|
│ │ ├── app.py # 路由 + 中间件
|
||||||
│ │ ├── deps.py # 依赖注入(AppState)
|
│ │ ├── deps.py # 依赖注入(AppState)
|
||||||
@@ -236,7 +244,7 @@ md-vector-db/
|
|||||||
├── scripts/
|
├── scripts/
|
||||||
│ ├── serve.py # 快速启动脚本
|
│ ├── serve.py # 快速启动脚本
|
||||||
│ └── ingest_obsidian.py # 批量入库 Obsidian 知识库
|
│ └── ingest_obsidian.py # 批量入库 Obsidian 知识库
|
||||||
└── tests/ # 测试(46 个)
|
└── tests/ # 测试(115+ 个)
|
||||||
```
|
```
|
||||||
|
|
||||||
## 测试
|
## 测试
|
||||||
@@ -250,7 +258,7 @@ uv run pytest tests/ -v --cov=src --cov-report=term-missing # 覆盖率
|
|||||||
|
|
||||||
## 架构
|
## 架构
|
||||||
|
|
||||||
**数据流**: MD 文件 → `MarkdownSplitter.split()` (标题→段落分块) → `batch_embed()` (分批嵌入) → `ChromaDB collection.add()` → `Searcher.search()` 查询
|
**数据流**: 文件 → `get_splitter(path)` 自动选择 → `Splitter.split()` → `batch_embed()` (分批嵌入) → `ChromaDB collection.add()` → `Searcher.search()` 查询
|
||||||
|
|
||||||
**依赖方向**: `config` ← `db` ← `embedder` ← `ingest` / `search` ← `server` / `cli`
|
**依赖方向**: `config` ← `db` ← `embedder` ← `ingest` / `search` ← `server` / `cli`
|
||||||
|
|
||||||
|
|||||||
@@ -1,11 +1,30 @@
|
|||||||
"""EPUBSplitter 测试."""
|
"""EPUBSplitter 测试."""
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
ebooklib = pytest.importorskip("ebooklib", reason="ebooklib 未安装")
|
|
||||||
|
class TestEPUBSplitterMissingDep:
|
||||||
|
"""缺失依赖时的行为测试(不 skip 整个文件)."""
|
||||||
|
|
||||||
|
def test_split_raises_clear_import_error(self, monkeypatch):
|
||||||
|
"""未安装 ebooklib 时给出明确提示."""
|
||||||
|
from src.core.splitters.epub import EPUBSplitter
|
||||||
|
s = EPUBSplitter()
|
||||||
|
import builtins
|
||||||
|
original_import = builtins.__import__
|
||||||
|
|
||||||
|
def mock_import(name, *args, **kwargs):
|
||||||
|
if name == "ebooklib" or name.startswith("ebooklib."):
|
||||||
|
raise ImportError("No module named 'ebooklib'")
|
||||||
|
return original_import(name, *args, **kwargs)
|
||||||
|
|
||||||
|
monkeypatch.setattr(builtins, "__import__", mock_import)
|
||||||
|
with pytest.raises(ImportError, match="ebooklib"):
|
||||||
|
s.split("dummy.epub", source_file="test.epub")
|
||||||
|
|
||||||
|
|
||||||
class TestEPUBSplitter:
|
class TestEPUBSplitter:
|
||||||
"""EPUBSplitter 测试(需 ebooklib)."""
|
"""EPUBSplitter 测试(需 ebooklib)."""
|
||||||
|
ebooklib = pytest.importorskip("ebooklib", reason="ebooklib 未安装")
|
||||||
|
|
||||||
def test_split_simple_epub(self, tmp_path):
|
def test_split_simple_epub(self, tmp_path):
|
||||||
"""用 ebooklib 创建一个简单 EPUB 并测试分块."""
|
"""用 ebooklib 创建一个简单 EPUB 并测试分块."""
|
||||||
@@ -47,10 +66,3 @@ class TestEPUBSplitter:
|
|||||||
from src.core.splitters.epub import EPUBSplitter
|
from src.core.splitters.epub import EPUBSplitter
|
||||||
s = EPUBSplitter()
|
s = EPUBSplitter()
|
||||||
assert hasattr(s, "split")
|
assert hasattr(s, "split")
|
||||||
|
|
||||||
def test_epub_missing_dependency_message(self):
|
|
||||||
"""EPUBSplitter.split() 在未安装 ebooklib 时应给出明确提示."""
|
|
||||||
from src.core.splitters.epub import EPUBSplitter
|
|
||||||
s = EPUBSplitter()
|
|
||||||
# 验证 split 方法存在且可调用(有明确的 import error 信息)
|
|
||||||
assert callable(s.split)
|
|
||||||
|
|||||||
Reference in New Issue
Block a user