编写数据库大数据测试脚本_编写数据访问代码测试–数据事项

编写数据库大数据测试脚本

在为数据访问代码编写测试时,我们将数据集用于两个不同的目的:

  1. 在运行数据访问测试之前,我们将数据库初始化为已知状态。
  2. 我们验证从数据库中找到正确的更改。

这些看起来很容易。 但是,以使我们的生活痛苦并花费大量时间的方式弄乱事情非常容易。

这就是为什么我决定写这篇博客文章的原因。

这篇博客文章描述了在使用DbUnit数据集时我们可能犯的三个最常见的错误,更重要的是,这篇博客文章描述了如何避免出现这些错误。

DbUnit数据集的三个致命罪过

之所以像DbUnit这样的库享有如此糟糕的声誉,最常见的原因是,开发人员使用错误的方式,并且在他们开枪后抱怨。

的确,当我们使用DbUnit数据集时,我们会犯一些错误,这些错误会引起很多挫败感,并使我们花费大量时间。 这就是为什么我们必须了解这些错误是什么,以便避免犯下这些错误。

使用DbUnit数据集时,我们会犯三个常见(且代价高昂)的错误:

1.使用单个数据集初始化数据库

我们可能犯的第一个错误是使用单个数据集初始化数据库。 尽管如果我们的应用程序只有少数几个功能以及一个带有几个数据库表的小型数据库,这非常方便,但是如果我们在一个实际的软件项目中工作,情况可能并非如此。

奇怪的是,我们的应用程序具有许多功能,并且具有包含数十个(或数百个)数据库表的大型数据库。 如果我们在现实生活中的软件项目中使用这种方法,我们的数据集将是巨大的,因为:

  • 每个数据库表都会增加数据集的大小。
  • 测试数量增加了我们的数据集的大小,因为不同的测试需要不同的数据。

我们的数据集的大小是一个大问题,因为:

  • 数据集越大,在运行测试之前将使用过的数据库初始化为已知状态的速度就越慢。 更糟的是,当我们添加新的数据库表或编写新的测试时,我们的测试变得越来越慢。
  • 如果不阅读测试代码,就不可能找到与特定测试案例相关的数据。 如果一个测试用例失败,找出原因就比应该做的难得多。

假设我们必须为用于管理客户和办公室信息的CRM编写测试。 此外,每个客户和办公室都位于城市中。 我们的数据集的第一个版本如下所示:

<?xml version='1.0' encoding='UTF-8'?>
<dataset>
	<cities id="1" name="Helsinki"/>
	
	<customers id="1" city_id="1" name="Company A"/>
	
	<offices id="1" city_id="1" name="Office A"/>
</dataset>

我们可以立即看到,我们的测试套件必须为每个测试用例调用一个不必要的INSERT语句。 这看起来似乎没什么大不了,但是让我们看看当我们不得不为要列出位于特定城市的客户和办公室的功能编写测试时会发生什么。 编写完这些测试后,我们的数据集如下所示:

<?xml version='1.0' encoding='UTF-8'?>
<dataset>
	<cities id="1" name="Helsinki"/>
	<cities id="2" name="Tampere"/>
	<cities id="3" name="Turku"/>
	
	<customers id="1" city_id="1" name="Company A"/>
	<customers id="2" city_id="2" name="Company B"/>
	
	<offices id="1" city_id="1" name="Office A"/>
	<offices id="2" city_id="3" name="Office B"/>
</dataset>

我们可以看到,

  • 我们的测试套件必须为每个测试用例调用三个不必要的INSERT语句。
  • 目前尚不清楚哪些数据与特定测试用例相关,因为我们的数据集会在每次测试运行之前初始化整个数据库。

这看起来似乎不是灾难性的失败(不是),但是此示例仍然说明了为什么在为实际应用编写测试时我们不应该采用这种方法。

2.为每个测试用例或一组测试用例创建一个数据集

通过将单个数据集拆分为较小的数据集,我们可以解决该问题。 如果我们决定这样做,则可以为每个测试用例或一组测试用例创建一个数据集。

如果我们采用这种方法,则我们的每个数据集都应仅包含与测试用例(或多个测试用例)相关的数据。 这似乎是个好主意,因为我们的数据集较小,每个数据集仅包含相关数据。

但是,我们必须记住,通向地狱的道路是有良好意图的。 尽管我们的测试比使用单个数据集的测试要快,并且很容易找到与特定测试用例相关的数据,但是这种方法有一个主要缺点:

维护我们的数据集变得地狱。

因为许多数据集都包含插入到同一表中的数据,所以如果这些数据库表的结构发生了更改(或者我们应该说何时?),则维护这些数据集将需要大量工作。

如果在为较早引入的CRM编写测试时使用此方法,则可以将单个数据集拆分为两个较小的数据集。

第一个数据集包含我们编写用于管理客户信息的功能测试时所需的信息。 它看起来如下:

<?xml version='1.0' encoding='UTF-8'?>
<dataset>
	<cities id="1" name="Helsinki"/>
	<cities id="2" name="Tampere"/>
	
	<customers id="1" city_id="1" name="Company A"/>
	<customers id="2" city_id="2" name="Company B"/>
</dataset>

第二个数据集包含我们在编写用于管理办公室信息的功能的测试时所需的信息。 第二个数据集如下所示:

<?xml version='1.0' encoding='UTF-8'?>
<dataset>
	<cities id="1" name="Helsinki"/>
	<cities id="3" name="Turku"/>
	
	<offices id="1" city_id="1" name="Office A"/>
	<offices id="2" city_id="3" name="Office B"/>
</dataset>

如果我们更改城市表的结构会怎样?

究竟! 这就是为什么采用这种方法不是一个好主意的原因。

3.断言一切

我们可以按照以下步骤创建一个数据集,用于验证从数据库中找到正确的数据:

  1. 在运行测试之前,将从用于初始化数据库的数据集中找到的数据复制到已知状态。
  2. 将其内容粘贴到数据集,该数据集用于验证是否从数据库中找到了正确的数据。
  3. 对其进行所需的更改。

遵循这些步骤很危险,因为这很有意义。 毕竟,如果我们已经使用数据集X初始化了数据库,那么在创建用于确保从数据库中找到正确信息的数据集时使用该数据集似乎是合乎逻辑的。

但是,此方法具有三个缺点:

  • 很难得出预期的结果,因为这些数据集通常包含测试代码不会更改的信息。 这是一个问题,尤其是如果我们犯了一个或两个错误。
  • 由于这些数据集包含测试代码不会更改的信息(例如公用数据库表),因此维护这些数据集将需要进行许多不必要的工作。 如果我们更改这些数据库表的结构,则也必须对数据集进行相同的更改。 这是我们不想做的事情。
  • 由于这些数据集通常包含不必要的信息(经测试的代码不会更改的信息),因此验证从数据库中找到期望的信息的速度比可能要慢。

假设我们必须为更新客户信息的函数编写测试(更新后的客户的ID为2)。

在运行此测试之前,将使用过的数据库初始化为已知状态的数据集如下所示:

<?xml version='1.0' encoding='UTF-8'?>
<dataset>
	<cities id="1" name="Helsinki"/>
	<cities id="2" name="Tampere"/>
	
	<customers id="1" city_id="1" name="Company A"/>
	<customers id="2" city_id="2" name="Company B"/>
</dataset>

确保将正确的信息保存到数据库的数据集如下所示:

<?xml version='1.0' encoding='UTF-8'?>
<dataset>
	<cities id="1" name="Helsinki"/>
	<cities id="2" name="Tampere"/>
	
	<customers id="1" city_id="1" name="Company A"/>
	<customers id="2" city_id="1" name="Company B"/>
</dataset>

让我们逐一介绍该解决方案的缺点:

  • 因为我们的数据集非常小,所以很容易弄清楚应该更新哪些信息,但是却没有那么容易。 如果我们的数据集更大,那自然就会困难得多。
  • 该数据集包含从“ 城市”表中找到的信息。 由于此信息不会被测试函数修改,因此我们的测试必须做出不相关的断言,这意味着我们的测试比它们可能要慢。
  • 如果更改城市数据库表的结构,则必须修改数据集以验证是否已将正确的信息保存到数据库中。 这意味着维护这些数据集将花费大量时间,并迫使我们进行不必要的工作。

正确完成的数据集

现在,我们已经确定了开发人员在使用DbUnit数据集时犯的三个最常见的错误。 现在是时候找出我们如何避免犯这些错误并在测试中有效使用数据集了。

让我们开始仔细研究一个好的测试套件的需求。 一个好的测试套件的要求是:

  • 它必须易于阅读 。 如果我们的测试套件易于阅读,则它可以作为始终保持最新状态的文档,并且在测试用例失败时可以更快地找出问题所在。
  • 它必须易于维护 。 易于维护的测试套件将为我们节省大量时间,使我们可以更有效率地使用它。 另外,它可能会使我们免于很多挫败感。
  • 它必须尽可能快,因为快速测试套件可确保快速反馈,而快速反馈意味着我们可以更有效地利用时间。 同样,我们必须了解,尽管集成测试套件通常比单元测试套件要慢得多,但放弃此要求没有任何意义。 实际上,我声称我们必须更加注意它,因为如果这样做,我们可以大大减少测试套件的执行时间。

您可能想知道为什么我没有提到每个测试用例必须独立。 这确实是一个好的测试套件的一项重要要求,但我将其遗漏了,因为如果我们已经在使用DbUnit之类的工具,我们可能已经发现我们的测试用例一定不能依赖于其他测试用例。

既然我们知道测试套件的要求是什么,那么找出使用DbUnit数据集如何满足这些要求就容易得多。

如果要满足这些要求,则必须遵循以下规则:

1.使用小数据集

我们必须使用小型数据集,因为它们更易于阅读,并且可以确保我们的测试尽可能快。 换句话说,我们必须确定编写测试并仅使用该数据所需的最少数据量。

测试与客户相关的功能时用于初始化数据库的数据集如下所示:

<?xml version='1.0' encoding='UTF-8'?>
<dataset>
	<cities id="1" name="Helsinki"/>
	<cities id="2" name="Tampere"/>
	
	<customers id="1" city_id="1" name="Company A"/>
	<customers id="2" city_id="2" name="Company B"/>
</dataset>

另一方面,在运行与办公室相关功能的测试时,用于初始化数据库的数据集如下所示:

<?xml version='1.0' encoding='UTF-8'?>
<dataset>
	<cities id="1" name="Helsinki"/>
	<cities id="3" name="Turku"/>
	
	<offices id="1" city_id="1" name="Office A"/>
	<offices id="2" city_id="3" name="Office B"/>
</dataset>

如果查看突出显示的行,则会注意到我们的数据集使用不同的城市。 我们可以通过修改第二个数据集以使用与第一个数据集相同的城市来解决此问题。 完成此操作后,第二个数据集如下所示:

<?xml version='1.0' encoding='UTF-8'?>
<dataset>
	<cities id="1" name="Helsinki"/>
	<cities id="2" name="Tampere"/>
	
	<offices id="1" city_id="1" name="Office A"/>
	<offices id="2" city_id="2" name="Office B"/>
</dataset>

那么,有什么意义呢? 似乎我们没有取得什么成就,但是我们能够将二手城市的数量从三个减少到两个。 当我们看下一条规则时,这种小改进之所以有价值的原因变得显而易见。

通常,DbUnit数据集又大又凌乱,并且包含许多冗余数据。 在这种情况下,采用这种方法将使我们的数据集更具可读性,并使我们的测试变得更快。

2.将大型数据集划分为较小的数据集

我们已经创建了两个数据集,其中包含在运行测试之前初始化数据库所需的最少数据量。 问题在于两个数据集都包含“公共”数据,这使我们的数据集难以维护。

通过执行以下步骤,我们可以摆脱此问题:

  1. 标识多个数据集中使用的数据。
  2. 将该数据移动到一个单独的数据集(或多个数据集)。

我们有两个看起来如下的数据集(突出显示了常见数据):

<?xml version='1.0' encoding='UTF-8'?>
<dataset>
	<cities id="1" name="Helsinki"/>
	<cities id="2" name="Tampere"/>
	
	<customers id="1" city_id="1" name="Company A"/>
	<customers id="2" city_id="2" name="Company B"/>
</dataset>
<?xml version='1.0' encoding='UTF-8'?>
<dataset>
	<cities id="1" name="Helsinki"/>
	<cities id="2" name="Tampere"/>
	
	<offices id="1" city_id="1" name="Office A"/>
	<offices id="2" city_id="2" name="Office B"/>
</dataset>

我们可以通过创建单个数据集来消除维护问题,该数据集包含插入到citys表中的信息。 完成此操作后,我们获得了三个数据集,如下所示:

<?xml version='1.0' encoding='UTF-8'?>
<dataset>
	<cities id="1" name="Helsinki"/>
	<cities id="2" name="Tampere"/>
</dataset>
<?xml version='1.0' encoding='UTF-8'?>
<dataset>
	<customers id="1" city_id="1" name="Company A"/>
	<customers id="2" city_id="2" name="Company B"/>
</dataset>
<?xml version='1.0' encoding='UTF-8'?>
<dataset>
	<offices id="1" city_id="1" name="Office A"/>
	<offices id="2" city_id="2" name="Office B"/>
</dataset>

我们刚刚做了什么?

好吧,最重要的改进是,如果我们对citys表进行更改,则只需要对一个数据集进行这些更改。 换句话说,维护这些数据集比以前容易得多。

3.仅声明可通过测试代码更改的信息

前面我们看过一个数据集,该数据集可确保在更新客户信息时从使用的数据库中找到正确的信息。 问题在于数据集包含测试代码未更改的数据。 这意味着:

  • 由于我们的数据集包含不相关的数据,因此很难弄清楚预期结果。
  • 我们的测试比可能的要慢,因为它们必须做出无关紧要的断言。
  • 我们的测试很难维护,因为如果我们对数据库进行更改,那么我们也必须对数据集进行相同的更改。

遵循以下简单规则,我们可以解决所有这些问题:

我们必须仅声明可通过测试代码更改的信息。

让我们找出这个规则的含义。

之前我们创建了一个(问题性的)数据集,以确保在更新客户信息时(更新后的客户ID为2)将正确的信息信息保存到数据库中。 该数据集如下所示:

<?xml version='1.0' encoding='UTF-8'?>
<dataset>
	<cities id="1" name="Helsinki"/>
	<cities id="2" name="Tampere"/>
	
	<customers id="1" city_id="1" name="Company A"/>
	<customers id="2" city_id="1" name="Company B"/>
</dataset>

我们可以通过保留必要的数据并删除其他数据来解决其问题。 如果我们要编写一个测试来确保将正确客户的信息更新到数据库中,那么很明显我们不在乎从city表中找到的信息。 我们唯一关心的是从客户表中找到的数据。

从数据集中删除无关信息后,它看起来如下所示:

<?xml version='1.0' encoding='UTF-8'?>
<dataset>	
	<customers id="1" city_id="1" name="Company A"/>
	<customers id="2" city_id="1" name="Company B"/>
</dataset>

现在,我们已经解决了性能和维护问题,但是仍然存在一个问题:

我们的数据集有两行,尚不清楚哪一行包含更新的信息。 这不是一个大问题,因为我们的数据集很小,但是当我们使用更大的数据集时,这可能会成为一个问题。 我们可以通过在数据集中添加注释来解决此问题。

完成此操作后,我们的数据集如下所示:

<?xml version='1.0' encoding='UTF-8'?>
<dataset>	
	<customers id="1" city_id="1" name="Company A"/>
	
	<!-- The information of the updated customer -->
	<customers id="2" city_id="1" name="Company B"/>
</dataset>

好了很多。 对?

摘要

这篇博客文章告诉我们:

  • 通往地狱的道路充满了良好的意愿。 当我们使用DbUnit数据集时,我们可能犯的三个最常见的错误似乎是个好主意,但是如果我们在现实生活中的软件项目中犯了这些错误,那我们将一头雾水。
  • 通过使用小型数据集,将大型数据集划分为较小的数据集,并仅声明可通过测试代码更改的信息,可以避免DbUnit数据集引起的问题。

翻译自: https://www.javacodegeeks.com/2014/08/writing-tests-for-data-access-code-data-matters.html

编写数据库大数据测试脚本

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值