20

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

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

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

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

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

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

有没有办法在数据库模式的沙子上画一条线,然后及时回滚到那个时间点?有点像一个大的“撤消”功能。除了 expdp/impdp 或 rman 之外的东西。也许整个方法都关闭了。建议?其他人是如何做到这一点的?

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

是否有产品可以帮助实现这种“撤消”能力?

4

4 回答 4

11

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

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

另一种方法是使用数据泵。您似乎放弃了 impdp 但 Oracle 还为它提供了 PL/SQL API DBMS_DATAPUMP。我在这里建议它,因为它提供了在运行导入之前丢弃任何现有数据的能力。所以我们可以有一个导出的数据集作为我们的测试夹具;执行设置是运行数据泵作业的问题。您无需在 TearDown 中执行任何操作,因为整理工作发生在 SetUp 开始时。

于 2011-06-10T22:45:42.390 回答
9

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

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

于 2011-06-10T21:21:18.087 回答
3

1.5 小时对于 1100 个表和 400K 的代码来说似乎是很长的时间。我显然不知道你的环境细节,但根据我的经验,我敢打赌你可以把它缩短到 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。花几百美元,给每个人提供个人版(与企业版具有相同的功能)。为每个人提供他们需要的工具,持续改进最终将解决您的问题。


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

于 2011-06-14T07:26:54.513 回答
0

尽管 Oracle 闪回是企业版功能,但它所基于的技术可用于所有版本,即 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 存储过程中。必须考虑执行语句的顺序。

我认为这样做的好处是允许事务提交,这是可能出现大量错误的地方,即参照完整性、主键违规等。

于 2013-02-09T09:28:15.167 回答