test-generation.md 11 KB

测试用例生成 -- 智能测试用例生成

输入要求

  1. 被测代码(必填):需要测试的函数/类/模块
  2. 测试框架(必填):如Jest、Pytest、JUnit、Go testing
  3. 编程语言(必填):代码使用的语言
  4. 测试类型(可选):单元测试/集成测试/全部,默认全部
  5. 已有测试(可选):如果已有部分测试需要补充
  6. 专项要求(可选):安全测试/性能测试/长任务测试/兼容性测试

执行流程

第一步:Spec场景覆盖检查

生成测试前先检查spec中的scenario:

  • 如有spec:确保每个scenario至少有一个对应的测试用例
  • spec → 测试映射:

    Scenario: [scenario名称] → Test: [测试用例名称]
    
  • 无spec:基于代码逻辑生成测试,但提示建议补充spec

第二步:代码分析

  • 识别被测函数的输入参数和返回值
  • 识别条件分支(if/else、switch、try-catch)
  • 识别外部依赖(数据库、API、文件系统)
  • 识别边界条件(空值、空数组、最大值、最小值)
  • 识别安全触发面:外部输入、权限、SQL、HTML输出、CSRF、上传、反序列化、敏感信息
  • 识别性能触发面:循环、批量处理、分页、数据库查询、网络调用、缓存、长任务
  • 识别长任务触发面:Init 创建、Step 分批、Poll 查询、重试、取消、超时、断点续跑

第三步:生成测试场景

| 场景类型 | 说明 | 示例 | | - | - | - | | 正常路径 | 标准输入,预期成功 | 正常参数调用 | | 边界条件 | 临界值输入 | 空数组、最大长度、0值 | | 异常路径 | 错误输入,预期失败 | null、负数、类型错误 | | 状态相关 | 依赖对象状态的测试 | 对象初始化后/操作后 | | 并发相关 | 多线程/协程场景 | 同时读写、竞态条件 | | 安全相关 | 验证注入、越权、输出转义和令牌校验 | SQL注入payload、XSS输入、缺失CSRF token、越权访问 | | 性能相关 | 验证响应时间、查询次数、批量规模和资源占用 | 1000条批处理、分页查询、慢查询阈值 | | 长任务相关 | 验证 Init-Step-Poll 全链路和失败恢复 | Init返回task_id、Step分批推进、Poll状态变化、取消/重试 |

第四步:编写测试代码

  • 使用 Arrange-Act-Assert 结构
  • 为外部依赖创建Mock/Stub
  • 使用描述性的测试名称
  • 每个测试只验证一个概念
  • 安全测试必须包含恶意输入和权限负例,断言拒绝、转义或错误码
  • 性能测试必须写明数据规模、阈值和统计口径,不能只写"性能正常"
  • 长任务测试必须覆盖 Init、Step、Poll、失败重试、取消、超时和幂等

第五步:覆盖率分析

  • 语句覆盖率预估 — 按已测试语句数 / 被测函数总语句数估算;生成测试后统计 Arrange-Act-Assert 覆盖的代码行数占比
  • 分支覆盖率预估 — 按已覆盖分支数 / 被测函数总分支数估算(每个 if/else/switch/try-catch 的每个分支计1);生成测试后统计触发过的条件分支占比
  • 未覆盖路径说明
  • 安全覆盖检查:确认输入校验、权限、输出转义、CSRF、文件上传、反序列化等触发面是否有正反例
  • 性能覆盖检查:确认核心路径有数据规模、耗时阈值、查询次数或资源占用断言
  • 长任务覆盖检查:确认 Init-Step-Poll、重试、取消、超时、断点续跑至少覆盖核心路径
  • Spec覆盖检查:确认所有scenario都有对应测试

第六步:记录到项目记忆

测试用例生成完成后,将关键决策记录到项目记忆(参见 project-memory-management.md):

  • 记录测试策略选择
  • 记录 Mock/Stub 约定和命名规范
  • 更新测试覆盖率基线,作为后续测试的质量参考

实战请求示例

示例一:接口功能测试

帮我给登录接口生成测试用例。
框架:Laravel Feature Test / PHPUnit。
接口:POST /api/login。
输入:email、password。
覆盖:成功登录、密码错误、邮箱格式错误、账号禁用、频率限制。
安全:断言不会返回 password_hash、token 只在成功时返回。
验证:给出测试文件路径、运行命令和预期通过数。

优先加载:test-generation.md、api-design.md、laravel-testing.md。

示例二:长任务测试

帮我给批量刷新缓存任务生成测试。
架构:Init-Step-Poll。
覆盖:Init 返回 task_id;Step 每批 50 条;Poll 返回 percent;失败可重试;取消后不能继续执行。
边界:空数据、超大数据、重复 Step、无权限访问。
验证:给出单元测试和手动接口测试步骤。

优先加载:test-generation.md、api-design.md、cms-development.md。

输出格式

## 测试用例报告

**被测函数**:[函数名]
**测试框架**:[框架]
**生成测试数**:[X]个

## 测试场景分析

| 场景 | 输入 | 预期输出 | 类型 |
|------|------|---------|------|
| [场景1] | [输入] | [输出] | 正常路径 |
| [场景2] | [输入] | [输出] | 边界条件 |
| [场景3] | [输入] | [输出] | 异常路径 |
| [场景4] | [输入] | [输出] | 安全/性能/长任务 |

## 测试代码

[语言] [完整测试代码]


## 覆盖率预估

- **语句覆盖**:[X]%
- **分支覆盖**:[X]%
- **安全覆盖**:[已覆盖/未覆盖,说明]
- **性能覆盖**:[已覆盖/未覆盖,说明]
- **长任务覆盖**:[已覆盖/不涉及,说明]
- **未覆盖路径**:[说明]

## 运行命令

bash [运行测试的命令]

质量标准

  • 每个测试必须有明确的Arrange-Act-Assert结构
  • 测试名称必须描述行为和预期结果(如shouldReturnErrorWhenInputIsNull)
  • 边界条件必须覆盖:空值、空集合、最大值、最小值、边界值+1/-1
  • 异常测试必须验证具体的异常类型和错误消息
  • 安全测试必须覆盖适用风险:SQL注入、XSS、CSRF、权限绕过、文件上传、反序列化、敏感信息泄露
  • 性能测试必须定义数据规模、响应时间/查询次数/内存阈值,并说明环境前提
  • 长任务测试必须覆盖 Init 创建、Step 分批、Poll 查询、失败重试、取消、超时和幂等
  • 外部依赖(数据库、API、文件)必须使用Mock,不能真实调用
  • 不得生成无意义的测试(如测试getter/setter且不做断言)

算法边界用例清单(图与递归算法)

仅覆盖「空值/空集合/最大值/边界值±1」等值域边界不足以拦住图与递归算法缺陷。环检测这类算法三次迭代都没写对,根因是测试侧缺一张能拦住它的结构边界用例表。

边界应从不变量推导,而不是背诵:凡是会让某个不变量被违反的结构,就是必须测的边界。先按 karpathy-coding-guidelines.md 不变量推导三步法推出「不变量命题 + 终止度量 + 守恒关系」,再取其逆否命题枚举边界——这样边界表从"背下来的表"变成"推导出来的表",面对没写进表的全新算法也能自己推出该测什么。

任何图遍历 / 递归 / 状态机 / 依赖解析算法,除值域边界外必须补齐以下结构化边界(以有向图环检测为例,可推广到树、DAG、拓扑排序、可达性分析等):

| 边界 | 结构 | 断言要点 | | - | - | - | | 0 节点 | 空图 | cycle=0,且不抛异常 | | 1 节点 | 单点无环 | cycle=0 | | 自环 | 单点指向自身 | cycle=1(或按业务语义) | | 两节点互环(down) | A→B→A | cycle=1,且遍历方向与边有向性一致 | | 两节点互环(both) | A⇄B(双向/无向) | cycle=1 | | 三环 | A→B→C→A | cycle=1,且不重复计数 | | 菱形 DAG | A→B→D, A→C→D | cycle=0(断言无环) | | 平行边 | A→B 出现两次 | 覆盖不重复、环计数不翻倍 | | up 方向 | 反向遍历同图 | 边方向与遍历方向一致,结果不为负 |

  • 递归不变量断言:对每个递归 / DFS,必须断言不变量(invariant)在每次递归入口与出口成立,例如「已访问集合不含回边指向的节点」「递归栈深不超过节点总数」「计数单调不减」。流程跑通 ≠ 结果正确,必须有可判定的结构化断言。
  • 回边判定黑盒断言:不要只测"能跑完",要断言具体结果(环数、环成员、是否标记、是否重复)。「流程跑通但结果错」是这类缺陷的典型漏网形态。
  • property-based testing 提示:对纯函数式算法(排序、环检测、拓扑排序、去重),用 property-based 框架(Python Hypothesis、JS fast-check、Java jqwik 等)生成随机结构,断言稳定性质,避免测试依赖输入顺序或样本偶然性:
    • 单调性:给图加入一条边后,环数单调不减;
    • 交换律:重排节点顺序 / 反转子图,结果不变;
    • 对任意合法 DAG,拓扑排序结果与任一合法顺序一致。

失败回退机制

| 步骤 | 失败条件 | 回退目标 | 最大重试 | 不可恢复时升级路径 | | - | - | - | - | - | | 第一步:Spec场景覆盖检查 | 无spec或spec场景与代码实现不一致 | 基于代码逻辑生成测试,标注"无spec对照" | 1 | 建议先走 Spec驱动开发 补全spec | | 第二步:代码分析 | 代码量过大,分支/依赖识别超限 | 按函数分批分析,每批输出局部测试 | 0 | 建议缩小测试范围或分模块生成 | | 第三步:生成测试场景 | 边界条件难以枚举 | 优先覆盖核心路径 + 已知边界,标注"边界待补" | 2 | 输出场景骨架,建议人工补充边界 | | 第四步:编写测试代码 | Mock/Stub设置复杂,外部依赖难以隔离 | 降级为集成测试,标注"未完全Mock" | 2 | 输出测试框架骨架,建议人工补全Mock | | 第五步:覆盖率分析 | 覆盖率无法量化(无运行环境) | 输出预估覆盖率,标注"未实际运行" | 1 | 建议用户本地运行测试后回填实际覆盖率 | | 第六步:记录到项目记忆 | 项目记忆系统不可用 | 输出测试策略到本地文件 | 1 | 标注"策略未沉淀",提示用户手动保存 |

关联 reference

  • frontend-design(前端设计)— 前端页面或组件测试需参考 frontend-design 的交互状态、响应式断点和可访问性要求
  • api-design(API设计)— API 和长任务测试需参考 api-design 的认证、错误码、分页和 Init-Step-Poll 契约
  • cms-development(CMS二次开发)— CMS/PHP 测试需参考 cms-development 的权限、CSRF、输出转义和批处理规则
  • mysql-database(MySQL数据库)— SQL 和性能测试需参考 mysql-database 的参数绑定、索引、事务和 EXPLAIN 标准
  • code-review(代码审查)— 生成前可用 code-review 确保被测代码逻辑正确
  • bug-diagnosis(Bug诊断)— 修复Bug后可用 test-generation 生成回归测试
  • code-generation(代码生成)— 生成代码后可用 test-generation 生成配套测试
  • project-memory-management(项目记忆管理)— 记录测试策略、Mock/Stub 约定和测试覆盖率基线