对大型数据库进行单元测试

时间:2009-04-09 20:27:51

标签: database unit-testing tdd

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

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

该应用程序的目的是管理信用协议申请的处理。有特定角色的用户可以更改agreement个对象的状态,我的工作是测试此过程的一部分。

我正在考虑两种方法:

第一种方法

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

好处

这种方法的优点是非常简单的测试。可以很容易地描述预期的数据,因为我确切地知道在转换之后对象应该是什么样子。

缺点

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


第二种方法

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

好处

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

缺点

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


您如何看待这两种方法?

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

这里有没有人有创建此类测试的经验?

3 个答案:

答案 0 :(得分:3)

我不确定我是否完全同意您在测试运行后无法恢复数据库的假设。虽然我绝对同意某些测试应该在一个全尺寸,多TB的数据库上运行,但我不明白为什么你不能在一个更小,更小的测试数据库上运行大多数测试。是否存在需要测试的限制,例如“不能超过十亿个相同的行?”

我的建议实际上是对大多数功能规范使用较小的测试数据库,并在每次测试时创建 - 丢弃所有表,并使用尽可能少的样本数据来测试您的功能。

答案 1 :(得分:2)

为了创建测试的夹具数据,您有几个选择:

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

(b)使用“工厂”创建此数据(某种应用程序代码)也很常见。在构建这些类时需要进行初始投资,但一旦构建完成,它们就可以重新用于所有测试。这在Ruby / Rails代码中非常流行。 (这是你上面的第二种方法。)

(c)当然,您可以使用“生产”数据的副本,并尝试对此进行测试。但这可能是最困难的方法,因为你将永远与现实世界改变数据竞争。而且它也往往比一小组夹具数据慢几个数量级。

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

有一个独立的问题。将数据导入数据库,然后运行测试后,需要将其还原。有几种常见的方法:

(1)回滚事务。这是一个很好的方法 - 如果可行的话。但有时,您确实需要确认交易已完成,因此无效。

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

(3)手动撤消测试所做的事情。这是最容易出错且最困难的方法,但可能。

建议?

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

另一个难题是数据库迁移,如果你还没有那个。这些是用于改进数据库的脚本。如果您有这些组织和自动化,您可以将它们应用于您的测试/夹具数据以及您的生产数据。

答案 2 :(得分:1)

如何测试交易中的所有内容然后将其回滚? E.g:

BeginTransaction
DoThings
VerifyResult
RollbackTransaction