测试与质量保证.md 29 KB

测试与质量保证

本文引用的文件

  • ai-template-match-test-cases.md
  • ai-llm-template-match-bug-report-20261026.md
  • run_tests.py
  • generate.py
  • manifest.json
  • eslint.config.mjs
  • stylelint.config.mjs
  • vitest.config.mts
  • package.json

目录

  1. 引言
  2. 项目结构与测试范围
  3. 单元测试、端到端测试与 LLM 模板匹配测试分层
  4. LLM 模板匹配测试夹具总览
  5. 生成测试数据:generate.py
  6. 运行测试与比对结果:run_tests.py
  7. 清单文件 manifest.json
  8. 前端代码质量配置:ESLint、Stylelint、Vitest
  9. 后端测试目录约定
  10. 新增测试用例流程
  11. 修复回归问题与调试 LLM 匹配失败
  12. 持续集成、覆盖率与发布前检查建议
  13. 结论

引言

本仓库的测试体系包含三层内容:

  • 后端 JUnit 单元测试:覆盖 AI 清洗模板匹配的指纹、归一化、同义词、模糊词、打分、绑定与列计划等确定性逻辑。
  • 端到端测试:通过 HTTP API 调用真实服务,验证上传、智能清洗、批次、任务、治理树和数据库落库。
  • LLM 模板匹配测试:围绕 docs/testing/fixtures/ai-llm-match-20261026 下的 Python 测试夹具,使用 generate.py 生成生产风格样本,用 run_tests.py 批量执行,并用 manifest.json 管理测试用例清单。

文档 docs/testing/ai-template-match-test-cases.md 是该测试套件的核心说明;ai-llm-template-match-bug-report-20261026.md 记录了本轮发现的缺陷、根因分析和修复状态。

项目结构与测试范围

从仓库结构看,测试相关内容主要分布在以下位置:

路径 作用
docs/testing/ai-template-match-test-cases.md AI 模板匹配严格测试用例文档,定义 A/E 五类测试范围
docs/testing/ai-llm-template-match-bug-report-20261026.md LLM 模板匹配问题报告、复现步骤、修复记录
docs/testing/fixtures/ai-llm-match-20261026/ LLM 模板匹配测试夹具根目录
docs/testing/fixtures/ai-llm-match-20261026/bills/ 银行流水相关测试样本
docs/testing/fixtures/ai-llm-match-20261026/calls/ 通信话单相关测试样本
docs/testing/fixtures/ai-llm-match-20261026/full-template/ table_info 全量模板的原表头样本
docs/testing/fixtures/ai-llm-match-20261026/full-template-variants/ table_info 全量模板变体样本
docs/testing/fixtures/ai-llm-match-20261026/edge/ 边界场景样本
docs/testing/fixtures/ai-llm-match-20261026/retest/ 回归重测样本
docs/testing/fixtures/ai-llm-match-20261026/results/ 批量执行产出的 JSON 结果
ai-electron/frontend/eslint.config.mjs 前端 ESLint 配置
ai-electron/frontend/stylelint.config.mjs 前端 Stylelint 配置
ai-electron/vitest.config.mts Electron 主进程 Vitest 配置
ai-electron/frontend/package.json 前端脚本入口,包含 lint 命令
graph TB
    Docs["测试文档<br/>ai-template-match-test-cases.md"]
    BugReport["问题报告<br/>ai-llm-template-match-bug-report-20261026.md"]
    Fixtures["测试夹具目录<br/>fixtures/ai-llm-match-20261026"]
    Generate["generate.py<br/>生成测试数据"]
    Runner["run_tests.py<br/>批量执行与结果收集"]
    Manifest["manifest.json<br/>用例清单"]
    Bills["bills/<br/>银行流水样本"]
    Calls["calls/<br/>通信话单样本"]
    FullTpl["full-template/<br/>全量模板原表头"]
    Variants["full-template-variants/<br/>全量模板变体"]
    Edge["edge/<br/>边界场景"]
    Retest["retest/<br/>回归重测"]
    Results["results/<br/>执行结果 JSON"]

    Docs --> Fixtures
    BugReport --> Fixtures
    Generate --> Fixtures
    Manifest --> Runner
    Fixtures --> Runner
    Bills --> Fixtures
    Calls --> Fixtures
    FullTpl --> Fixtures
    Variants --> Fixtures
    Edge --> Fixtures
    Retest --> Fixtures
    Runner --> Results

图示来源

  • ai-template-match-test-cases.md:1-111
  • run_tests.py:1-60
  • generate.py:1-20
  • manifest.json:1-20

章节来源

  • ai-template-match-test-cases.md:1-111
  • ai-llm-template-match-bug-report-20261026.md:1-200

单元测试、端到端测试与 LLM 模板匹配测试分层

AI 模板匹配测试按确定性程度和链路深度分为五层:

层级 名称 被测内容 执行方式 特点
A 离线匹配规则 指纹、归一化、同义词、模糊词、打分组件 JUnit 确定性高,适合回归
B 绑定与计划 filterBinds 域解析、改写、歧义、列计划 JUnit 验证字段映射逻辑
C 端到端真链路 上传 → 智能清洗 → job/批次/数据/治理树 HTTP API + dev 数据库核验 覆盖完整业务流
D 异常容错 空表头、损坏文件、去重、跨案件 端到端 验证鲁棒性
E 全量模板覆盖 table_info 中全部模板逐一同类型文件 端到端分批 覆盖既有匹配器与 AI 兜底

测试锚定三个行业场景:

场景 模板 关键列 出口
车辆登记 AI 模板 2111790826933268480 号牌号码、机动车所有人、身份证明号码 B
银行交易流水 既有 table_info#2 trans_record 交易金额、借贷标志、查询卡号 A
通信记录 既有 table_info#1 call_record 本机号码、对方号码、呼叫开始时间 A

其中,“既有直中”指上传阶段被既有匹配器命中后直接走既有清洗,不再进入 AI 兜底链路。这是设计行为,不是 bug。要验证 AI 腿,必须构造同义词、相似词、乱序、缺必填、噪音表头等变体。

章节来源

  • ai-template-match-test-cases.md:1-111

LLM 模板匹配测试夹具总览

docs/testing/fixtures/ai-llm-match-20261026 是一个自包含的测试环境:

  • 输入:由 generate.py 生成的 xlsx 或 csv 样本。
  • 清单:由 manifest.json 描述每个用例的文件路径、类别、期望模板、变异方式和备注。
  • 执行器:run_tests.py 负责登录、打开案件、上传文件、触发智能清洗、轮询状态、读取数据库并写入结果。
  • 输出:results/ 目录下的 JSON 文件,包含上传结果、sheet 列表、job 信息、batch 信息和模板信息。

    flowchart TD
    Start["开发者运行测试"] --> Mode{"选择模式"}
    Mode -->|生成数据| Gen["generate.py"]
    Mode -->|执行测试| Run["run_tests.py"]
    Gen --> Manifest["更新 manifest.json"]
    Gen --> Samples["生成 bills/calls/edge 等样本"]
    Run --> ManifestRead["读取 manifest.json"]
    ManifestRead --> Upload["POST /dm/preFileUpload"]
    Upload --> Clean["POST /aiClean/smartClean"]
    Clean --> Status["轮询 /aiClean/smartClean/status"]
    Status --> DBJobs["查询 ai_clean_job"]
    Status --> DBBatch["查询 ai_clean_batch"]
    Status --> DBTemplate["查询 ai_clean_template"]
    DBJobs --> Result["写入 results/*.json"]
    DBBatch --> Result
    DBTemplate --> Result
    

图示来源

  • run_tests.py:1-60
  • run_tests.py:60-120
  • run_tests.py:120-200
  • generate.py:1-20

章节来源

  • ai-template-match-test-cases.md:1-111
  • ai-llm-template-match-bug-report-20261026.md:1-200

生成测试数据:generate.py

generate.py 是测试数据的工厂。它不依赖外部人工准备样本,而是连接 PostgreSQL,读取系统模板元数据,再用 openpyxl 和 xlwt 生成 Excel 文件。

主要职责

  1. 连接本地开发数据库 zsjz-ai。
  2. 使用固定随机种子 20261026,保证生成数据可重复。
  3. 为账单、话单、跨行业和 edge 场景生成“生产风格”假数据。
  4. 为 table_info 中全部模板生成原表头和变体样本。
  5. 输出到 docs/testing/fixtures/ai-llm-match-20261026 下对应目录。
  6. 生成完成后应同步更新 manifest.json,使执行器能识别新用例。

支持的生成模式

参数 含义
targeted 生成账单、话单、跨行业和异常场景样本
full 生成 table_info 全量模板的原表头与变体样本
all 同时执行 targeted 与 full

数据生成策略

脚本内置了多类数据生成函数,例如姓名、身份证号、手机号、银行卡号、金额、日期、通话时长、借贷方向、通话方向、公司、支行、地址、航班、车次、机场、车站等。这些值用于模拟真实业务数据,避免样本过于简单导致匹配器误判。

flowchart TD
    Entry["python generate.py <mode>"] --> ReadDB["连接 zsjz-ai 数据库"]
    ReadDB --> Seed["设置随机种子 20261026"]
    Seed --> SelectMode{"选择模式"}
    SelectMode -->|targeted| Targeted["生成账单/话单/跨行业/异常样本"]
    SelectMode -->|full| Full["生成 table_info 全量模板样本"]
    SelectMode -->|all| Both["执行 targeted 与 full"]
    Targeted --> WriteFiles["写入 fixtures 子目录"]
    Full --> WriteFiles
    WriteFiles --> UpdateManifest["提示更新 manifest.json"]

图示来源

  • generate.py:1-20
  • generate.py:20-60

章节来源

  • generate.py:1-200

运行测试与比对结果:run_tests.py

run_tests.py 是 LLM 模板匹配测试的主要入口。它封装了 HTTP 客户端、数据库查询和结果序列化逻辑。

常用命令

命令 含义
python run_tests.py group1 按 manifest 分组定向执行
python run_tests.py group1 --upload-only 只上传,不发起智能清洗
python run_tests.py group1 --limit 10 限制执行数量
python run_tests.py list 列出分组

核心组件

组件 职责
Client 管理 requests.Session、登录、自动续 token、打开案件、请求 API
db_jobs 根据 sheet_id 列表查询 ai_clean_job
db_batch 根据 batch_id 查询 ai_clean_batch
db_ai_template 根据模板 id 查询 ai_clean_template 及其字段
upload_one 上传单个文件并提取 sheet 信息
run_group 加载 manifest、过滤用例、分批执行、汇总结果

关键接口

接口 方法 用途
/auth/login POST 获取认证 token
/case/open POST 打开目标案件
/dm/preFileUpload POST 上传文件并返回 batchId、fileId、sheets
/aiClean/smartClean POST 发起智能清洗
/aiClean/smartClean/status GET 查询批次状态
/gt/treeTablePage POST 查询治理树数据页

结果校验流程

sequenceDiagram
    participant Dev as "开发者"
    participant Runner as "run_tests.py"
    participant API as "后端 API"
    participant DB as "PostgreSQL"

    Dev->>Runner: 运行指定分组
    Runner->>API: POST /auth/login
    Runner->>API: POST /case/open
    loop 遍历 manifest 中的用例
        Runner->>API: POST /dm/preFileUpload
        API-->>Runner: 返回 fileInfo、batchId、sheets
        alt --upload-only
            Runner->>Runner: 保存上传结果
        else 正常执行
            Runner->>API: POST /aiClean/smartClean
            Runner->>API: GET /aiClean/smartClean/status
            API-->>Runner: 返回批次状态
            Runner->>DB: 查询 ai_clean_job
            Runner->>DB: 查询 ai_clean_batch
            Runner->>DB: 查询 ai_clean_template
            Runner->>Runner: 合并结果并写入 JSON
        end
    end

图示来源

  • run_tests.py:1-60
  • run_tests.py:60-120
  • run_tests.py:120-200

章节来源

  • run_tests.py:1-200

清单文件 manifest.json

manifest.json 是测试夹具的索引。它定义了测试总数、分类计数以及每个用例的详细元数据。

顶层字段

字段 含义
generated_at 清单生成时间
case_id 默认测试案件 id
counts 各分类用例数量统计
files 用例数组

单个用例字段

字段 含义
test_id 用例编号,如 BILL-01、CALL-02
category 分类,如 bill、call、industry、edge
path 相对于 fixtures 根目录的文件路径
template_id 参考模板 id
expected_template_id 预期模板 id
mutation 对原始表头的变异说明
sheet 工作表名称
rows 数据行数
notes 人类可读说明
format 文件格式,如 xlsx

常见变异方式

变异键 含义
普通键值对 将原表头名替换为新名字
_order: "reversed" 倒置列序
_extra 增加额外列
_drop 删除某个列
_keep 仅保留部分列
erDiagram
  MANIFEST {
    string generated_at
    int case_id
  }

  COUNTS {
    int bill
    int call
    int industry
    int edge
    int "full-exact"
    int "full-variant"
  }

  FILE_ENTRY {
    string test_id
    string category
    string path
    int template_id
    int expected_template_id
    object mutation
    string sheet
    int rows
    string notes
    string format
  }

  MANIFEST ||--o{ COUNTS : "包含"
  MANIFEST ||--o{ FILE_ENTRY : "包含"

图示来源

  • manifest.json:1-20

章节来源

  • manifest.json:1-200

前端代码质量配置:ESLint、Stylelint、Vitest

ESLint

前端 ESLint 位于 ai-electron/frontend/eslint.config.mjs,主要特点如下:

  • 忽略 node_modules、dist、public、build、git、IDE、sh、md、woff、ttf、d.ts 和快照目录。
  • Vue 文件使用 vue-eslint-parser,TypeScript 使用 @typescript-eslint/parser,JS 使用 @babel/eslint-parser。
  • TypeScript 推荐规则启用,但关闭了一些较严格的规则,如 ban-ts-comment、ban-types、no-explicit-any、no-unused-vars 等。
  • JS 使用 Babel 解析,并启用装饰器 legacy 语法。
  • Prettier 集成,打印宽度 120,分号结尾,单引号,尾随逗号全开。

    graph TB
    Files["前端源码<br/>*.vue / *.ts / *.tsx / *.js"] --> ESLint["eslint.config.mjs"]
    ESLint --> Vue["Vue 解析器"]
    ESLint --> TS["TypeScript 解析器"]
    ESLint --> JS["Babel 解析器"]
    ESLint --> Prettier["Prettier 格式化规则"]
    

图示来源

  • eslint.config.mjs:1-177

章节来源

  • eslint.config.mjs:1-177

Stylelint

前端 Stylelint 位于 ai-electron/frontend/stylelint.config.mjs,主要特点如下:

  • 基础规则来自 stylelint-config-standard 和 stylelint-config-standard-less。
  • Vue HTML/CSS 使用 postcss-html,LESS 使用 postcss-less,SCSS 使用 postcss-scss。
  • 允许 Vue 专用伪类和伪元素,如 global、deep、v-deep、v-global、v-slotted。
  • 忽略大量规则以适配现有样式工程,例如媒体查询范围、选择器命名、at-rule 白名单、rpx 单位等。
  • 与 Prettier 集成,禁用部分 Prettier 的 CSS 重写偏好。

    graph TB
    Styles["样式文件<br/>*.vue / *.less / *.scss / *.css"] --> Stylelint["stylelint.config.mjs"]
    Stylelint --> Standard["标准规则"]
    Stylelint --> Less["LESS 规则"]
    Stylelint --> SCSS["SCSS 规则"]
    Stylelint --> Vue["Vue 扩展规则"]
    Stylelint --> Prettier["Prettier 集成"]
    

图示来源

  • stylelint.config.mjs:1-121

章节来源

  • stylelint.config.mjs:1-121

Vitest

Electron 项目的 Vitest 配置位于 ai-electron/vitest.config.mts,当前行为是:

  • 测试文件匹配 electron/**/*.test.ts。
  • frontend/ 有独立前端工程,不在此处执行。
  • 没有测试时允许通过,便于 CI 不因缺少测试文件而失败。
  • codex 模块的单测已移除,但配置保留供后续主进程测试使用。

需要特别注意:前端业务代码并未在 package.json 中看到显式 vitest 脚本,也没有在前端 package.json 中引入 vitest 依赖。因此当前前端测试能力较弱,更适合补充单元测试和页面级测试。

flowchart TD
    Root["ai-electron/vitest.config.mts"] --> Include["匹配 electron/**/*.test.ts"]
    Root --> PassNoTests["passWithNoTests=true"]
    Frontend["ai-electron/frontend/"] --> Separate["独立前端工程<br/>无统一测试脚本"]

图示来源

  • vitest.config.mts:1-10
  • package.json:1-30

章节来源

  • vitest.config.mts:1-10
  • package.json:1-30

后端测试目录约定

后端 Java 项目遵循 Maven 标准布局:

目录 含义
ai-server/src/main/java 服务端主代码
ai-server/src/test/java 服务端单元测试
ai-server/src/test/resources 服务端测试资源
ai-gateway/src/main/java 网关主代码
ai-gateway/src/test/java 网关单元测试
ai-gateway/src/test/python 网关相关的 Python 测试或辅助脚本

从 pom.xml 可见,后端依赖 spring-boot-starter-test 和 reactor-test,说明测试框架基于 Spring Boot Test,可能使用 JUnit、Mockito 及响应式测试工具。不过当前仓库中没有发现 surefire/failsafe 插件的自定义配置,也没有看到覆盖率插件(如 JaCoCo)的显式启用。

因此,当前后端测试约定更接近“默认 Maven 约定 + Spring Boot Test”,而不是一个强约束的测试工程。

graph TB
    MainJava["src/main/java"] --> ServerMain["ai-server 主代码"]
    MainJava --> GatewayMain["ai-gateway 主代码"]
    TestJava["src/test/java"] --> ServerTest["ai-server 单元测试"]
    TestJava --> GatewayTest["ai-gateway 单元测试"]
    TestResources["src/test/resources"] --> ServerResources["ai-server 测试资源"]
    TestPython["src/test/python"] --> GatewayPython["ai-gateway Python 测试"]

图示来源

  • pom.xml:26-97

章节来源

  • pom.xml:26-97

新增测试用例流程

新增后端 JUnit 单元测试

  1. 在 ai-server/src/test/java 或 ai-gateway/src/test/java 下创建对应包结构。
  2. 使用 Spring Boot Test 编写测试类。
  3. 对确定性逻辑(指纹、归一化、同义词、打分、绑定、计划)优先写单测。
  4. 对涉及数据库或外部服务的逻辑,考虑使用测试容器或内存数据库。
  5. 确保测试类命名清晰,例如 HeaderScorerTest、AiTemplateMatcherTest。

新增 LLM 模板匹配测试用例

  1. 在 docs/testing/fixtures/ai-llm-match-20261026 下新增或修改样本文件。
    • 账单类放在 bills/。
    • 话单类放在 calls/。
    • 边界场景放在 edge/。
    • 回归重测放在 retest/。
  2. 在 manifest.json 中新增一条用例,填写 test_id、category、path、expected_template_id、mutation、sheet、rows、notes、format。
  3. 运行 python docs/testing/fixtures/ai-llm-match-20261026/run_tests.py <group>。
  4. 查看 docs/testing/fixtures/ai-llm-match-20261026/results/ 下的最新 JSON 结果。
  5. 如果结果不符合预期,先确认是“既有匹配器直中”还是“AI 兜底链路”。

新增前端测试

当前前端缺少统一的测试脚本。建议:

  1. 在 ai-electron/frontend 下新增单元测试目录,例如 __tests__/。
  2. 使用 Vitest 或 Jest 编写组件、工具函数、store 测试。
  3. 在 package.json 中增加测试脚本,例如 test、test:watch、test:coverage。
  4. 将 lint:eslint、lint:stylelint、type:check 纳入本地提交钩子和 CI。

章节来源

  • ai-template-match-test-cases.md:1-111
  • manifest.json:1-200
  • run_tests.py:1-60

修复回归问题与调试 LLM 匹配失败

常见问题定位

当 LLM 模板匹配失败时,按以下顺序排查:

  1. 是否被既有匹配器直中
    同表头或集合匹配成功的文件不会进入 AI 链路。这是设计行为。若目标是验证 AI,需要使用同义词、相似词、乱序、缺必填或噪音表头。

  2. 上传阶段是否误配模板
    查看上传结果中的 template_id 是否与 expected_template_id 一致。如果既有匹配器把话单误判为通信登记信息,属于上传阶段问题,不是 AI 模型的问题。

  3. AI 是否被触发
    检查 matched_by 是否为 SCORE、HEADER_CACHE 或 LLM。如果既有条目直接走既有清洗,则不会出现 AI 判定日志。

  4. 是否被 verify 闸门拦截
    如果模型选对模板但必填列未绑定或抽样错误率高,会进入 NEED_REVIEW。这说明防御机制生效,不代表匹配完全失败。

  5. 数据库结果是否一致
    使用 run_tests.py 自带的 db_jobs、db_batch、db_ai_template 逻辑核对 ai_clean_job、ai_clean_batch、ai_clean_template。

  6. 是否是并发或模型超时问题
    本地 Ollama qwen 模型可能只支持单会话并发。默认并发过高会导致重试、超时和批次卡住。

调试步骤

flowchart TD
    Fail["LLM 匹配失败"] --> CheckDirect["检查是否既有直中"]
    CheckDirect -->|是| DesignOK["符合设计:已有匹配器优先"]
    CheckDirect -->|否| CheckUpload["检查上传模板是否误配"]
    CheckUpload -->|误配| FixUploader["修复上传阶段匹配逻辑"]
    CheckUpload -->|正确| CheckAICall["检查 AI 是否被触发"]
    CheckAICall -->|未触发| CheckVerify["检查 verify 闸门"]
    CheckAICall -->|已触发| CheckResult["检查结果 JSON 与数据库"]
    CheckVerify -->|NEED_REVIEW| ReviewCase["人工复核或改进绑定"]
    CheckResult --> MatchOK{"结果是否符合预期"}
    MatchOK -->|是| Record["记录为已知差异或观察项"]
    MatchOK -->|否| Investigate["调查匹配分数、模板覆盖率和模型输出"]

图示来源

  • ai-template-match-test-cases.md:1-111
  • ai-llm-template-match-bug-report-20261026.md:1-200
  • run_tests.py:60-200

典型回归修复案例

编号 问题 修复方向
F-01 交通银行同义表被错配为农商行模板,必填缺失导致 0 行入库 加强文件侧覆盖率门槛,收紧模糊词相似度规则
F-01B 导出话单变体被误判为通信登记信息 修复上传阶段部分匹配逻辑
F-03B AI 动态表方向字典整串写入单元格 修正方向字段归一化
F-05 出口 B 新建 AI 表与既有模板同名,日志不可区分 使用 AI_ 前缀和导入备注区分
F-06 二次 askLlm 返回越界序号 增加序号校验
F-07 语义命中模板但确定性闸门拦截 改进必填列绑定或闸门判断

章节来源

  • ai-llm-template-match-bug-report-20261026.md:1-200
  • ai-template-match-test-cases.md:1-111

持续集成、覆盖率与发布前检查建议

当前状态

  • 前端有明确的 lint 脚本:lint:eslint、lint:prettier、lint:stylelint、lint:all、type:check。
  • 前端没有统一的测试脚本,也没有在 package.json 中引入 vitest 依赖。
  • Electron 根目录有 Vitest 配置,但只匹配主进程测试文件。
  • 后端使用 Spring Boot Test,但没有看到 surefire/failsafe 或 JaCoCo 的显式配置。
  • LLM 模板匹配测试目前更像本地实验脚本,不适合直接作为高可靠 CI 步骤。

建议的 CI 流水线

flowchart TD
    Push["推送代码"] --> Install["安装依赖"]
    Install --> TypeCheck["TypeScript/Vue 类型检查"]
    TypeCheck --> ESLint["ESLint"]
    ESLint --> Prettier["Prettier 检查"]
    Prettier --> Stylelint["Stylelint"]
    Stylelint --> UnitTests["后端 JUnit 单元测试"]
    UnitTests --> Coverage["生成后端覆盖率"]
    Coverage --> LLMSmoke["LLM 模板匹配冒烟测试"]
    LLMSmoke --> Build["构建前端与 Electron"]
    Build --> Report["生成构建报告"]
    Report --> Release["发布前检查"]

图示来源

  • package.json:1-30
  • eslint.config.mjs:1-177
  • stylelint.config.mjs:1-121
  • vitest.config.mts:1-10

具体建议

代码质量

  • 保持前端 pnpm lint:all 在本地可运行。
  • 将 lint:eslint、lint:stylelint、type:check 加入 pre-commit 或 CI。
  • 对于新增前端测试,逐步缩小 eslint/vue/ts 规则的宽松配置,避免一次性引入过多错误。

覆盖率

  • 后端建议使用 JaCoCo 生成覆盖率报告,并将阈值纳入 CI。
  • 对 AI 清洗核心逻辑(打分、绑定、计划、verify)设定较高覆盖率要求。
  • 对 UI 展示逻辑和第三方包装层可适当降低要求。

持续集成

  • 后端单元测试放在 CI 主干分支保护之前。
  • LLM 模板匹配测试可作为可选或定时任务,因为它依赖外部模型、数据库和服务状态。
  • 对 manifest.json 变更进行 diff 检查,防止意外丢失用例。
  • 对 results/ 中关键结果做快照对比,但不把大体积二进制产物作为必要提交。

发布前检查

建议发布前至少完成:

  1. pnpm type:check
  2. pnpm lint:eslint
  3. pnpm lint:prettier
  4. pnpm lint:stylelint
  5. 后端 JUnit 全量通过
  6. 至少一次 LLM 模板匹配冒烟测试
  7. 构建产物可用
  8. 问题报告中所有标记“已修复”的用例重新执行并通过

章节来源

  • package.json:1-30
  • vitest.config.mts:1-10
  • ai-template-match-test-cases.md:1-111

结论

该仓库的测试体系以“确定性单测 + 端到端链路 + LLM 模板匹配夹具”为主轴。ai-template-match-test-cases.md 提供了测试范围和设计口径,ai-llm-template-match-bug-report-20261026.md 提供了缺陷复现与修复上下文,而 fixtures/ai-llm-match-20261026 下的 generate.py、run_tests.py、manifest.json 构成了 LLM 模板匹配测试的数据、执行器和索引。

前端代码质量工具链已经比较完善,但测试能力仍较弱;后端有 Spring Boot Test 基础,但缺少统一的覆盖率与 CI 配置。未来应优先补齐前端单元测试、后端覆盖率目标和稳定的 LLM 冒烟测试流程,使 AI 模板匹配链路既能被快速回归,又能稳定支撑生产数据清洗。