All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 6m29s
主要变更: - 新增 tb_shop_series_allocation 表,存储系列级别的一次性佣金配置 - ShopPackageAllocation 移除 one_time_commission_amount 字段 - PackageSeries 新增 enable_one_time_commission 字段控制是否启用一次性佣金 - 新增 /api/admin/shop-series-allocations CRUD 接口 - 佣金计算逻辑改为从 ShopSeriesAllocation 获取一次性佣金金额 - 删除废弃的 ShopSeriesOneTimeCommissionTier 模型 - OpenAPI Tag '系列分配' 和 '单套餐分配' 合并为 '套餐分配' 迁移脚本: - 000042: 重构佣金套餐模型 - 000043: 简化佣金分配 - 000044: 一次性佣金分配重构 - 000045: PackageSeries 添加 enable_one_time_commission 字段 测试: - 新增验收测试 (shop_series_allocation, commission_calculation) - 新增流程测试 (one_time_commission_chain) - 删除过时的单元测试(已被验收测试覆盖)
134 lines
3.5 KiB
Markdown
134 lines
3.5 KiB
Markdown
---
|
||
description: 从 Spec 的 Scenarios 和 Business Flows 自动生成验收测试和流程测试
|
||
---
|
||
|
||
从 Spec 文档自动生成两类测试:
|
||
1. **验收测试**(Acceptance Tests):从 Scenarios 生成,验证单 API 契约
|
||
2. **流程测试**(Flow Tests):从 Business Flows 生成,验证多 API 业务场景
|
||
|
||
**Input**: 可选指定 change 名称(如 `/opsx:gen-tests add-auth`)。如果省略,从上下文推断或提示选择。
|
||
|
||
**Steps**
|
||
|
||
1. **选择 change**
|
||
|
||
如果提供了名称,使用它。否则:
|
||
- 从对话上下文推断
|
||
- 如果只有一个活跃 change,自动选择
|
||
- 如果模糊,运行 `openspec list --json` 让用户选择
|
||
|
||
2. **检查 change 状态**
|
||
```bash
|
||
openspec status --change "<name>" --json
|
||
```
|
||
确认 specs artifact 已完成(`status: "done"`)
|
||
|
||
3. **读取 spec 文件**
|
||
|
||
读取 `openspec/changes/<change-name>/specs/*/spec.md` 下的所有 spec 文件。
|
||
|
||
4. **解析 Scenarios**
|
||
|
||
从每个 spec 文件中提取 `#### Scenario:` 块:
|
||
```markdown
|
||
#### Scenario: 成功创建套餐
|
||
- **GIVEN** 用户已登录且有创建权限
|
||
- **WHEN** POST /api/admin/packages with valid data
|
||
- **THEN** 返回 200 和套餐详情
|
||
```
|
||
|
||
5. **解析 Business Flows**(如果存在)
|
||
|
||
从 spec 文件中提取 `### Flow:` 块,包含多步骤业务场景。
|
||
|
||
6. **生成验收测试**
|
||
|
||
输出路径:`tests/acceptance/<capability>_acceptance_test.go`
|
||
|
||
模板结构:
|
||
```go
|
||
func Test{Capability}_Acceptance(t *testing.T) {
|
||
env := testutils.NewIntegrationTestEnv(t)
|
||
|
||
t.Run("Scenario_{name}", func(t *testing.T) {
|
||
// GIVEN: ...
|
||
// WHEN: ...
|
||
// THEN: ...
|
||
// 破坏点:...
|
||
})
|
||
}
|
||
```
|
||
|
||
7. **生成流程测试**
|
||
|
||
输出路径:`tests/flows/<capability>_<flow>_flow_test.go`
|
||
|
||
模板结构:
|
||
```go
|
||
func TestFlow_{FlowName}(t *testing.T) {
|
||
env := testutils.NewIntegrationTestEnv(t)
|
||
|
||
var (
|
||
// 流程级共享状态
|
||
)
|
||
|
||
t.Run("Step1_{name}", func(t *testing.T) {
|
||
// 依赖:...
|
||
// 破坏点:...
|
||
})
|
||
}
|
||
```
|
||
|
||
8. **运行测试验证**
|
||
|
||
```bash
|
||
source .env.local && go test -v ./tests/acceptance/... ./tests/flows/... 2>&1 | head -50
|
||
```
|
||
|
||
**预期**:全部 FAIL(功能未实现,证明测试有效)
|
||
|
||
**如果测试 PASS**:说明测试写得太弱,需要加强
|
||
|
||
**Output**
|
||
|
||
```
|
||
## 测试生成完成
|
||
|
||
**Change:** <change-name>
|
||
**来源:** specs/<capability>/spec.md
|
||
|
||
### 生成的测试文件
|
||
|
||
**验收测试** (tests/acceptance/):
|
||
- <capability>_acceptance_test.go
|
||
- Scenario_xxx
|
||
- Scenario_yyy
|
||
|
||
**流程测试** (tests/flows/):
|
||
- <capability>_<flow>_flow_test.go
|
||
- Step1_xxx
|
||
- Step2_yyy
|
||
|
||
### 验证结果
|
||
|
||
$ source .env.local && go test -v ./tests/acceptance/... ./tests/flows/...
|
||
|
||
--- FAIL: TestXxx_Acceptance (0.00s)
|
||
--- FAIL: TestXxx_Acceptance/Scenario_xxx (0.00s)
|
||
xxx_acceptance_test.go:45: 404 != 200
|
||
|
||
✓ 所有测试预期 FAIL(功能未实现)
|
||
✓ 测试生成完成
|
||
|
||
下一步: 开始实现 tasks,每完成一个功能单元运行相关测试验证
|
||
```
|
||
|
||
**Guardrails**
|
||
|
||
- 每个 Scenario 必须生成一个测试用例(不要跳过)
|
||
- 每个测试必须包含"破坏点"注释
|
||
- 流程测试的 step 必须声明依赖
|
||
- 使用 IntegrationTestEnv,不要 mock 依赖
|
||
- 测试必须在功能缺失时 FAIL(不要写永远 PASS 的测试)
|
||
- 详细模板参考:`.opencode/skills/openspec-generate-acceptance-tests/SKILL.md`
|