with one click
integration-testing
写集成/端到端测试时使用。测真实交互,稳定不脆弱。
Install with Codex or Claude Copy this prompt, paste it into Codex, Claude, or another assistant, and let it review the skill page and install it for you.
Menu
写集成/端到端测试时使用。测真实交互,稳定不脆弱。
Install with Codex or Claude Copy this prompt, paste it into Codex, Claude, or another assistant, and let it review the skill page and install it for you.
Based on SOC occupation classification
做 Cocos Creator 多机型/多分辨率适配时使用。Canvas、Widget、安全区。
Cocos Creator 用 AssetBundle 做分包/远程资源时使用。加载、释放、依赖、缓存。
优化 Cocos Creator 渲染性能时使用。合批、图集、动静分离、Label。
给 Cocos Creator 原生包做热更新时使用。version manifest、增量、校验、回滚。
写 Cocos Creator 动效/动画时使用。tween、Animation、Spine、性能与清理。
做 Cocos Creator 大量条目列表时使用。虚拟列表、节点复用。
| name | integration-testing |
| description | 写集成/端到端测试时使用。测真实交互,稳定不脆弱。 |
| category | testing |
| tags | ["集成测试","测试"] |
规则: 对数据库读写、HTTP 调用、队列消息等关键 I/O,必须至少有一层测试走真实实现,而非全部替换为 mock。
为什么: AI 写测试时习惯把所有外部依赖都 mock 掉,代码看起来很"干净",但这样只是在测试自己写的 mock 实现,而非系统的真实行为。常见事故:mock 掉了 ORM 层,测试全绿,上线后因字段类型不匹配导致 IntegrityError。mock 掉了 HTTP 客户端,测试通过,生产环境 API 已改版本导致响应结构变了。
怎么做:
规则: 每条集成测试必须独立准备自己的数据,测试结束后恢复初始状态,与其他用例无任何隐式依赖。
为什么: AI 生成的测试常复用全局状态——在 beforeAll 里插一条记录,多个 it 块都读它。当测试并行跑或顺序变化时,用例之间互相污染,出现"单独跑通,全量跑挂"的薛定谔测试。常见事故:两个用例都插了 email = 'test@example.com' 的用户,唯一索引冲突导致其中一个随机失败。
怎么做:
test / it 内部完成数据 setup,通过事务回滚或 afterEach truncate 清理。beforeAll 里的共享数据被多个用例修改。规则: 集成测试依赖的外部服务要通过受控手段启动(Testcontainers、Docker Compose),而非假设 CI/本地某个固定地址永远可用。
为什么: AI 有时会在代码里硬编码 localhost:5432 或 redis://ci-server,假设环境已就绪。这导致:换一台机器跑就失败、CI 服务重启后测试挂掉、本地没有 Redis 的同事根本无法运行测试。测试变成"只在我电脑上能跑"的代码。
怎么做:
testcontainers 库在测试套件启动时自动拉起所需服务,结束时销毁。规则: 断言系统对外可观察的状态(数据库里写了什么、HTTP 响应返回了什么、消息队列里有什么),不断言内部函数是否被调用了几次。
为什么: AI 写集成测试时常把"调用次数断言"从单元测试搬过来:expect(repository.save).toHaveBeenCalledOnce()。这把测试和实现绑死:一旦重构把 save 改成批量 bulkInsert,所有测试挂掉,即使行为完全正确。测试应该保护行为,不保护实现。
怎么做:
verify(mock.method()) 风格的交互断言只留给单元测试。规则: 集成测试中所有不确定因素——时间戳、随机数、外部网络——必须被固定或受控替换,保证每次运行结果相同。
为什么: AI 生成的测试里经常出现 new Date() 直接写进断言,或者 Math.random() 生成的 ID 参与比对。时间一过零点、随机数"恰好"重复,测试莫名失败。更严重的是偶发性 flaky:本地每次过,CI 一周出一次红,根本无法定位原因。
怎么做:
jest.useFakeTimers / freezegun / clock.freeze 固定时间。// 反例 — 整个测试没有一行真实 DB 操作,只是在验证 mock 的行为
it("should create user", async () => {
const mockRepo = { save: jest.fn().mockResolvedValue({ id: 1 }) };
const service = new UserService(mockRepo as any);
const result = await service.createUser({ email: "a@b.com" });
expect(mockRepo.save).toHaveBeenCalledOnce(); // ❌ 测试了 mock,没测真实行为
expect(result.id).toBe(1); // ❌ id 是 mock 自己返回的
});
// 正例 — 使用 Testcontainers 启动真实 Postgres,验证实际写入
it("should create user", async () => {
const container = await new PostgreSqlContainer().start();
const dataSource = await initDataSource(container.getConnectionUri());
const service = new UserService(dataSource.getRepository(User));
const result = await service.createUser({ email: "a@b.com" });
// ✅ 直接查库验证,不依赖 mock
const saved = await dataSource.getRepository(User).findOneBy({ id: result.id });
expect(saved?.email).toBe("a@b.com");
await container.stop();
});
# 反例 — beforeAll 插入的数据被多个 test 修改,顺序不同结果不同
@pytest.fixture(scope="module")
def user(db):
return db.insert(User(name="shared")) # ❌ 模块级共享,多 test 互相干扰
def test_update_name(user, db):
db.update(user.id, name="changed") # 改了共享状态
def test_original_name(user, db):
assert user.name == "shared" # ❌ 若 test_update_name 先跑则失败
# 正例 — 每个 test 独立数据 + 事务回滚隔离
@pytest.fixture(autouse=True)
def db_transaction(db):
with db.begin_nested():
yield
db.rollback() # ✅ 每 test 结束自动回滚
def test_update_name(db):
user = db.insert(User(name="alice")) # ✅ 独立数据,不影响他人
db.update(user.id, name="changed")
assert db.get(user.id).name == "changed"