7.0 KiB
7.0 KiB
name, version, description, requires
| name | version | description | requires | |
|---|---|---|---|---|
| bug-reproduce | 1.1.0 | 结构化 Bug 复现框架,系统化定位和复现 Bug。当需要从 Bug 报告出发编写复现步骤和回归测试时使用。仅复现,不修复。 |
|
Bug 复现框架(PHP Hyperf + Vue 3)
触发条件
用户提供 Bug 报告、Issue 描述,要求复现问题或编写回归测试。
⚠️ 核心原则
- 只复现,不修复 — 输出是失败的测试用例,不是修复代码
- 最多 3 次尝试 — 3 次无法复现即标记为 UNCONFIRMED
- 遇到硬停止条件立即放弃 — 不浪费时间在不可能的事上
执行流程
1. 信号解析(Parse Signals)
从用户提供的 Bug 报告中提取关键信号:
□ 错误消息 / 堆栈追踪
□ 复现步骤(操作序列)
□ 影响区域(后端服务 / 前端组件 / API / 数据库)
□ 环境信息(PHP 版本 / 浏览器 / OS)
□ 何时开始出现 / 上次正常的版本
□ 是否可稳定复现 / 偶发
2. 路由到测试策略(Route to Test Layer)
根据影响区域,选择对应的测试层级和工具:
| 影响区域 | 测试层 | 工具 | 关键目录 |
|---|---|---|---|
| PHP Service/Repository | 单元测试 | PHPUnit + Mockery | Case-Database-Backend/test/Unit/ |
| Controller/API 端点 | 集成测试 | Hyperf Testing HttpClient | Case-Database-Backend/test/Feature/ |
| 中间件/认证 | 集成测试 | Hyperf Testing | Case-Database-Backend/test/Feature/ |
| 数据库 Migration/Model | 单元测试 | PHPUnit + SQLite | Case-Database-Backend/test/Unit/ |
| Vue 组件逻辑 | 单元测试 | Vitest | frontend-*/src/**/*.test.ts |
| Vue 组件交互 | 组件测试 | Vitest + Vue Test Utils | frontend-*/src/**/*.test.ts |
| 跨页面流程 | E2E 测试 | Playwright | frontend-*/e2e/ |
| API ↔ 前端联调 | E2E 测试 | Playwright | frontend-*/e2e/ |
3. 定位源码(Locate Source Files)
# 搜索相关文件
rg -l "ClassName\|functionName" --type php --glob '!vendor/**'
rg -l "ComponentName" --glob '*.vue' --glob '!node_modules/**'
# 查看最近变更
git log --oneline -10 -- <affected-path>
# 查看 diff
git diff HEAD~5 -- <affected-path>
4. 追踪代码路径(Trace Code Path)
从入口点到失败点,追踪完整的调用链:
后端路径示例:
Route → Middleware → Controller → FormRequest → Service → Repository → Model → DB
前端路径示例:
用户操作 → Event Handler → Composable/Store → API Request → 响应处理 → UI 更新
记录每个节点的输入输出和异常处理情况。
5. 形成假设(Hypothesize)
陈述清晰、可测试的假设:
假设 A (70%): 当 [输入/条件] 时,代码在 [位置] 执行了 [错误行为],
因为 [根因分析]。
假设 B (20%): ...
假设 C (10%): ...
每个假设必须指向具体的代码行。
6. 查找测试模式(Find Test Patterns)
在编写测试前,先查找同区域的已有测试作为参考:
# 查找 PHP 测试
rg -l "class.*Test" --type php Case-Database-Backend/test/
# 查找 Vue 测试
rg -l "describe\|it\(" --glob '*.test.ts' Case-Database-Frontend-*/src/
使用相同的 mock 模式和 setup 结构保持一致性。
7. 编写失败测试(Write Failing Test)
测试必须满足:
- 使用步骤 6 中找到的已有模式
- 断言正确行为(测试在当前代码上会失败)
- 包含 Bug 引用注释
- 同时包含一个 happy path 测试(证明 setup 正确)
PHP 测试模板:
<?php
declare(strict_types=1);
namespace HyperfTest\Unit;
use PHPUnit\Framework\TestCase;
class OrderServiceTest extends TestCase
{
// Happy path — proves setup works
public function testCreateOrderWithValidData(): void
{
$service = new OrderService($this->mockRepo);
$result = $service->create(['amount' => 100]);
$this->assertNotNull($result->id);
}
// Regression — reproduces the bug
// @see https://github.com/org/repo/issues/123
public function testCreateOrderRejectsNegativeAmount(): void
{
$service = new OrderService($this->mockRepo);
$this->expectException(BusinessException::class);
$service->create(['amount' => -1]);
}
}
Vitest 测试模板:
import { getStatusText } from './OrderStatus.utils'
describe('OrderStatus (Bug #123)', () => {
// Happy path
it('should return correct status for paid order', () => {
expect(getStatusText('paid', false)).toBe('待发货')
})
// Regression — reproduces the bug
// @see https://github.com/org/repo/issues/123
it('should handle null status without crashing', () => {
expect(() => getStatusText(null, false)).not.toThrow()
expect(getStatusText(null, false)).toBe('待支付')
})
})
8. 运行并评分(Run & Score)
# PHP
cd Case-Database-Backend && composer test -- --filter=OrderServiceTest
# Vue
cd Case-Database-Frontend-user && npx vitest run OrderStatus.utils.test.ts
根据结果评定置信度:
| 置信度 | 判定条件 | 后续动作 |
|---|---|---|
| CONFIRMED | 测试稳定失败,失败模式与假设吻合 | 输出复现报告 |
| LIKELY | 测试失败,但失败方式与预期略有偏差 | 报告 + 附注偏差原因 |
| UNCONFIRMED | 无法触发失败 | 报告已尝试的方法 |
| SKIPPED | 遇到硬停止条件 | 报告停止原因 |
| ALREADY_FIXED | Bug 在当前代码上不可复现 | 报告何时修复的 |
9. 迭代或放弃(Iterate or Bail)
UNCONFIRMED 后的迭代(最多 3 次):
- 重新审视假设 — 重读代码路径
- 尝试不同的测试方式或层级
- 第 3 次仍失败 → 标记 UNCONFIRMED
硬停止条件(遇到即立即 SKIP):
- 需要真实第三方 API 凭证(支付网关、短信服务等)
- 竞态条件/时序依赖(需要精确的并发控制)
- 需要特定云基础设施(AWS/阿里云特定服务)
- 需要无法脚本化的手动 UI 操作
- 需要生产数据库中的真实数据
输出:复现报告
## 🐛 Bug 复现报告
**Issue**: [ID] — [标题]
**置信度**: CONFIRMED | LIKELY | UNCONFIRMED | SKIPPED | ALREADY_FIXED
### 根因分析
[1-2 句话解释 Bug 产生的机制]
### 定位
| 文件 | 行号 | 问题 |
|---|---|---|
| `path/to/file.php` | XX-YY | 描述 |
### 失败测试
`path/to/test/file` — X/Y 个测试失败:
1. `testName` — [失败描述]
### 修复提示
[修复方向的伪代码或文字描述,不写完整修复代码]
### 尝试记录
| 次数 | 假设 | 测试方法 | 结果 |
|---|---|---|---|
| 1 | [假设 A] | [测试方式] | FAIL/PASS |
| 2 | [假设 B] | [测试方式] | FAIL/PASS |
验证
- 从 Bug 报告中提取了所有关键信号
- 选择了正确的测试层级
- 失败测试包含 Bug 引用注释
- 同时有 happy path 测试证明 setup 正确
- 置信度评分有据可依
- 测试文件已保留(未删除)
- 输出了结构化复现报告