初始化

This commit is contained in:
2026-03-05 21:27:11 +08:00
commit 130de0fd5d
140 changed files with 21972 additions and 0 deletions

View File

@@ -0,0 +1,239 @@
---
name: bug-reproduce
version: 1.1.0
description: "结构化 Bug 复现框架,系统化定位和复现 Bug。当需要从 Bug 报告出发编写复现步骤和回归测试时使用。仅复现,不修复。"
requires: [vue-testing]
---
# 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
```bash
# 搜索相关文件
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
在编写测试前,先查找同区域的已有测试作为参考:
```bash
# 查找 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
<?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 测试模板**
```typescript
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
```bash
# 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 次):
1. 重新审视假设 — 重读代码路径
2. 尝试不同的测试方式或层级
3. 第 3 次仍失败 → 标记 UNCONFIRMED
**硬停止条件**(遇到即立即 SKIP
- 需要真实第三方 API 凭证(支付网关、短信服务等)
- 竞态条件/时序依赖(需要精确的并发控制)
- 需要特定云基础设施AWS/阿里云特定服务)
- 需要无法脚本化的手动 UI 操作
- 需要生产数据库中的真实数据
## 输出:复现报告
```markdown
## 🐛 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 |
```
## 验证
1. [ ] 从 Bug 报告中提取了所有关键信号
2. [ ] 选择了正确的测试层级
3. [ ] 失败测试包含 Bug 引用注释
4. [ ] 同时有 happy path 测试证明 setup 正确
5. [ ] 置信度评分有据可依
6. [ ] 测试文件已保留(未删除)
7. [ ] 输出了结构化复现报告