初始化
This commit is contained in:
239
.cursor/skills/bug-reproduce/SKILL.md
Normal file
239
.cursor/skills/bug-reproduce/SKILL.md
Normal 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. [ ] 输出了结构化复现报告
|
||||
Reference in New Issue
Block a user