You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用SAVEPOINT和ROLLBACK TO后pgTAP报测试计划与执行数量不符

pgTAP中SAVEPOINT回滚导致测试计数警告的解决方法

问题原因

pgTAP通过会话级临时表跟踪测试执行记录(包括断言结果和计数),ROLLBACK TO SAVEPOINT会回滚该测试断言对临时表的写入操作。当你在最后一个测试的断言后执行ROLLBACK TO SAVEPOINT时,这条测试的执行记录会被回滚删除,导致finish()统计时只能识别到前两个测试的记录,从而抛出“计划3个测试但执行了2个”的警告。

解决方案

方案1:移除最后一个测试的ROLLBACK TO SAVEPOINT

整个测试流程在一个事务中,最后执行的ROLLBACK会回滚所有测试产生的数据修改,不会造成数据泄漏。因此最后一个测试无需额外执行ROLLBACK TO SAVEPOINT,既能保证数据隔离,又能让pgTAP正确统计所有测试:

BEGIN;
CREATE EXTENSION IF NOT EXISTS pgtap WITH SCHEMA extensions;
SELECT plan(3);

-- Test 1
SAVEPOINT sp;
-- 执行测试数据操作(如插入/修改)
SELECT ok(true, 'first test works');
ROLLBACK TO sp;

-- Test 2
SAVEPOINT sp;
-- 执行测试数据操作
SELECT ok(true, 'second test works');
ROLLBACK TO sp;

-- Test 3
SAVEPOINT sp;
-- 执行测试数据操作
SELECT ok(true, 'third test works');
-- 移除此处的ROLLBACK TO sp
SELECT * FROM finish();
ROLLBACK;

方案2:每个测试使用独立事务

如果需要完全隔离每个测试的会话状态,可以将每个测试放在独立事务中,pgTAP的会话级临时表会跨事务保留测试记录:

BEGIN;
CREATE EXTENSION IF NOT EXISTS pgtap WITH SCHEMA extensions;
SELECT plan(3);
COMMIT;

-- Test 1
BEGIN;
-- 执行测试数据操作
SELECT ok(true, 'first test works');
ROLLBACK;

-- Test 2
BEGIN;
-- 执行测试数据操作
SELECT ok(true, 'second test works');
ROLLBACK;

-- Test 3
BEGIN;
-- 执行测试数据操作
SELECT ok(true, 'third test works');
ROLLBACK;

BEGIN;
SELECT * FROM finish();
ROLLBACK;

方案3:调整SAVEPOINT使用顺序(针对数据修改型测试)

如果测试涉及数据修改,确保断言在数据修改后、回滚前执行,这样断言能验证修改后的结果,同时回滚仅清除测试数据,不影响pgTAP的测试记录(仅适用于非最后一个测试,最后一个测试仍需依赖方案1的处理):

-- 单个测试的正确流程
SAVEPOINT sp;
-- 1. 准备测试数据(插入/修改)
INSERT INTO your_table VALUES ('test_data');
-- 2. 执行断言,验证数据状态
SELECT ok( (SELECT count(*) FROM your_table WHERE value = 'test_data') = 1, 'data inserted correctly');
-- 3. 回滚测试数据,不影响其他测试
ROLLBACK TO sp;

内容的提问来源于stack exchange,提问作者Jasmin Mustafic

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 06:31:06