您使用哪些最佳实践来测试数据库查询?

时间:2008-11-03 23:36:19

标签: database tdd integration-testing end-to-end

我目前正在测试我们的解决方案,该解决方案具有完整的“色域”层:UI,中间和无所不在的数据库。

在我到达现有团队之前,查询测试是由测试人员手动制作的查询完成的,这些查询理论上会根据各种相关性规则返回存储过程应返回的结果集,排序,你有什么。

这会产生针对测试人员查询的错误的副作用,而不是针对相关的实际查询。

我建议实际使用一个已知的结果集,你可以推断它应该如何返回,因为你控制了存在的数据 - 之前,数据是从生产中提取的,已经消毒,然后填充在我们的测试数据库中。

人们仍然坚持创建自己的查询来测试开发人员创建的内容。我怀疑还有很多人。在我看来,这根本不是理想的,只是不必要地增加了我们的测试足迹。

所以,我很好奇,您使用哪种做法来测试这样的场景,以及在不引入混乱数据的情况下,您可以获得最佳端到端覆盖的理想选择?

我遇到的问题是进行测试的最佳位置。我是否只是直接戳服务,并将该数据集与我可以从存储过程中提取的数据进行比较?我有一个粗略的想法,并且到目前为止已经取得了足够的成功,但我觉得我们仍然缺少一些重要的东西,所以我希望社区能够看到他们是否有任何有价值的见解可能有助于制定我的测试方法更好。

9 个答案:

答案 0 :(得分:3)

测试存储过程将要求每个测试人员都有一个单独的db实例。这是一项要求。如果您共享环境,则无法依赖测试结果。他们将毫无价值。

您还需要确保在每次测试后将数据库回滚到之前的状态,以使结果可预测且稳定。由于需要在每次测试后回滚状态,这些测试比标准单元测试需要更长的时间才能完成,所以它们可能是你想要运行一夜的东西。

有一些工具可以帮助您解决这个问题。 DbUnit就是其中之一,我也相信微软有一个Visual Studio for Database Professionals工具,它包含对数据库测试的一些支持。

答案 1 :(得分:3)

以下是一些指导原则:

  1. 使用隔离数据库进行单元测试(例如,没有其他测试运行或活动)
  2. 始终在同一测试中插入您要查询的所有测试数据
  3. 编写测试以随机创建不同数量的数据,例如随机插入数量表示1到10行
  4. 随机化数据,例如对于布尔字段随机插入和真或假
  5. 在变量测试中保持计数(例如行数,真实数量)
  6. 对于Asserts执行查询并与本地测试变量进行比较
  7. 使用企业服务事务将数据库回滚到以前的状态
  8. 请参阅以下链接,了解企业服务交易技术:

    http://weblogs.asp.net/rosherove/articles/DbUnitTesting.aspx

答案 2 :(得分:1)

作为我们持续集成的一部分,我们运行数据库查询的夜间“构建”。这涉及一组数据库调用,这些调用会定期从代码中的实际调用以及任何预期的即席查询中更新。

这些来电是为了确保:

1 /它们不会花太长时间。

2 /他们与前一晚的情况差别不大(差劲很大)。

通过这种方式,我们可以快速捕获错误的查询或数据库更改。

答案 3 :(得分:1)

查询计划程序是您的朋友,尤其是在这种情况下。最好检查一下索引是否在您期望使用时使用,并且查询不需要执行额外的工作。即使您的套件中包含压力测试,在应用程序开始停止之前捕获昂贵的查询仍然是一个好主意。

答案 4 :(得分:1)

我们为每个开发人员和测试人员预留了一个空白数据库。

运行测试时 - 每个测试都会清除数据库并加载它希望使用的数据。这在任何时候都给我们一个已知的状态。

然后我们可以在同一个数据库上测试几个不同的场景(一个接一个),我们永远不会在另一个测试者脚趾上标记。

这包括测试数据访问本身。对于服务测试,我们做了很多相同的事情,但我们只测试服务的内部 - 我们实际上没有点击服务,我们创建服务处理类的实例并传递我们需要的一切。这样我们就会测试代码而不是基础设施(消息等)。

答案 5 :(得分:1)

Django提供数据库单元测试功能。您可以借用他们的设计理念并在其他环境中重现它。

Django人员提供Python的标准unittest TestCase类的子类,该类使用已知的fixture来填充数据库 - 一组已知的数据行。

对于Django(和Python),最简单的方法是从JSON数据提取中填充数据库。夹具的其他文件格式可用于其他框架。例如,如果您在Oracle中工作,则可能会发现CSV文件更易于使用。

这个TestCase子类允许编写一个看起来很典型的TestCase,它使用已知的数据夹具来运行数据库。

此外,Django测试运行器为测试目的创建临时模式。这对Django来说很容易,因为它们有一个包含DDL创建的完整的对象 - 关系管理组件。如果您没有这个,那么您仍然需要DDL脚本,这样您就可以创建和处理测试模式以进行单元测试。

答案 6 :(得分:1)

SQLServerCentral有一篇文章here(您可能需要注册,但它是免费的,没有字符串)有关称为tsqlUnit的TSQL单元测试框架。它是开源的,并遵循xUnit框架的传统。

遵循SEAT TDD模式:

设置 - 通过操作对象,表格和/或数据来准备测试条件

练习 - 调用生产代码

断言 - 检查实际结果是否等于预期结果

拆解 - 将所有内容恢复到测试开始前的状态。这实际上是通过回滚事务来完成的,这样可以保证一切都很整洁。

虽然我没有使用它,但看起来很有希望,我肯定会更详细地看一下。

可以下载框架here

答案 7 :(得分:0)

我发现测试发送到数据库的SQL而不是查询数据库的结果很有用。

并不是说我不做以后的事情,但我发现测试它的速度要快于提升数据库的速度。

答案 8 :(得分:0)

这是一个繁重的设置,但是我建议使用TDDing容器。

在运行测试脚本后,构建一个新容器,该数据库将在内部运行数据库,并向其填充模拟数据,然后运行查询并针对返回的内容以及查询是否成功进行测试。

通过这种方式,您可以控制测试环境接近生产环境的程度。

ThoughtWorks