# 增强测试系统 — 全面测试计划 v3.0 > 日期: 2026-06-19 | 対象: feat/enhanced-test-phase1 / main > 測試范围: 全模块 34/36 + web API/Worker | 7 维度 | ~518 testing points --- ## 测试策略 ### 覆盖原则 - **Boil the Lake**: AI 使完整性成本趋近于零,推荐完整覆盖而非 happy path - **按风险优先级**: 管道中枢 > 外部依赖调用 > 数据模型 > 辅助工具 - **维度**: 功能正确性 / 错误恢复 / 边界值 / 并发安全 / 性能衰减 / 安全防护 / 环境依赖 ### 测试层次 ``` L0: 模块单元 ─ 全模块独立测试 (pytest, ~80 tests) ├── cobol_testgen (API/cond/core/coverage/design/read/output/models) ├── hina (classifier/gate/gcov/agent/retry/strategy) ├── orchestrator ← 新增: 管道中枢 ├── web (api/worker) ← 新增: API 端点 + Worker ├── agents (LLM/Parser/Data/Diagnostic) ← 新增 ├── config (Config/Mapping) ← 新增 ├── runners (4文件) ← 新增 ├── jcl (parser/executor) ← 新增 ├── quality / storage / preprocessor ← 新增 └── data models (+ dataclass 复杂逻辑) L1: 结合测试 ─ 模块间数据流 (pytest, ~25 tests) ├── extract_structure → generate_data ├── HINA 分类 → strategy 模板映射 ├── quality gate → orchestrator 循环 ├── API → Worker → Orchestrator 全链路 ← 新增 ├── LLM 链 (Agent1→2→3) 异常回退 ← 新增 ├── Config → Runner 选择路由 ← 新增 ├── HINA + gcov → 报告渲染 ← 新增 └── JCL 解析 → 执行 ← 新增 L2: HINA 统合测试 (test-data/ 10 programs, ~10 tests) ├── HINA001: 1:1 マッチング ├── HINA005: IF条件分岐 ├── HINA025: CALL └── HINA101: EXEC SQL L3: 実 COBOL 验证 (jcl-cobol-git/ 4 programs, ~4 tests) ├── CRDVAL / CRDCALC / CRDRPT / GENDATA └── 实际金额计算一致性确认 L4: 回归测试 ─ 既存 42 测试完全通过 L5: 非功能测试 ─ 性能/并发/安全 ← 新增层级 ├── 大文件上传 10MB 边界 ├── Worker 并发任务处理 ├── 路径遍历/文件类型校验 └── LLM 超时/隔离时优雅降级 L6: E2E UI 测试 ─ Playwright 浏览器测试 ← 新增层级 ├── 上传页加载/表单元素 ├── 文件上传 → 202 响应 → 轮询状态 └── 结果页面字段表格/摘要 ``` ### 测试手法 | 手法 | 适用层级 | 说明 | |:-----|:--------|:------| | TDD (红绿) | L0 | 先写测试,再实现 | | Golden 测试 | L2-L3 | 已知期望值对比 | | 模糊测试 | L1 | 异常 COBOL 输入容错 | | 边界值分析 | L0, L5 | PIC 桁数边界、空值、极值 | | 错误注入 | L0-L1 | LLM timeout/malformed、cobc 编译失败 | | 降级测试 | L1 | gcov failure/absence 时降级确认 | | 竞态条件 | L5 | 并发 Worker + Task JSON 文件读写 | | 安全审计 | L5 | 路径遍历、类型校验、信息泄露 | --- ## L0: 模块单元测试 ### 0.1 cobol_testgen API (保持 + 补充) 测试文件: `tests/test_cobol_testgen.py` | # | 测试名 | 内容 | 输入 | 期待输出 | |:-:|:-------|:-----|:-----|:---------| | UT-01 | extract_structure: 空程序 | 空字符串 | `{"total_branches": 0}` | | UT-02 | extract_structure: IF 1个 | `IF A > B ... ELSE ...` | branches=2, decisions=1 | | UT-03 | extract_structure: EVALUATE | `EVALUATE X WHEN 1 ... WHEN OTHER` | decisions=1, WHEN 数确认 | | UT-04 | extract_structure: 多文件 | 3文件程序 | file_count=3 | | UT-05 | extract_structure: CALL | `CALL 'SUBPGM'` | has_call=True | | UT-06 | extract_structure: SEARCH ALL | OCCURS+SEARCH ALL | has_search_all=True | | UT-07 | extract_structure: 固定格式 | 7桁目代码固定格式 | 正常解析(段落数>0) | | UT-08 | extract_structure: GOBACK | GOBACK 语句 | 非 STOP RUN 但正确退出 | | UT-09 | extract_structure: ALTER | ALTER X TO PROCEED TO Y | 标记 alter 语句 | | UT-10 | extract_structure: ENTRY | ENTRY 'ENTPT' | 多入口点识别 | | UT-11 | extract_structure: 无 PROCEDURE DIVISION | 数据部只有 ID/DATA | 空结构返回,不崩溃 | | UT-12 | generate_data: 正常生成 | IF 程序 | ≥2 条数据 | | UT-13 | generate_data: 空程序 | 无分支 | 0 或 1 条 | | UT-14 | generate_data: 深嵌套 REDEFINES | A REDEFINES B REDEFINES C | 所有变体字段正确取值 | | UT-15 | generate_data: OCCURS DEPENDING 最大 | ODO 到达最大值 | 数组长度正确 | | UT-16 | generate_data: PIC 9(18) | 超出 64-bit 范围 | 不溢出,字符串表示 | | UT-17 | generate_data: SIGN LEADING/TRAILING SEPARATE | SIGN IS LEADING SEPARATE | 符号位正确 | | UT-18 | incremental_supplement: 差分 | 未覆盖 ID 指定 | 对应 ID 数据 | | UT-19 | incremental_supplement: 不存在 ID | [-1] | 空列表 | | UT-20 | check_coverage: 静态报告 | structure 仅 | "note" 含静态限制描述 | ### 0.2 cobol_testgen cond (新增) 测试文件: `tests/cobol_testgen/test_cond.py` | # | 测试名 | 内容 | 期待 | |:-:|:-------|:-----|:------| | CO-01 | parse_single_condition: 数值比较 | `A > 100` | CondLeaf(> 100) | | CO-02 | parse_single_condition: 文字列 | `B = 'Y'` | CondLeaf(= 'Y') | | CO-03 | parse_compound: AND | `A > 0 AND B < 5` | CondAnd(>0, <5) | | CO-04 | parse_compound: OR | `A = 1 OR B = 2` | CondOr(=1, =2) | | CO-05 | parse_compound: 嵌套 AND+OR | `(A > 0 AND B < 5) OR C = 1` | 正确优先级 | | CO-06 | mcdc_sets: IF | IF A > 100 | 2 sets | | CO-07 | mcdc_sets: AND | A > 0 AND B < 5 | 3 sets (MCDC) | | CO-08 | mcdc_sets: OR | A = 1 OR B = 2 | 3 sets (MCDC) | | CO-09 | evaluate_tree: 真路径 | A=200 当 A>100 | True | | CO-10 | evaluate_tree: 假路径 | A=50 当 A>100 | False | ### 0.3 cobol_testgen core (新增) 测试文件: `tests/cobol_testgen/test_core.py` | # | 测试名 | 内容 | 期待 | |:-:|:-------|:-----|:------| | CE-01 | scan_paragraphs: 正常 | 3段落 | 3个段落 | | CE-02 | scan_paragraphs: 空程序 | 无段落 | 空列表 | | CE-03 | build_branch_tree: IF | IF 语句 | BrIf 节点 | | CE-04 | build_branch_tree: EVALUATE | EVALUATE 语句 | BrEval 节点 | | CE-05 | build_branch_tree: PERFORM | PERFORM VARYING | BrPerform 含循环 | | CE-06 | build_branch_tree: SEARCH ALL | SEARCH ALL | BrSearch 节点 | | CE-07 | classify_field_roles: IO / WORKING / LINKAGE | IO / WORKING / LINKAGE 字段 | 正确角色分类 | | CE-08 | propagate_assignments: 嵌套组 | 子字段赋值传播 | 子字段继承值 | | CE-09 | propagate_assignments: REDEFINES | REDEFINES 字段赋值 | 共享起始位置 | ### 0.4 cobol_testgen coverage (新增) 测试文件: `tests/cobol_testgen/test_coverage.py` | # | 测试名 | 内容 | 期待 | |:-:|:-------|:-----|:------| | CV-01 | collect_decision_points: IF | 1个 IF | 1个决策点 (2分支) | | CV-02 | collect_decision_points: EVALUATE | EVALUATE 4 WHEN | 1决策点 4分支 | | CV-03 | collect_decision_points: SEARCH ALL | SEARCH ALL | 1决策点 | | CV-04 | mark_coverage: 全覆盖 | 所有分支有测试数据 | 覆盖率 100% | | CV-05 | mark_coverage: 部分覆盖 | 一半分支有数据 | 覆盖率 50% | | CV-06 | mark_coverage: 零覆盖 | 无测试数据 | 覆盖率 0% | | CV-07 | locate_decision_lines: 源码定位 | 已知决策点 | 正确行号 | | CV-08 | generate_html_report: 基本渲染 | 决策点+统计 | 有效 HTML | ### 0.5 cobol_testgen design (新增) 测试文件: `tests/cobol_testgen/test_design.py` | # | 测试名 | 内容 | 期待 | |:-:|:-------|:-----|:------| | DE-01 | enum_paths: 2层嵌套 | IF 内 IF | 路径枚举数正确 | | DE-02 | apply_constraint: 数值约束 | field > 100 | 字段值 > 100 | | DE-03 | apply_constraint: 文字约束 | field = 'ABC' | 字段值 'ABC' | | DE-04 | apply_constraint: MCDC 约束 | AND 条件 | 满足指定真值 | | DE-05 | generate_records: 基本 | 已知分支路径 | 记录字段值正确 | | DE-06 | sync_redefined_fields: REDEFINES | REDEFINES 字段 | 同步后值一致 | | DE-07 | apply_occurs_depending: ODO | OCCURS DEPENDING ON | 数组长度按依赖字段 | | DE-08 | make_base_record: 序列值 | seq_num=1 | 字段含序列值 | ### 0.6 cobol_testgen read (新增) 测试文件: `tests/cobol_testgen/test_read.py` | # | 测试名 | 内容 | 期待 | |:-:|:-------|:-----|:------| | RD-01 | preprocess: 固定格式 | 7桁目代码 | 正确提取 | | RD-02 | preprocess: 自由格式 | `>>SOURCE FORMAT IS FREE` | 正确提取 | | RD-03 | preprocess: COPY 展开 | `COPY CPYBOOK` | COPY 内容展开 | | RD-04 | preprocess: 嵌套 COPY | COPY 内含 COPY | 递归展开 | | RD-05 | extract_data_division: 多段 | ID/DATA/PROCEDURE | DATA DIVISION 文本 | | RD-06 | parse_pic: 简单 | PIC 9(4) | PicInfo(4, 0) | | RD-07 | parse_pic: 带小数 | PIC S9(7)V99 | PicInfo(9, 2, signed) | | RD-08 | parse_pic: COMP-3 | PIC S9(7)V99 COMP-3 | signed, COMP-3 | | RD-09 | parse_data_division: 层级 | 01/05/10/15 | 正确层级树 | | RD-10 | parse_data_division: 88-level | 88 AA VALUE 'X' | is_88 识别 | | RD-11 | parse_data_division: REDEFINES | 字段含 REDEFINES | redefines 属性 | | RD-12 | parse_data_division: OCCURS | OCCURS 10 TIMES | occurs=10 | | RD-13 | resolve_copybooks: 多路径 | 搜索多目录 | 找到 COPY | ### 0.7 cobol_testgen output (新增) 测试文件: `tests/cobol_testgen/test_output.py` | # | 测试名 | 内容 | 期待 | |:-:|:-------|:-----|:------| | OU-01 | output_json: 基本 | 3条测试记录 | 有效 JSON 文件 | | OU-02 | output_input_files: 多方向 | I-O / INPUT 字段 | 文件输出正确 | ### 0.8 HINA Classifier (保持) 测试文件: `tests/hina/test_classifier.py` | # | 测试名 | 内容 | 输入 | 期待 | |:-:|:-------|:-----|:-----|:------| | HC-01 | L1: DB操作 | `EXEC SQL SELECT` | category="DB操作" ≥90% | | HC-02 | L1: 子程序调用 | `CALL ... LINKAGE SECTION` | category="子程序调用" ≥90% | | HC-03 | L1: SORT | `SORT WORK-FILE ON KEY` | category="SORT" ≥90% | | HC-04 | L1: IS INITIAL | `PROGRAM-ID. X IS INITIAL.` | category="IS INITIAL" ≥90% | | HC-05 | L1: 编辑输出 | `WRITE AFTER ADVANCING` | category="编辑输出" ≥80% | | HC-06 | L1: 文件编成 | `ORGANIZATION IS` | category="文件编成" ≥90% | | HC-07 | 关键字重叠 | DB操作+CALL 两者 | 最大确信度关键字胜出 | | HC-08 | compute_confidence: L1≥90% | L1 仅 | method="keyword" | | HC-09 | compute_confidence: LLM结果 | LLM 结果 | method="hybrid" | | HC-10 | compute_confidence: 两者无 | 关键字无+LLM无 | category="unknown" confidence=0 | ### 0.9 HINA Strategy (保持) 测试文件: `tests/hina/test_strategy.py` | # | 测试名 | 内容 | 期待 | |:-:|:-------|:-----|:------| | HS-01 | get_strategy: マッチング | 9 required items | | HS-02 | get_strategy: キーブレイク | 6 required items | | HS-03 | get_strategy: 条件分岐 | 4 required items | | HS-04 | get_strategy: 未知类型 | 空模板 | | HS-05 | supplement: マーカー追加 | マーカーレコード含む list | | HS-06 | supplement_only: 特定间隙 | 指定 ID のみマーカー | ### 0.10 HINA Gate (保持) 测试文件: `tests/hina/test_gate.py` | # | 测试名 | 内容 | 输入 | 期待 | |:-:|:-------|:-----|:-----|:------| | QG-01 | 全通过 | branch≥95%, paragraph=100% | passed=True | | QG-02 | 分岐不足 | branch=80% | passed=False, decision_gaps 有 | | QG-03 | 段落不足 | paragraph=0.5 | passed=False | | QG-04 | 数据无 | empty list | passed=False, no_data=True | | QG-05 | 评分计算 | branch=0.92, para=1.0 | score=0.976 | ### 0.11 HINA Retry (保持 + 补充) 测试文件: `tests/hina/test_retry.py` | # | 测试名 | 内容 | 期待 | |:-:|:-------|:-----|:------| | RH-01 | 即时 PASS | 1次 PASS | heal=0, simple=0 | | RH-02 | heal 恢复 | BLOCKED→环境修复→PASS | heal=1, simple=0 | | RH-03 | simple 恢复 | BLOCKED→重试→PASS | heal=0, simple=1 | | RH-04 | 上限超限 | 全部 FAIL | status=FATAL | | RH-05 | QUALITY_WARN 不需重试 | QUALITY_WARN→立即返回 | heal=0, simple=0 | | RH-06 | heal 环境修复失败 | heal 尝试仍然 BLOCKED | simple 回退 | ← 新增 | | RH-07 | 并发重试计数 | 同时 heal + simple | 计数不竞争 | ← 新增 | ### 0.12 HINA gcov_collector (新增) 测试文件: `tests/hina/test_gcov_collector.py` | # | 测试名 | 内容 | 期待 | |:-:|:-------|:-----|:------| | GC-01 | collect_gcov: cobc 未安装 | 无 cobc 命令 | available=False, reason=cobc_not_found | | GC-02 | collect_gcov: .gcda/.gcno 不存在 | 工作目录无覆盖文件 | available=False, reason=no_coverage_data | | GC-03 | collect_gcov: 正常 | 有效 .gcda/.gcno | available=True, line_rate>0 | ### 0.13 HINA Agent (LLM 分类) (补充) 测试文件: `tests/hina/test_agent.py` | # | 测试名 | 内容 | 期待 | |:-:|:-------|:-----|:------| | HA-01 | classify_with_llm: 正常 | 有效结构体 | 返回 dict 含 category | | HA-02 | classify_with_llm: LLM 返回非法 JSON | LLM 返回乱码 | fallback 分类 | ← 新增 | | HA-03 | classify_with_llm: LLM 返回空字符串 | LLM 返回 "" | fallback 分类 | ← 新增 | | HA-04 | classify_with_llm: LLM 超时 | httpx.TimeoutException | fallback + 日志输出 | ← 新增 | | HA-05 | _parse_llm_response: 合法 JSON | `{"category": "DB操作"}` | 解析成功 | | HA-06 | _parse_llm_response: 非法 JSON | "暂无" | try/except 不崩溃 | | HA-07 | _parse_llm_response: 含 markdown 包裹 | `` ```json ... ``` `` | 正确提取 JSON | | HA-08 | _fallback_classification: 纯 DB | EXEC SQL 无其他 | "DB操作" | | HA-09 | _fallback_classification: 纯 CALL | CALL 无 SQL | "子程序调用" | | HA-10 | _fallback_classification: 两者无 | 无关键字匹配 | "unknown" | ### 0.14 orchestrator (新增 — 🔥 高风险) 测试文件: `tests/test_orchestrator.py` | # | 测试名 | 内容 | 期待 | |:-:|:-------|:-----|:------| | OR-01 | run_pipeline: 正常路径 | 所有组件正常工作 | VerificationRun 返回, status=PASS | | OR-02 | run_pipeline: cobol_testgen 返回空 | extract_structure 空 | pipeline 继续, 适当错误 | | OR-03 | run_pipeline: HINA Agent 异常 | classify_with_llm 抛出 | 不阻断 pipeline, 日志记录 | | OR-04 | run_pipeline: quality gate 失败 | 覆盖率不足 | QUALITY_WARN 设置 | | OR-05 | run_pipeline: gcov 不可用 | collect_gcov 失败 | available=False, pipeline 继续 | | OR-06 | run_pipeline: Java 编译失败 | mvn 返回非零 | status=BLOCKED, exit_code≠0 | | OR-07 | run_pipeline: cobc 编译失败 | cobc 返回非零 | status=BLOCKED | | OR-08 | run_pipeline: Runner 运行失败 | run() 返回非零 | status=BLOCKED | | OR-09 | run_pipeline: LLM 全部回退 | Agent1/2/3 全部 fallback | 无崩溃, 结果含 fallback 标记 | | OR-10 | run_pipeline: 无 LLM API key | 环境变量不存在 | Agent1/2/3 使用默认值/failback | | OR-11 | run_pipeline: 大文件 (10000行 COBOL) | 大型输入文件 | 30秒内完成, 不超时 | ← 新增非功能 | | OR-12 | _done: 正常结束 | 标准 VerificationRun | 正确写入 report_path | ### 0.15 web/api.py (新增 — 🔥 高风险) 测试文件: `tests/web/test_api.py` | # | 测试名 | 内容 | 期待 | |:-:|:-------|:-----|:------| | WA-01 | GET / 返回 HTML | 无参数 | 200, Content-Type text/html | | WA-02 | POST /verify 正常上传 | 4个文件 + runner= native | 202, 含 task_id, status=queued | | WA-03 | POST /verify 文件超 10MB | 超大文件 | 413 | | WA-04 | POST /verify 缺少文件 | 3个文件 | 422 或 400 | | WA-05 | POST /verify runner=spark | spark 模式 | 202, runner=spark | | WA-06 | GET /status 存在任务 | 有效 task_id | 200, 含 status | | WA-07 | GET /status 不存在 | 无效 task_id | 404 | | WA-08 | GET /status 任务完成 | 结果已写入 | status=done, fields 含数据 | | WA-09 | GET /fields 正常 | 有效 task_id | 200, 字段列表 | | WA-10 | GET /fields 任务不存在 | 无效 task_id | 404 | | WA-11 | GET / 表单元素存在 | 渲染检查 | 5 个文件/输入元素 | | WA-12 | 路径遍历防护 | `../../../etc/passwd` 文件上传 | 拒绝或 sanitize | ← 安全 | ### 0.16 web/worker.py (新增 — 🔥 高风险) 测试文件: `tests/web/test_worker.py` | # | 测试名 | 内容 | 期待 | |:-:|:-------|:-----|:------| | WR-01 | main: 无任务 | 空 tasks/ 目录 | 无操作, 继续循环 | | WR-02 | main: 正常任务 | queued 任务文件 | 处理, 状态→done | | WR-03 | main: 任务文件损坏 | 非法 JSON | 异常处理, 不崩溃 | | WR-04 | main: runner=spark 但无 spark-submit | spark-submit 不在 PATH | 状态→blocked, 含 reason | | WR-05 | main: 并发任务 | 2个 queued 任务 | 依次处理, 各有结果 | | WR-06 | main: Worker 中断恢复 | running 状态→重启 Worker | running 任务可重新处理 | | WR-07 | Task 文件状态机 | queued→running→done 转换 | 状态不可逆 | ### 0.17 agents 模块 (新增) 测试文件: `tests/agents/test_agents.py` | # | 测试名 | 内容 | 期待 | |:-:|:-------|:-----|:------| | AG-01 | LLMClient.call: 正常 | 消息列表 | 返回响应字符串 | | AG-02 | LLMClient.call: 缓存命中 | 相同消息两次调用 | 第二次返回缓存, 不调 API | | AG-03 | LLMClient.call: 超时 | httpx 超时 | 抛出异常 | | AG-04 | LLMClient.call: 重试成功 | 首次 500, 重试 200 | 最终成功返回 | | AG-05 | LLMClient.call: 重试耗尽 | 全部失败 | 抛出异常 | | AG-06 | Agent1Parser.parse: 正常 COPYBOOK | 合法字段列表 | 返回 FieldTree, 字段数正确 | | AG-07 | Agent1Parser.parse: LLM 返回非法 JSON | LLM 返回 `not json` | 返回 FieldTree(copybook_name="parse_error") | | AG-08 | Agent1Parser.parse: JSON 缺失 fields | `{}` | 空 FieldTree, 不崩溃 | | AG-09 | Agent2Data.design: 正常 | 已知 FieldTree | TestSuite 含测试 case | | AG-10 | Agent2Data.design: LLM 返回非法 | LLM 异常 | 返回 TestSuite 含 TC-FALLBACK | | AG-11 | Agent2Data.design: spark_mode | spark=True | SparkConfig 生成 | | AG-12 | Agent3Diagnostic.analyze: 正常 | FieldResult MISMATCH | 返回诊断字符串 | ### 0.18 config (新增) 测试文件: `tests/config/test_config.py` | # | 测试名 | 内容 | 期待 | |:-:|:-------|:-----|:------| | CF-01 | Config: 默认值 | 无参数 | runner_mode=native, llm_model=gpt-4o-mini | | CF-02 | Config: from_toml | 有效 TOML 文件 | 正确解析 | | CF-03 | Config: from_toml 文件不存在 | 不存在路径 | 默认值 | | CF-04 | Config: from_toml 非法 TOML | 格式错误 | 妥善处理/不崩溃 | | CF-05 | MappingConfig: 正常 | 有效 YAML 映射 | FieldMapping 列表 | | CF-06 | MappingConfig: 空映射 | 空 YAML | 空列表 | | CF-07 | MappingConfig: 格式错误 | 非法 YAML | 解析错误处理 | ### 0.19 runners (新增) 测试文件: `tests/runners/test_runners.py` | # | 测试名 | 内容 | 期待 | |:-:|:-------|:-----|:------| | RN-01 | Runner 抽象类 | 实例化 | TypeError (抽象) | | RN-02 | NativeJavaRunner.compile: 成功 | mvn 成功 | BuildResult(success=True) | | RN-03 | NativeJavaRunner.compile: Maven 失败 | mvn 非零退出 | BuildResult(success=False) | | RN-04 | NativeJavaRunner.run: 正常 | jar 输出 JSON | RunResult(records 含数据) | | RN-05 | NativeJavaRunner.run: 无输出 | jar 输出空 | RunResult(records=[]) | | RN-06 | CobolRunner.compile: 成功 | cobc 成功 | BuildResult(success=True) | | RN-07 | CobolRunner.compile: 编译错误 | cobc 语法错误 | BuildResult(success=False) | | RN-08 | CobolRunner.compile: gcov 参数 | gcov=True | 含 -fprofile-arcs 参数 | | RN-09 | CobolRunner.run: 正常 | 二进制执行 | RunResult(success=True) | | RN-10 | DataWriter.write: 正常 | TestSuite 数据 | 文件写入正确 | ### 0.20 jcl (新增) 测试文件: `tests/jcl/test_jcl.py` | # | 测试名 | 内容 | 期待 | |:-:|:-------|:-----|:------| | JC-01 | parse_jcl: 基本 JOB | JOB + 2 STEP | 1个 Job, 2个 JobStep | | JC-02 | parse_jcl: COND 参数 | COND=(0,NE) | CondParam(0, NE) | | JC-03 | parse_jcl: DD 语句 | DD DSN=..., DISP=SHR | DDEntry 含 DSN/DISP | | JC-04 | parse_jcl: 续行 | 多行 DD 语句 | 合并为单行 | | JC-05 | parse_jcl: 空文件 | 无内容 | 返回 None | | JC-06 | parse_jcl: 注释行 | `//* COMMENT` | 跳过注释 | | JC-07 | parse_jcl: 文件不存在 | 无效路径 | 返回 None | | JC-08 | JclExecutor.execute: 正常 | 已解析 Job | 执行结果 | ### 0.21 quality (新增) 测试文件: `tests/quality/test_quality.py` | # | 测试名 | 内容 | 期待 | |:-:|:-------|:-----|:------| | QL-01 | L1OffsetValidator.validate: cobc 存在 | 有效 FieldTree | 含 score/mismatches | | QL-02 | L1OffsetValidator.validate: cobc 不存在 | 无 cobc | 异常或 fallback | | QL-03 | L2RoundtripValidator.validate: 无 COMP-3 | 无 COMP-3 字段 | pass=True, results=[] | | QL-04 | L2RoundtripValidator.validate: 有 COMP-3 | 含 COMP-3 字段 | pass=True, 字段值正确 | ### 0.22 storage (新增) 测试文件: `tests/storage/test_storage.py` | # | 测试名 | 内容 | 期待 | |:-:|:-------|:-----|:------| | ST-01 | DiskCache.get/set: 正常 | key-value 存取 | 获取与设置一致 | | ST-02 | DiskCache.get: 不存在 | 无缓存 key | 返回 None | | ST-03 | ReportStore.save_history: 正常 | JSONL 写入 | 追加文件 | | ST-04 | TestDataBundle: 路径 | base_path | cobol_input/spark_input 正确 | ### 0.23 preprocessor (新增) 测试文件: `tests/test_preprocessor.py` | # | 测试名 | 内容 | 期待 | |:-:|:-------|:-----|:------| | PP-01 | expand: 有 COPY 文件 | COPY CPYBOOK → 文件存在 | COPYBOOK 内容展开 | | PP-02 | expand: 无 COPY 文件 | COPY NOTEXIST | "NOT FOUND" 标记 | | PP-03 | expand: 无 COPY 语句 | 纯文本 | 原文不变 | ### 0.24 数据模型 (补充断言) 测试文件: `tests/data/test_models.py` | # | 测试名 | 内容 | 期待 | |:-:|:-------|:-----|:------| | DM-01 | Field 构建 | 所有属性 | 属性值正确 | | DM-02 | FieldTree.flatten: 嵌套 | 层级字段 | 展平字典含所有字段 | | DM-03 | FieldTree.flatten: 同名字段 | 不同层级同名 | 后覆盖前 | | DM-04 | VerificationRun: 默认 timestamp | 空构造 | timestamp 自动填充 | | DM-05 | VerificationRun.verdict: PASS | status=PASS | "PASS" | | DM-06 | VerificationRun.verdict: BLOCKED | status=BLOCKED | "BLOCKED" | | DM-07 | VerificationRun.total_fields | matched=5, mismatched=3 | 8 | | DM-08 | TestSuite.has_spark | spark_config 有/无 | True/False | | DM-09 | FieldResult 容忍度 | tolerance_applied>0 | 状态含 PASS 但标记 | ### 0.25 报告生成器 (保持) 测试文件: `tests/report/test_generator.py` | # | 测试名 | 内容 | 期待 | |:-:|:-------|:-----|:------| | RG-01 | generate_json: 新字段 | VerificationRun 全字段 | JSON 含所有字段 | | RG-02 | generate_html: 覆盖率显示 | paragraph_rate>0 | "段落覆盖率" 显示 | | RG-03 | generate_html: HINA 显示 | hina_type 设置 | "判定类型" 显示 | | RG-04 | generate_html: HINA 不显示 | hina_type="" | HINA 区不显示 | | RG-05 | generate_html: 质量评分显示 | quality_score>0 | "质量评分" 显示 | | RG-06 | generate_html: 质量评分不显示 | quality_score=0 | 质量区不显示 | | RG-07 | generate_html: 警告显示 | quality_warn 设置 | 警告栏显示 | | RG-08 | generate_machine_json: 全字段 | VerificationRun | branch_rate 等包含 | | RG-09 | generate_json: 向后兼容 | 新字段未设置 | 与现有 JSON 同结构 | ### 0.26 comparator (新增) 测试文件: `tests/comparator/test_comparator_all.py` | # | 测试名 | 内容 | 期待 | |:-:|:-------|:-----|:------| | CP-01 | compare_field: 数值完全一致 | c="100.00", j="100.00" | status=PASS | | CP-02 | compare_field: 数值容忍度内 | c="100.01", j="100.00", tol=0.02 | status=PASS | | CP-03 | compare_field: 数值超出容忍 | c="110.00", j="100.00", tol=0.02 | status=MISMATCH | | CP-04 | compare_field: 日期一致 | 同日期不同格式 | PASS | | CP-05 | compare_field: 字符串 | c="ABC", j="ABC" | PASS | | CP-06 | align_records: 1:1 | COBOL 1条, Java 1条, 键匹配 | 1个对齐对 | | CP-07 | align_records: 多对多 | 3条+3条, 键匹配 | 3个对齐对 | | CP-08 | align_records: 无匹配 | 无共同键 | 空结果 | | CP-09 | detect_rounding: 有 rounding | c=100, j=99.99 | RoundingResult(detected=True) | | CP-10 | detect_rounding: 无 rounding | c=100.00, j=100.00 | RoundingResult(detected=False) | --- ## L1: 结合测试 测试文件: `tests/test_integration.py` | # | 测试名 | 场景 | 期待 | |:-:|:-------|:------|:------| | CT-01 | extract→generate 一致性 | 同源 extract→generate | generate_data 可生成数据 | | CT-02 | HINA→Strategy 映射 | 匹配分类→全标记生成 | 9个标记 | | CT-03 | QG→incremental 循环控制 | 分支不足→supplement→再检查 | passed=True | | CT-04 | strategy→TestCase 型一致 | supplement 输出→TestCase 转换 | 可作为 TestCase 使用 | | CT-05 | orchestrator: 正常路径 | cobol_testgen→HINA→QG→DataWriter | complete_tests 到 DataWriter | | CT-06 | orchestrator: LLM 异常 | HINA Agent 异常 | 错误日志, pipeline 继续 | | CT-07 | orchestrator: gcov 无效 | gcov_enabled=False | 动态覆盖率跳过 | | CT-08 | API→Worker→Orchestrator 全链路 | POST → Worker 消费 → 结果可查 | 状态 queued→running→done | ← 新增 | | CT-09 | LLM Agent 链异常回退 | Agent1 失败 → Agent2/3 可用 | Agent2 含 TC-FALLBACK | ← 新增 | | CT-10 | Config→Runner 路由 | runner_mode=spark → SparkJavaRunner | 正确 Runner 实例化 | ← 新增 | | CT-11 | HINA+gcov→报告渲染 | 覆盖率数据 → 报告 HTML | HTML 含覆盖率和 HINA | ← 新增 | | CT-12 | JCL 解析→执行 | parse→execute 数据流 | 执行结果 | ← 新增 | | CT-13 | gcov_collector: 未安装 | gcov 命令不存在 | available=False | ← L1 移入 | | CT-14 | gcov_collector: 正常 | .gcda/.gcno 存在 | available=True, line_rate 计算 | ← L1 移入 | | CT-15 | Config: 质量门禁设置 | aurak.toml 变更→from_toml | quality_gate_mode=warn | ← L1 移入 | --- ## L2: HINA 统合测试 测试文件: `test-data/run_validation.py` (HINA*.cbl 10个程序) | # | 程序 | 验证项 | 期待 | |:-:|:-----|:-------|:------| | IT-01 | HINA001 | 匹配结构分析 | 段落≥8, 文件≥2 | | IT-02 | HINA005 | IF 分支覆盖率 | 分支≥6, 决策点≥3 | | IT-03 | HINA006 | EVALUATE 覆盖率 | 分支≥6, 决策点≥3 | | IT-04 | HINA007 | 键中断分析 | 段落≥3, 文件≥2 | | IT-05 | HINA013 | 项目检查分析 | 分支≥6, 决策点≥3 | | IT-06 | HINA025 | L1 分类+CALL 分析 | HINA="子程序调用", confidence≥90% | | IT-07 | HINA101 | L1 分类+SQL 分析 | HINA="DB操作", confidence≥95% | | IT-08 | run_validation.py 全执行 | 所有 HINA 程序 | 8/10 pass (已知限制2) | --- ## L3: 実 COBOL 验证 | # | 程序 | 验证项 | 期待 | |:-:|:-----|:-------|:------| | RT-01 | CRDVAL | COPYBOOK 展开+全 pipeline | 无错误 | | RT-02 | CRDCALC | 同上 | 同上 | | RT-03 | CRDRPT | 同上 | 同上 | | RT-04 | GENDATA | 同上 | 同上 | --- ## L4: 回归测试 | # | 测试 | 命令 | 期待 | |:-:|:-----|:------|:------| | RE-01 | comparator 全测试 | `pytest tests/comparator/ -v` | 22 passed | | RE-02 | report 全测试 | `pytest tests/report/ -v` | 3 passed | | RE-03 | golden 全测试 | `pytest tests/test_golden.py -v` | 11 passed | | RE-04 | e2e imports | `pytest tests/test_e2e.py -v` | 1 passed | | RE-05 | 全单元 | `pytest tests/ --ignore=e2e/ --ignore=test_web_e2e.py --ignore=test_biz_e2e.py -v` | 42 passed | --- ## L5: 非功能测试 ### 5.1 性能 测试文件: `tests/nonfunctional/test_performance.py` | # | 测试名 | 场景 | 接受标准 | |:-:|:-------|:------|:---------| | NF-01 | COBOL 10万行解析时间 | extract_structure 含10万行输入 | ≤30秒完成 | | NF-02 | 大文件上传 10MB 边界 | POST /verify 9.5MB 文件 | 202 响应, ≤10秒 | | NF-03 | Worker 并发任务处理 | 5个任务同时 enqueue | 全部完成, ≤60秒 | | NF-04 | 报告 HTML 生成:大数据集 | 1000字段结果渲染 | ≤5秒 | | NF-05 | LLM 调用缓存加速 | 相同请求重复调用 | 第二次 ≤100ms | ### 5.2 并发安全 测试文件: `tests/nonfunctional/test_concurrency.py` | # | 测试名 | 场景 | 期待 | |:-:|:-------|:------|:------| | NF-06 | 同时 POST 相同文件 | 2个并行 /verify 请求 | 不同 task_id | | NF-07 | Worker 双实例 | 2个 Worker 同时 polling | 无任务重复处理 | | NF-08 | Task JSON 并发读写 | 读的同时 Worker 在写入 | 无损坏/无异常 | ### 5.3 安全 测试文件: `tests/nonfunctional/test_security.py` | # | 测试名 | 场景 | 期待 | |:-:|:-------|:------|:------| | NF-09 | 路径遍历: 上传文件名 | 文件名 `../../../etc/passwd` | 拒绝或 sanitize | | NF-10 | 路径遍历: copybook 路径 | `--cobol-src ../../../etc/passwd` | BLOCKED | | NF-11 | 文件类型校验 | 非 COBOL 文件扩展名 | 接受或合理处理 | | NF-12 | API key 环境变量未设置 | LLM_API_KEY 为空 | Agent 使用 fallback 而非崩溃 | | NF-13 | 错误信息泄露 | API 返回 stack trace | 不包含敏感路径 | ### 5.4 错误恢复与降级 测试文件: `tests/nonfunctional/test_resilience.py` | # | 测试名 | 场景 | 期待 | |:-:|:-------|:------|:------| | NF-14 | Worker 中断→重启 | Worker 在 running 状态崩溃 | 重启后可重新处理 | | NF-15 | 磁盘满模拟 | task JSON 写失败 | 错误日志, 不崩溃 | | NF-16 | LLM API 不可用 | 网络隔离 | Agent 全部 fallback, pipeline 继续 | | NF-17 | cobc 非 fatal warning | 编译通过但有 warning | pipeline 继续, warning 记录 | --- ## L6: E2E UI 测试 (Playwright) 测试文件: `tests/test_web_e2e.py` | # | 测试名 | 场景 | 期待 | |:-:|:-------|:------|:------| | UI-01 | 上传页加载 | GET / | 标题含 verify, h1 可见 | | UI-02 | 表单元素存在 | 检查 4个文件输入 + 下拉框 | 所有元素可见, 可交互 | | UI-03 | 文件上传 | 选择4个文件 → 提交 | 202 响应, 跳转到 /status | | UI-04 | 上传后轮询 | 等待 Worker 完成 | 状态从 queued→done | | UI-05 | 结果页面: 摘要 | 验证完成 | 显示 matched/mismatched | | UI-06 | 结果页面: 字段表 | 字段列表渲染 | 每列含 name/status/COBOL/Java | | UI-07 | 无效文件上传 | 上传非 COBOL 文件 | 合理错误提示 | --- ## 边界测试 (补充 L0-L3) | # | 场景 | 输入 | 期待 | |:-:|:-----|:------|:------| | EC-01 | 空 COBOL | `IDENTIFICATION DIVISION. PROGRAM-ID. X.` | 无错误 | | EC-02 | 巨大程序 | 1万行级别 | 30秒内无超时 | | EC-03 | 日文字符串 | PIC N 全角数据 | extract 正常 | | EC-04 | REDEFINES | REDEFINES 使用 | 正常解析 | | EC-05 | OCCURS DEPENDING | ODO 使用 | 正常解析 | | EC-06 | 88-level 值 | 88-level 多个 | is_88=True 识别 | | EC-07 | 仅注释 | 全行注释 | 无错误 | | EC-08 | 非法 PIC | `PIC XXX` 非标准 | 正常或合理 fallback | | EC-09 | 空文件路径 | `--cobol-src` 不存在的文件 | BLOCKED | | EC-10 | Lark 语法错误 | 未预期的字符串 | 空结构, 错误日志 | | EC-11 | COMP-3 无效 sign nibble | 0xF 异常 nibble | 取值或报错 | ← 新增 | | EC-12 | REDEFINES 链 A→B→C | 3层 REDEFINES | 所有变体可访问 | ← 新增 | | EC-13 | GOBACK 对比 STOP RUN | GOBACK 程序 | 正常退出 | ← 新增 | | EC-14 | 无文件上传 | POST /verify 无任何文件 | 422 错误 | ← 新增 | | EC-15 | mapping.yaml 格式错误 | 非法 YAML | 解析错误处理 | ← 新增 |--- ## 程序类型覆盖 (33+2 COBOL 程序类型覆盖行) | 程序类型 | 覆盖状态 | Phase | 测试文件 | |:---------|:--------:|:-----:|:---------| | simple_sequential | ✅ | Phase 7 | `tests/parametrized/test_matching.py` | | condition_heavy | ✅ | Phase 7 | `tests/parametrized/test_matching.py` | | evaluate_driven | ✅ | Phase 7+8 | `tests/parametrized/test_call_search.py` | | data_file_centric | ✅ | Phase 7 | `tests/parametrized/test_matching.py` | | search_intensive | ✅ | Phase 8 | `tests/parametrized/test_call_search.py` | | call_based | ✅ | Phase 8 | `tests/parametrized/test_call_search.py` | | mixed_complex | ✅ | Phase 9 | `tests/parametrized/test_crosscutting.py` | | 1:1 matching | ✅ | Phase 7 | `tests/parametrized/test_matching.py` | | 1:N matching | ✅ | Phase 7 | `tests/parametrized/test_matching.py` | | N:1 matching | ✅ | Phase 7 | `tests/parametrized/test_matching.py` | | KEY break (accumulate) | ✅ | Phase 7 | `tests/parametrized/test_matching.py` | | KEY break (aggregate) | ✅ | Phase 7 | `tests/parametrized/test_matching.py` | | KEY break (mark) | ✅ | Phase 7 | `tests/parametrized/test_matching.py` | | Division 50/50 | ✅ | Phase 7 | `tests/parametrized/test_division.py` | | Division 25/25/25/25 | ✅ | Phase 7 | `tests/parametrized/test_division.py` | | Division 100 (all) | ✅ | Phase 7 | `tests/parametrized/test_division.py` | | CSV → FB conversion | ✅ | Phase 7 | `tests/parametrized/test_csv_conversion.py` | | CALL BY REFERENCE | ✅ | Phase 8 | `tests/parametrized/test_call_search.py` | | CALL BY VALUE | ✅ | Phase 8 | `tests/parametrized/test_call_search.py` | | CALL BY CONTENT | ✅ | Phase 8 | `tests/parametrized/test_call_search.py` | | SEARCH ALL (binary) | ✅ | Phase 8 | `tests/parametrized/test_call_search.py` | | SEARCH ALL (duplicate) | ✅ | Phase 8 | `tests/parametrized/test_call_search.py` | | SORT (ascending) | ✅ | Phase 8 | `tests/parametrized/test_sort_merge.py` | | SORT (descending) | ✅ | Phase 8 | `tests/parametrized/test_sort_merge.py` | | SORT (multiple keys) | ✅ | Phase 8 | `tests/parametrized/test_sort_merge.py` | | MERGE (2 files) | ✅ | Phase 8 | `tests/parametrized/test_sort_merge.py` | | MERGE (uneven) | ✅ | Phase 8 | `tests/parametrized/test_sort_merge.py` | | VL: ODO logic | ✅ | Phase 9 | `tests/parametrized/test_crosscutting.py` | | LP: PERFORM VARYING | ✅ | Phase 9 | `tests/parametrized/test_crosscutting.py` | | LP: PERFORM UNTIL | ✅ | Phase 9 | `tests/parametrized/test_crosscutting.py` | | NP: COMP-3 precision | ✅ | Phase 9 | `tests/parametrized/test_crosscutting.py` | | NP: ROUNDED clause | ✅ | Phase 9 | `tests/parametrized/test_crosscutting.py` | | D: Leap year / Month end | ✅ | Phase 9 | `tests/parametrized/test_crosscutting.py` | | 日文: 全角片假名 | ✅ | Phase 10 | `tests/parametrized/test_japanese.py` | | 日文: 半角片假名 | ✅ | Phase 10 | `tests/parametrized/test_japanese.py` | | 日文: SJIS 5C/7C 问题文字 | ✅ | Phase 10 | `tests/parametrized/test_japanese.py` | | 日文: 和历日期 | ✅ | Phase 10 | `tests/parametrized/test_japanese.py` | | 日文: Encoding round-trip | ✅ | Phase 10 | `tests/parametrized/test_japanese.py` | **33+2 = 35 程序类型全覆盖** --- ## 类型别测试矩阵 (Phase 7-10 测试文件清单) ### Phase 7: 匹配/分割/CSV 转换 (~8 测试文件) | 测试文件 | 测试内容 | 测试数 | |:---------|:---------|:------:| | `tests/parametrized/test_parametrized.py` | 8个公开函数的正常路径+边界 | ~50 | | `tests/parametrized/test_matching.py` | 1:1/1:N/N:1 匹配 + KEY 中断 + gcov | ~20 | | `tests/parametrized/test_division.py` | 50%/25%/100% 分割 + 余数处理 | ~15 | | `tests/parametrized/test_csv_conversion.py` | CSV→FB 字段数/类型/引号 | ~13 | ### Phase 8: CALL / SEARCH ALL / SORT / MERGE (~2 测试文件) | 测试文件 | 测试内容 | 测试数 | |:---------|:---------|:------:| | `tests/parametrized/test_call_search.py` | CALL 3种传递 + SEARCH ALL 查找 | ~22 | | `tests/parametrized/test_sort_merge.py` | SORT 升/降序 + MERGE 均匀/不均 | ~18 | ### Phase 9: 横断功能测试 (~1 测试文件, ~20 tests) | 测试文件 | 领域 | 测试数 | |:---------|:-----|:------:| | `tests/parametrized/test_crosscutting.py` | VL(ODO)+LP(PERFORM)+NP(COMP3/ROUNDED)+D(闰年/月末/和历) | ~20 | ### Phase 10: 日文测试 (~1 测试文件, ~20 tests) | 测试文件 | 测试内容 | 测试数 | |:---------|:---------|:------:| | `tests/parametrized/test_japanese.py` | 全角/半角/SJIS 5C/7C/和历/编码回环 | ~20 | --- ## 横跨功能测试行 (Phase 9) 横断功能测试覆盖 COBOL 运行时四大核心领域: | 领域 | 缩写 | 测试内容 | 测试数 | |:-----|:----:|:---------|:------:| | 可变长 / ODO | VL | OCCURS DEPENDING ON 长度/读取/边界 | 5 | | 循环 / PERFORM | LP | PERFORM VARYING 升/降/步进 + UNTIL | 5 | | 数值精度 | NP | COMP-3 BCD 解码 + ROUNDED 上下舍入 | 5 | | 日期逻辑 | D | 闰年/月末/和历转换 | 5 | --- ## 日文测试行 (Phase 10) 日文测试覆盖 COBOL 日文处理的特殊场景: | 测试分组 | 内容 | 测试数 | |:---------|:-----|:------:| | 查找表常量 | 全角平/片假名/半角/SJIS 问题文字/和历边界 | 4 | | 全角文字生成 | PIC N 字段填充 + 长度 + 内容验证 | 3 | | 半角片假名生成 | PIC X 字段填充 + 长度验证 | 2 | | SJIS 问题文字 | 5C 问题 + 7C 问题文字 | 2 | | 和历日期 | 标准格式 + 边界切换 + 默认参数 | 3 | | 编码回环 | Shift-JIS ↔ UTF-8 回环 + 数据类型选择 | 4 | | 数据类型选择 | PIC N/9/X 正确分类 | 2 | --- ## 覆盖率目标 ``` Module Target Current ────────────────────────────────── ─────── ────── cobol_testgen/* ≥ 85% ~60% (单元不足) hina/classifier.py ≥ 90% 基本覆盖 hina/gate.py ≥ 95% 基本覆盖 hina/retry.py ≥ 90% 基本覆盖 hina/strategy.py ≥ 90% 基本覆盖 hina/hina_agent.py ≥ 85% ~60% hina/gcov_collector.py ≥ 80% 0% orchestrator.py ≥ 80% 0% ← 新增重点 web/api.py ≥ 85% 0% ← 新增重点 web/worker.py ≥ 75% 0% ← 新增重点 agents/* ≥ 80% 0% config/* ≥ 85% 0% runners/* ≥ 70% 0% jcl/* ≥ 80% 0% quality/* ≥ 70% 0% storage/* ≥ 65% ~low preprocessor.py ≥ 80% 0% report/generator.py ≥ 75% 基本覆盖 comparator/* ≥ 90% 基本覆盖 data/* ≥ 95% 模块级断言 parametrized/* ≥ 95% 100% ← 新增 (Phase 7-8) japanese_data.py ≥ 90% 100% ← 新增 (Phase 10) coverage/* ≥ 80% 100% ← 新增 hina/confidence.py ≥ 90% 100% ← 新增 hina/rule_engine/* ≥ 85% 100% ← 新增 ``` --- ## 测试执行计划 ### Phase A: 核心模块单元 (~15分) ```bash # 核心: cobol_testgen / hina / agents / config pytest tests/ -v -k "test_cobol or test_hina or test_agents or test_config" \ --ignore=tests/e2e/ --ignore=tests/test_web_e2e.py ``` ### Phase B: 管道中枢 + Web (~10分) ```bash # orchestrator, web API, Worker pytest tests/ -v -k "test_orchestrator or test_web or test_worker" ``` ### Phase C: 边界 + 非功能 (~15分) ```bash # 边界值, 性能, 安全, 容错 pytest tests/ -v -k "test_edge or test_nonfunc or test_resilience" ``` ### Phase D: runner + JCL + 其他模块 (~8分) ```bash pytest tests/ -v -k "test_runner or test_jcl or test_quality or test_storage" ``` ### Phase E: HINA 统合测试 (~2分) ```bash python test-data/run_validation.py ``` ### Phase F: 回归测试 (~1分) ```bash python -m pytest tests/comparator/ tests/report/ tests/test_golden.py tests/test_e2e.py -v ``` ### Phase G: 実 COBOL 测试 (~5分, WSL + GnuCOBOL) ```bash # WSL 侧 python -m pytest tests/test_golden.py -v ``` ### Phase H: E2E Playwright (~3分, 需启动 server) ```bash # 终端1 python -m uvicorn web.api:app --host 127.0.0.1 --port 8000 # 终端2 python -m pytest tests/test_web_e2e.py -v ``` ### Phase I: 类型别测试 Phase 7-10 (~2分) ```bash # parametrized 全测试 (匹配/分割/CSV/CALL/SORT/横断/日文) pytest tests/parametrized/ -v --ignore=tests/e2e/ ``` ### 一键全自动化 ```bash # 核心 + 边界 + 非功能 (不依赖外部环境) pytest tests/ -v --ignore=e2e/ --ignore=test_web_e2e.py --ignore=test_biz_e2e.py ``` --- ## 预期结果 | 测试维度 | 计划数 | 最低通过 | 通过率目标 | |:---------|:-----:|:--------:|:---------:| | L0 单元测试 | 280 | 270 | ≥96% | | L1 类型测试 (Phase 7-8) | 80 | 75 | ≥93% | | 横跨功能测试 (Phase 9) | 20 | 18 | ≥90% | | 日文测试 (Phase 10) | 20 | 18 | ≥90% | | L2 HINA 统合 | 8 | 6 | ≥75% | | L3 実 COBOL | 4 | 4 | 100% | | L4 回归 | 112 | 112 | 100% | | L5 非功能 | 6 | 5 | ≥83% | | L6 UI E2E | 7 | 7 | 100% | | **总计** | **~518** | **~500** | **≥96%** | **内訳:** ``` L0 单元测试: 280 (测试数 0.1~0.26 子模块单元测试) L1 类型测试 (Ph7-8): 80 (matching/division/CSV/CALL/SORT/parametrized) 横跨功能测试 (Ph9): 20 (VL/LP/NP/D 四大领域) 日文测试 (Ph10): 20 (全角/半角/SJIS/和历/编码) 非功能测试: 6 (性能/并发/安全/容错) 已有回归: 112 (L2+L3+L4+L6 合计) 总计: ~518 ``` --- ## 已知限制 1. **Lark 文法**: `SD` / `ASCENDING KEY` 未対応, HINA 2个测试跳过 2. **Windows 编码**: `PYTHONIOENCODING=utf-8` 或 `python -X utf8` 必须, GBK 错误频繁 3. **Docker 不可用**: 当前环境无 Docker Desktop, Spark runner 不可测试 4. **外部依赖**: 実 COBOL 测试需要 WSL + GnuCOBOL + Java (GnuCOBOL 3.1.2.0, OpenJDK 17) 5. **LLM API 成本**: Agent 测试依赖 LLM 调用, 缓存命中可降低成本 6. **沙盒权限**: settings.json 需包含 `D:/cobol-java/**` 读写权限以便子 Agent 并行开发