16c42787
tangwang
feat: implement r...
|
1
2
|
# 搜索引擎测试流水线指南
|
99b72698
tangwang
测试回归钩子梳理
|
3
4
5
|
本文档是测试套件的**权威入口**,涵盖目录约定、运行方式、回归锚点矩阵、以及手动
联调脚本的分工。任何与这里不一致的历史文档(例如提到 `tests/unit/` 或
`scripts/start_test_environment.sh`)都是过期信息,以本文为准。
|
16c42787
tangwang
feat: implement r...
|
6
|
|
99b72698
tangwang
测试回归钩子梳理
|
7
|
## 1. 测试目录与分层
|
16c42787
tangwang
feat: implement r...
|
8
9
|
```
|
99b72698
tangwang
测试回归钩子梳理
|
10
11
12
13
14
15
16
17
18
|
tests/
├── conftest.py # 只做 sys.path 注入;不再维护全局 fixture
├── ci/ # API/服务契约(FastAPI TestClient + 全 fake 依赖)
│ └── test_service_api_contracts.py
├── manual/ # 需真实服务才能跑的联调脚本,pytest 默认不 collect
│ ├── test_build_docs_api.py
│ ├── test_cnclip_service.py
│ └── test_facet_api.py
└── test_*.py # 子系统单测(全部自带 fake,无外部依赖)
|
16c42787
tangwang
feat: implement r...
|
19
20
|
```
|
99b72698
tangwang
测试回归钩子梳理
|
21
|
关键约束(写在 `pytest.ini` 里,不要另起分支):
|
16c42787
tangwang
feat: implement r...
|
22
|
|
99b72698
tangwang
测试回归钩子梳理
|
23
24
25
|
- `testpaths = tests`,`norecursedirs = tests/manual`;
- `--strict-markers`:所有 marker 必须先在 `pytest.ini::markers` 登记;
- 测试**不得**依赖真实 ES / DeepL / LLM 服务。需要外部依赖的脚本请放 `tests/manual/`。
|
16c42787
tangwang
feat: implement r...
|
26
|
|
99b72698
tangwang
测试回归钩子梳理
|
27
|
## 2. 运行方式
|
16c42787
tangwang
feat: implement r...
|
28
|
|
99b72698
tangwang
测试回归钩子梳理
|
29
30
31
32
33
34
35
|
| 场景 | 命令 | 覆盖范围 |
|------|------|----------|
| CI 门禁(每次提交) | `./scripts/run_ci_tests.sh` | `tests/ci` + `contract` marker + `search ∧ regression` |
| 发版 / 大合并前 | `./scripts/run_regression_tests.sh` | 所有 `@pytest.mark.regression` |
| 子系统子集 | `SUBSYSTEM=search ./scripts/run_regression_tests.sh` | 指定子系统的 regression 锚点 |
| 全量(含非回归) | `python -m pytest tests/ -q` | 全部自动化用例 |
| 手动联调 | `python tests/manual/<script>.py` | 需提前起对应服务 |
|
16c42787
tangwang
feat: implement r...
|
36
|
|
99b72698
tangwang
测试回归钩子梳理
|
37
|
## 3. Marker 体系与回归锚点矩阵
|
16c42787
tangwang
feat: implement r...
|
38
|
|
99b72698
tangwang
测试回归钩子梳理
|
39
40
|
marker 定义见 `pytest.ini`。每个测试文件通过模块级 `pytestmark` 贴标,同时
属于 `regression` 的用例构成“**回归锚点集合**”。
|
16c42787
tangwang
feat: implement r...
|
41
|
|
99b72698
tangwang
测试回归钩子梳理
|
42
43
44
45
46
47
48
49
50
51
52
53
|
| 子系统 marker | 关键文件(锚点) | 保护的行为 |
|---------------|------------------|------------|
| `contract` | `tests/ci/test_service_api_contracts.py` | Search / Indexer / Embedding / Reranker / Translation 的 HTTP 契约 |
| `search` | `test_search_rerank_window.py`, `test_es_query_builder.py`, `test_es_query_builder_text_recall_languages.py` | Searcher 主路径、排序 / 召回、keywords 副 combined_fields、多语种 |
| `query` | `test_query_parser_mixed_language.py`, `test_tokenization.py` | 中英混合解析、HanLP 分词、language detect |
| `intent` | `test_style_intent.py`, `test_product_title_exclusion.py`, `test_sku_intent_selector.py` | 风格意图、商品标题排除、SKU 选型 |
| `rerank` | `test_rerank_client.py`, `test_rerank_query_text.py`, `test_rerank_provider_topn.py`, `test_reranker_server_topn.py`, `test_reranker_dashscope_backend.py`, `test_reranker_qwen3_gguf_backend.py` | 粗排 / 精排 / topN / 后端切换 |
| `embedding` | `test_embedding_pipeline.py`, `test_embedding_service_limits.py`, `test_embedding_service_priority.py`, `test_cache_keys.py` | 文本/图像向量客户端、inflight limiter、优先级队列、缓存 key |
| `translation` | `test_translation_deepl_backend.py`, `test_translation_llm_backend.py`, `test_translation_local_backends.py`, `test_translator_failure_semantics.py` | DeepL / LLM / 本地回退、失败语义 |
| `indexer` | `test_product_enrich_partial_mode.py`, `test_process_products_batching.py`, `test_llm_enrichment_batch_fill.py` | LLM Partial Mode、batch 拆分、空结果补位 |
| `suggestion` | `test_suggestions.py` | 建议索引构建 |
| `eval` | `test_eval_metrics.py`(regression) + `test_search_evaluation_datasets.py` / `test_eval_framework_clients.py`(非 regression) | NDCG / ERR 指标、数据集加载、评估客户端 |
|
16c42787
tangwang
feat: implement r...
|
54
|
|
99b72698
tangwang
测试回归钩子梳理
|
55
56
|
> 任何新写的子系统单测,都应该在顶部加 `pytestmark = [pytest.mark.<子系统>, pytest.mark.regression]`。
> 不贴 `regression` 的测试默认**不会**被 `run_regression_tests.sh` 选中,请谨慎决定。
|
16c42787
tangwang
feat: implement r...
|
57
|
|
99b72698
tangwang
测试回归钩子梳理
|
58
|
## 4. 当前覆盖缺口(跟踪中)
|
16c42787
tangwang
feat: implement r...
|
59
|
|
99b72698
tangwang
测试回归钩子梳理
|
60
|
以下场景目前没有被 `regression` 锚点覆盖,优先级从高到低:
|
16c42787
tangwang
feat: implement r...
|
61
|
|
99b72698
tangwang
测试回归钩子梳理
|
62
63
64
65
66
67
|
1. **`api/routes/search.py` 的请求参数映射**:`QueryParser.parse(...)` 透传是否完整(目前只有 `tests/ci` 间接覆盖)。
2. **`indexer/document_transformer.py` 的端到端转换**:从 MySQL 行到 ES doc 的 snapshot 对比。
3. **`config/loader.py` 加载多租户配置**:含继承 / override 的合并规则。
4. **`search/searcher.py::_build_function_score`**:function_score 装配。
5. **Facet 聚合 / disjunctive 过滤**。
6. **图像搜索主路径**(`search/image_searcher.py`)。
|
16c42787
tangwang
feat: implement r...
|
68
|
|
99b72698
tangwang
测试回归钩子梳理
|
69
|
补齐时记得同步贴 `regression` + 对应子系统 marker,并在本表删除条目。
|
16c42787
tangwang
feat: implement r...
|
70
|
|
99b72698
tangwang
测试回归钩子梳理
|
71
|
## 5. 手动联调:索引文档构建流水线
|
16c42787
tangwang
feat: implement r...
|
72
|
|
99b72698
tangwang
测试回归钩子梳理
|
73
74
|
除自动化测试外,联调/问题排查时建议走一遍“**MySQL → ES doc**”链路,确保字段与 mapping
与查询逻辑对齐。
|
89638140
tangwang
重构 indexer 文档构建接口...
|
75
76
|
```bash
|
a7920e17
tangwang
项目名称和部署路径修改
|
77
|
cd /home/tw/saas-search
|
89638140
tangwang
重构 indexer 文档构建接口...
|
78
|
./scripts/stop.sh # 停掉已有进程(可选)
|
99b72698
tangwang
测试回归钩子梳理
|
79
|
./scripts/start_indexer.sh # 启动 indexer 服务,默认端口 6004
|
89638140
tangwang
重构 indexer 文档构建接口...
|
80
|
|
89638140
tangwang
重构 indexer 文档构建接口...
|
81
82
|
curl -X POST "http://127.0.0.1:6004/indexer/build-docs-from-db" \
-H "Content-Type: application/json" \
|
99b72698
tangwang
测试回归钩子梳理
|
83
|
-d '{ "tenant_id": "170", "spu_ids": ["223167"] }'
|
89638140
tangwang
重构 indexer 文档构建接口...
|
84
85
|
```
|
99b72698
tangwang
测试回归钩子梳理
|
86
87
|
返回中 `docs[0]` 即当前代码构造的 ES doc(与 `mappings/search_products.json` 对齐)。
与真实 ES 数据对比的查询参考 `docs/常用查询 - ES.md`;若字段不一致,按以下路径定位:
|
16c42787
tangwang
feat: implement r...
|
88
|
|
99b72698
tangwang
测试回归钩子梳理
|
89
90
91
|
- `indexer/document_transformer.py` — 文档构造逻辑
- `indexer/incremental_service.py` — 增量查库逻辑
- `logs/indexer.log` — 索引日志
|
16c42787
tangwang
feat: implement r...
|
92
|
|
99b72698
tangwang
测试回归钩子梳理
|
93
|
## 6. 编写测试的约束(与 `开发原则` 对齐)
|
16c42787
tangwang
feat: implement r...
|
94
|
|
99b72698
tangwang
测试回归钩子梳理
|
95
96
97
98
|
- **fail fast**:测试输入不合法时应直接抛错,不用 `if ... return`;不要用 `try/except` 吃掉异常再 `assert not exception`。
- **不做兼容双轨**:用例对准当前实现,不为历史行为保留“旧 assert”。若确有外部兼容性(例如 API 上标注 Deprecated 的字段),在 `tests/ci` 里单独写**契约**用例并注明 Deprecated。
- **外部依赖全 fake**:凡是依赖 HTTP / Redis / ES / LLM 的测试必须注入 fake stub,否则归入 `tests/manual/`。
- **一处真相**:共享 fixture 如果超过 2 个文件使用,放 `tests/conftest.py`;只给 1 个文件用就放在该文件内。避免再次出现全库无人引用的 dead fixture。
|