如何实现Oracle PL / SQL的测试隔离测试?

时间:2011-06-10 21:10:15

标签: oracle unit-testing testing plsql isolation

在Java项目中,JUnit测试执行设置,测试和拆卸。即使在使用内存数据库模拟真实数据库时,通常也会回滚事务或从内存中删除数据库并在每次测试之间重新创建数据库。这为您提供了测试隔离,因为一次测试不会在可能影响下一次测试的环境中留下工件。每个测试都以已知状态开始,不能渗透到另一个测试中。

现在我有了一个Oracle数据库构建,可以创建1100个表和400K代码 - 很多pl / sql包。我不仅要测试db安装(完全 - 从头创建,部分 - 从以前的数据库升级等)并确保所有表和其他对象都处于安装后我期望的状态,但是也是在pl / sql上运行测试(我不确定我怎么做前者 - 建议?)。

我希望这一切都从Jenkins运行CI,以便通过回归测试捕获开发错误。

首先,我必须使用企业版而不是XE,因为XE不支持Java SP并且依赖于Oracle Web Flow。即使我消除了这些依赖关系,构建通常只需要1.5小时来加载(完整版本)。

那么你如何在这种环境中实现测试隔离?为每个测试使用事务并将其回滚?好的,那些提交它们的pl / sql程序怎么样?

我考虑过每次测试后重置数据库的备份和恢复,或者在每次测试之间重新创建整个数据库(过于激烈)。两者都不切实际,因为安装它需要一个多小时。每次测试都这样做是过度和疯狂。

有没有办法在db模式中绘制一条线,然后将其回滚到那个时间点? Sorta就像一个很大的“撤消”功能。除了expdp / impdp或rman之外的东西。也许整个方法都没有了。建议?其他人如何做到这一点?

对于CI或小型生产升级窗口,该测试套件必须在合理的时间内运行(30分钟是理想的)。

是否有可能有助于实现这种'撤销'能力的产品?

4 个答案:

答案 0 :(得分:11)

Kevin McCormack在The Server Labs Blog上发表了一篇关于使用Maven和Hudson对PL / SQL进行持续集成测试的文章。 Check it out。测试组件的关键要素是Steven Feuerstein's utPlsql框架,它是PL / SQL中JUnit概念的实现。

重置测试夹具的需求是PL / SQL测试的一个重大问题。有一点有助于观察良好实践并避免在存储过程中提交:事务控制应仅限于调用堆栈的最外层部分。对于那些只需要发出提交的程序(可能是因为它们执行DDL而隐式),总会有一个测试夹具发出DELETE语句。处理关系完整性使代码非常棘手。

另一种方法是使用数据泵。您似乎放弃了impdp,但Oracle也为它提供了PL / SQL API,DBMS_DATAPUMP。我在这里建议它,因为它提供了在运行导入之前删除任何现有数据的功能。所以我们可以将导出的数据集作为我们的测试夹具;执行SetUp是运行数据泵作业的问题。你不需要在TearDown中做任何事情,因为整理是在SetUp开始时进行的。

答案 1 :(得分:9)

在Oracle中,您可以使用闪回技术将服务恢复到某个时间点。

http://download.oracle.com/docs/cd/B28359_01/backup.111/b28270/rcmflash.htm

答案 2 :(得分:3)

对于1100个表和400K代码来说,1.5小时似乎很长。我显然不知道你的环境的细节,但根据我的经验,我打赌你可以把它缩小到5到10分钟。以下是我在Oracle中看到的两个主要安装脚本问题:

<强> 1。操作分为小部分

您拥有的步骤越多,开销就越多。例如,您希望尽可能合并这样的代码:

替换:

create table x(a number, b number, c number);
alter table x modify a not null;
alter table x modify b not null;
alter table x modify c not null;

使用:

create table x(a number not null, b number not null, c number not null);

替换:

insert into x values (1,2,3);
insert into x values (4,5,6);
insert into x values (7,8,9);

使用:

insert into x
select 1,2,3 from dual union all
select 4,5,6 from dual union all
select 7,8,9 from dual;

如果您在不同位置运行脚本和数据库,则尤其如此。当你将它乘以10,000时,那个微小的网络滞后开始变得重要。我所知道的每个Oracle SQL工具都会一次发送一个命令。

<强> 2。开发人员必须共享数据库

这是一个长期的流程解决方案,而不是技术修复,但你必须在某个时候开始。大多数使用Oracle的地方只在几台服务器上安装它。然后,它成为一个必须谨慎管理的稀缺资源。人们争夺它,角色不清楚,事情没有得到解决。

如果这是您的环境,请立即停止疯狂并在每台笔记本电脑上安装Oracle。花几百美元给每个人个人版(具有与企业版相同的功能)。为每个人提供他们需要的工具,持续改进最终将解决您的问题。


此外,对于模式“撤消”,您可能希望查看可传输的表空间。我从来没有使用它,但据说它是一种更快的安装系统的方式 - 只需复制和粘贴文件而不是导入。同样,也许某种类型的虚拟化可以提供帮助 - 创建操作系统和数据库的快照。

答案 3 :(得分:0)

虽然Oracle Flashback是企业版功能,但它所基于的技术在所有版本中都可用,即Oracle Log Miner:

http://docs.oracle.com/cd/B28359_01/server.111/b28319/logminer.htm#i1016535

我很想知道是否有人使用它来为功能测试提供测试隔离,即查询v $ LOGMNR_CONTENTS以从对应于测试开始的时间点获取UNDO语句列表。

数据库需要处于归档模式,在junit测试用例中需要使用

注释的方法
@Startup 

将调用DBMS_LOGMNR.START_LOGMNR。测试将运行,然后在使用

注释的方法中运行
@Teardown

将查询v $ LOGMNR_CONTENTS以查找UNDO语句列表。然后这些将通过JDBC执行。实际上,可以将查询和执行UNDO语句提取到PLSQL存储过程中。必须考虑执行语句的顺序。

我认为这有一个好处,允许事务提交,这是很多bug可能蔓延的地方,即参照完整性,主键违规等。