使用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
相关产品推荐
相关产品推荐

