针对大型数据库的单元测试

Unit testing against large databases

我想问一下您对大型数据库进行单元测试的建议。

我想为一个大多数是在T-SQL中实现的应用程序编写单元测试,因此模拟数据库不是一个选择。
数据库很大(大约10GB),因此在测试运行后恢复数据库实际上也是不可能的。

该应用程序的目的是管理信贷协议中的应用程序处理。有些用户具有更改agreement对象状态的特定角色,而我的工作是测试此过程的一部分。

我正在考虑两种方法:

第一种方法

创建符合特定条件的协议,然后测试协议状态的更改(例如,从在某个办公室等待到在该特定办公室处理)。这些协议将在应用程序本身中创建,它们将成为我的测试用例。所有测试都将包含在执行这些测试后将回滚的事务中。
好处

这种方法的优点是非常简单的测试。可以很容易地描述预期的数据,因为我完全知道转换后对象的外观。

缺点

缺点是数据库无法以破坏测试的方式进行更改。测试用例中使用的用户和协议必须始终看起来相同,如果需要更改数据库,则必须重复准备过程。

第二种方法

在单元测试中创建协议。以编程方式创建符合特定条件的协议。用于创建协议的数据将是随机选择的。同样,将随机创建将更改协议状态的用户。

好处

此方法的优点是易于更改对象,并能够在具有不同数据的数据库上运行测试。

缺点

两个对象(协议和用户)都有很多字段和相关数据,而且恐怕要花一些时间来实现这些对象的创建(我也担心这些对象可能包含一些错误,因为创建方法如果没有错误,将很难实现)。

您如何看待这两种方法?

是否有任何Stack Overflow读者都值得按照第二种方法描述的那样创建对象?

这里的任何人都有创建此类测试的经验吗?


我不确定我是否完全同意您的假设,即您无法在测试运行后还原数据库。尽管我绝对同意某些测试应该在全尺寸,多TB数据库上运行,但我不明白为什么您不能在一个小得多的测试数据库上运行大多数测试。是否存在需要测试的约束,例如"不能超过十亿个相同的行?"

实际上,我的建议是对大多数功能规格使用较小的测试数据库,并在每次测试时创建并删除其所有表,并尽可能减少测试功能所需的样本数据。


要为测试创建夹具数据,您有几种选择:

(a)创建一个脚本,该脚本创建一个空数据库,然后添加少量记录作为灯具数据。这些数据可以是手动构建的,也可以是真实数据库中的一些记录。这是Rails的方法,在Java世界中很常见。

(b)使用"工厂"来创建此数据(某种应用程序代码)也是很常见的。建立这些类需要最初的投资,但是一旦建立了它们,就可以将它们重新用于您的所有测试。现在,这在Ruby / Rails代码中非常流行。 (这是您上面的第二种方法。)

(c)当然,您可以使用" production "数据的副本,并尝试对此进行测试。但这可能是最困难的方法,因为您将始终与现实世界中不断变化的数据竞争。而且它也往往比一小组夹具数据要慢几个数量级。

从状态(c)转换为状态(a)或(b)肯定有成本,但这是对未来的投资。它不会花费那么长时间-即使花费一整天,测试运行中的加速也会很快弥补它。

有一个与某人无关的问题。将数据放入数据库中,然后运行测试之后,需要将其还原。有几种常见的方法:

(1)回滚事务。如果可行,这是一个很好的方法。但是,有时候,您实际上需要确认事务已完成,因此这是行不通的。

(2)只需重新加载一组新的夹具数据。如果您的灯具数据很小,这是可行的。比(1)慢一点。

(3)手动撤消测试已完成的操作。这是最容易出错且最困难的方法,但是可能的。

推荐?

听起来您的应用程序很复杂。我建议您为测试(a)手工制作少量数据。将其与主数据库分开,以便更轻松地跟踪和重新加载。尝试回滚事务,但是如果这对您不起作用,则可以在每次测试之前从脚本重新加载(记住-数据很小)。

难题的另一部分是数据库迁移,如果您还没有确定的话。这些是用于演化数据库的脚本。如果您具有这些组织且自动化的功能,则可以将它们应用于测试/夹具数据以及生产数据。


如何测试事务中的所有内容然后将其回滚?例如:

1
2
3
4
BeginTransaction
DoThings
VerifyResult
RollbackTransaction