用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
直接命令不会经过审查 Prompt;运行前请先检查来源。
npx skills add https://github.com/ZeroZ-lab/unified-skills --skill verify-quality-integration-testing命令会保持在同一行。复制前请横向滚动并检查完整内容。
想先保存到本地?可下载 SkillsMP 当前能够提供的文件。
基于 SOC 职业分类
正在显示 SKILL.md
| name | verify-quality-integration-testing |
| description | 集成测试——验证组件间交互和边界契约。当需要在单元测试之上验证跨组件/跨服务正确性,或提到"集成测试""integration""契约测试" |
verify-workflow-review/reviewbuild-quality-tdd/SKILL.md必须写: API 端点(请求→响应)、数据库操作(ORM→真实DB)、跨服务调用、认证流程、文件上传/处理、Webhook 处理
不必写: 纯函数逻辑(单元测试)、第三方 SDK 内部行为、简单 CRUD 无业务逻辑
偏好顺序(从高到低):
1. 真实实现 → 最高信心,能抓到真实 bug
2. Fake → 依赖的内存版本(如内存数据库)
3. Stub → 返回固定数据,无行为
4. Mock → 验证方法调用 —— 仅用于无法控制副作用的边界
仅在以下场景 mock: 外部支付网关、邮件发送服务、第三方 API(无法控制、有速率限制或要花钱)。
绝不 mock 数据库。 用测试数据库或事务回滚。
describe('POST /tasks', () => {
it('创建任务并返回 201', async () => {
// Arrange: 设置测试场景
const user = await createTestUser();
const payload = { title: '买菜', priority: 'high' };
// Act: 执行被测动作
const response = await request(app)
.post('/tasks')
.auth(user.token)
.send(payload);
// Assert: 验证结果
expect(response.status).toBe(201);
expect(response.body.task.title).toBe('买菜');
expect(response.body.task.status).toBe('pending');
// 验证副作用: 确实写入了数据库
const saved = await db.tasks.findById(response.body.task.id);
expect(saved).not.toBeNull();
});
});
// Happy path
it('创建资源返回 201', ...);
// Validation errors
it('缺少必填字段返回 400', async () => {
const response = await request(app).post('/tasks').send({});
expect(response.status).toBe(400);
expect(response.body.error.code).toBe('VALIDATION_ERROR');
});
// Auth errors
it('未认证用户返回 401', async () => {
const response = await request(app).post('/tasks').send(validPayload);
expect(response.status).toBe(401);
});
// Permission errors
it('非所有者修改他人任务返回 403', async () => {
const task = await createTask({ ownerId: 'user-a' });
const response = await request(app)
.patch()
.()
.({ : });
(response.).();
});
(, () => {
response = (app)
.()
.(user.)
.({ : });
(response.).();
});
(, ...);
(, ...);
(, ...);
覆盖每个端点的: Happy → Validation → Auth → Permission → Not Found → Edge
// 方法 A: 事务回滚(首选 —— 快速、可靠)
let tx: Transaction;
beforeEach(async () => {
tx = await db.startTransaction();
});
afterEach(async () => {
await tx.rollback(); // 所有变更回滚,不污染数据库
});
// 方法 B: 测试数据库(事务回滚不可用时)
beforeEach(async () => {
await testDb.truncate(); // 清空测试库
});
// 格式: <动作> + <场景> + <预期>
it('拒绝没有标题的任务创建')
it('对未认证用户返回 401')
it('幂等创建 —— 相同幂等键返回同一资源')
it('并发更新时返回 409 冲突')
输出或记录必须包含:
| 说辞 | 现实 | 后果 |
|---|---|---|
| "单元测试就够了" | 单元测试验证孤立单元。集成测试验证它们一起工作时正确。API 参数会正确传递吗?数据库会接受数据吗?单元测试不答这些。 | 单元测试全绿但集成失败是最常见的生产故障模式——参数格式不匹配、数据库约束冲突、认证流程断裂。这些 bug 只在用户真实操作时才暴露。 |
| "mock 外部依赖更快" | Mock 的数据库返回数据 ≠ 真实数据库接受数据。用测试DB而不用mock。 | Mock 通过但真实数据库拒绝数据(类型不匹配、约束违反、字符编码问题),上线后以 500 错误形式爆发。 |
| "写集成测试很慢" | 500ms-2s 一个集成测试。发现一个跨组件 bug 省下的调试时间远多于此。 | 一个跨组件 bug 在生产排查需 4-8 小时(日志追踪 + 多服务定位);集成测试写 2 分钟就能捕获同类问题。 |
| "Happy path 就够了,error case 手工测" | 手工测错误路径不做回归保护。下次代码改动可能不经意在 error path 崩溃。 | 未测试的错误路径在 2 周后的改动中回归,以 500/空响应/数据不一致形式出现,且无法自动检测。 |
违反字面规则就是违反精神。 没有灰色地带。
setTimeout 等待(用条件轮询 waitFor)describe('POST /tasks', () => {
it('创建任务成功', async () => {
const res = await request(app).post('/tasks').auth(token).send({ title: 'test' });
expect(res.status).toBe(201);
});
});
问题:没有验证 400(缺字段)、401(未认证)、403(无权限)、404(不存在)、边界情况。上线后这些路径会以 500 错误暴露。
describe('POST /tasks', () => {
it('创建任务返回 201', async () => { /* happy path */ });
it('缺少 title 返回 400 VALIDATION_ERROR', async () => { /* validation */ });
it('未认证返回 401', async () => { /* auth */ });
it('非所有者修改他人任务返回 403', async () => { /* permission */ });
it('修改不存在任务返回 404', async () => { /* not found */ });
it('幂等键重复返回同一资源', async () => { /* edge: idempotency */ });
});
优点:覆盖 Happy + Validation + Auth + Permission + Not Found + Edge,每条路径都有回归保护。
| 失败场景 | 处理方式 |
|---|---|
| 集成测试全红(Happy Path 失败) | 阻塞,先修复核心功能再测其他路径。不跳过 Happy Path 进入 review |
| Auth/Permission 测试失败 | 阻塞,认证和权限问题属于安全红线,不降级为"后续修复" |
| 数据库隔离失败(测试间状态泄漏) | 修复隔离策略(事务回滚或 truncate),不依赖手动清理。测试间共享状态 = 结果不可信 |
| 外部服务 mock 与真实行为不一致 | 更新 mock 行为匹配真实 API 文档,或替换为 Fake 实现。mock 与真实不一致 = 测试无效 |
| 部分端点测试未覆盖 | 在 review 前补充缺失端点测试,不接受"后续补测试"。未覆盖端点 = 未验证契约 |
# Integration Test Report — <name>
## 覆盖范围
- 端点数: N
- 覆盖端点: [列表]
- 未覆盖端点: [列表 + 原因]
## 测试矩阵
| 端点 | Happy | Validation | Auth | Permission | Not Found | Edge |
|------|-------|------------|------|------------|-----------|------|
| POST /tasks | PASS | PASS | PASS | PASS | — | PASS |
| PATCH /tasks/:id | PASS | PASS | PASS | PASS | PASS | PASS |
## 测试替身使用
| 依赖 | 替身类型 | 原因 |
|------|---------|------|
| 数据库 | 真实(事务回滚) | 绝不 mock 数据库 |
| 支付网关 | Mock | 外部服务,不可控 |
| 邮件服务 | Mock | 外部服务,有副作用 |
## 隔离策略
- 方式: 事务回滚 / truncate
- 验证: 测试间无共享状态
## 结果
- 通过数: X
- 失败数: Y
- 跳过数: Z
## 失败详情
[列出每个失败测试:端点、路径、失败原因、修复建议]
## 下一步
- 全绿 → 进入 /review
- 有失败 → 修复后重新运行,不跳过进入 review