集成testing中需要的数据库数据; 通过API调用创build或使用导入的数据?

这个问题或多或less是编程语言不可知的。 然而,现在我主要进入Java,这是我将从中画出的例子。 我也在考虑OOP的情况,所以如果你想testing一个方法,你需要一个方法类的实例。

unit testing的一个核心规则是它们应该是自治的,并且可以通过将类从它的依赖中隔离出来来实现。 有几种方法可以做到这一点,它取决于是否使用IoC注入依赖(在Java世界中,我们有Spring,EJB3和其他提供注入function的框架/平台),或者如果你模拟对象(对于Java你有JMock和EasyMock )将被testing的类从它的依赖关系中分离出来。

如果我们需要在不同的类中testing一组方法*,并且看到它们很好的集成,我们编写集成testing 。 这是我的问题!

  • 至less在Web应用程序中,状态通常被持久化到数据库。 我们可以使用与unit testing相同的工具来实现与数据库的独立性。 但在我看来,我认为有些情况下,不使用数据库进行集成testing太嘲讽(但随意不同意,根本不使用数据库,也是一个有效的答案,因为它使问题变得无关紧要)。
  • 当您使用数据库进行集成testing时,如何使用数据填充该数据库? 我可以看到两种方法:
    • 在开始testing之前,存储集成testing的数据库内容并加载它。 如果它被存储为SQL转储,数据库文件,XML或其他东西将是有趣的知道。
    • 通过API调用创build必要的数据库结构。 这些调用可能会分解成testing代码中的几种方法,每种方法都可能失败。 它可以被看作是依赖于其他testing的集成testing。

你如何确定需要testing的数据库数据? 你为什么select你select的方法?

请提供一个动机的答案 ,因为这是有趣的部分所在。 请记住,只是说“这是最好的做法!” 不是一个真正的动机,它只是重复你从某人读到或听到的东西。 那么请解释一下为什么这是最好的做法。

*我在unit testing的定义中包含了一个调用同一个类中的其他方法的方法,虽然在技术上可能是不正确的。 随时纠正我,但让我们保持它作为一个侧面的问题。

我更喜欢使用API​​调用创buildtesting数据。

在testing开始时,您将创build一个空的数据库(内存中或生产中使用的数据库),运行安装脚本对其进行初始化,然后创build数据库使用的任何testing数据。 testing数据的创build可以例如用对象母体模式来组织,以便相同的数据可以在许多testing中重复使用,可能具有较小的变化。

您希望在每次testing之前使数据库处于已知状态,以便具有无副作用的可重复testing。 所以当一个testing结束时,你应该放弃testing数据库或者回滚事务,这样下一次testing可以以同样的方式重新创buildtesting数据,而不pipe前面的testing是否通过。

为什么我会避免导入数据库转储(或类似),原因是它将testing数据与数据库模式耦合。 当数据库模式发生变化时,您还需要更改或重新创buildtesting数据,这可能需要手动工作。

如果testing数据是在代码中指定的,那么您将拥有IDE重构工具的能力。 当你做一个影响数据库模式的改变的时候,它可能也会影响到API调用,所以你无论如何都需要使用API​​来重构代码。 通过几乎相同的努力,您还可以重构testing数据的创build – 尤其是在重构可以自动化(重命名,引入参数等)的情况下。 但是,如果testing依赖于数据库转储,则除了重构使用API​​的代码之外,还需要手动重构数据库转储。

与集成testing数据库相关的另一件事是testing从以前的数据库模式升级是否正确。 为此,您可能需要阅读“ 重构数据库:进化数据库devise”或本文: http : //martinfowler.com/articles/evodb.html

在集成testing中,您需要使用真实数据库进行testing,因为您必须validation您的应用程序是否可以实际与数据库交谈。 将数据库隔离为依赖性意味着您正在推迟数据库是否正确部署的真实testing,您的模式是预期的,并且您的应用程序是使用正确的连接stringconfiguration的。 部署到生产环境时,您不希望发现任何问题。

您还需要使用预先创build的数据集和空数据集进行testing。 你需要testing你的应用程序以一个空的数据库开始,只有你的默认初始数据的path,并开始创build和填充数据,还有一个定义明确的数据集,针对特定条件你想testing,如压力,性能和等等。

另外,让每个状态之前你有一个知名的状态数据库。 您不希望在集成testing之间存在依赖关系。

为什么这两种方法被定义为排他性的?

  • 我看不到任何可行的论点, 使用预先存在的数据集,特别是在过去引起问题的特定数据。

  • 我无法看到任何可行的论点,因为没有以可编程的方式扩展这些数据,所有可能的情况都可以导致问题,甚至是一些随机数据进行集成testing

在现代的敏捷方法中 ,unit testing是每次运行相同testing都非常重要的地方。 这是因为unit testing的目的不在于发现错误,而在于保持应用程序开发的function,允许开发人员根据需要进行重构。

另一方面,集成testing旨在查找您不曾预料的错误。 在我看来,每次运行一些不同的数据甚至可以是好的。 如果发生故障,您只需确保您的testing保留了失败的数据。 请记住,在正式的集成testing中,应用程序本身将被冻结,除了错误修复,所以您的testing可以改变,以testing最大可能的数量和种类的错误。 在整合,你可以,应该扔在应用程序的厨房水槽。

正如其他人所指出的,当然,这一切当然取决于您正在开发的应用程序types和您所在的组织types等。

我通常使用SQL脚本填充您讨论的场景中的数据。

这是直接的,很容易重复。

我都这样做,这取决于我需要testing什么:

  • 我从SQL脚本或数据库转储导入静态testing数据。 这些数据用于对象加载(反序列化或对象映射)和SQL查询testing(当我想知道代码是否会返回正确的结果时)。

    另外,我通常有一些骨干数据(configuration,值名称查询表等)。 这些也加载在这一步。 请注意,这个加载是一个单独的testing(从头开始创build数据库)。

  • 当我有修改数据库的代码(对象 – >数据库),我通常运行它对一个活的数据库(在内存或testing实例的某处)。 这是为了确保代码的工作; 不要创build任何大量的行。 testing之后,我回滚事务(遵循testing不能修改全局状态的规则)。

当然,这个规则也有例外:

  • 我还在性能testing中创build了大量的行。
  • 有时候,我必须提交unit testing的结果(否则,testing会变得太大)。

我已经使用DBUnit在数据库中logging快照,并以XML格式存储它们。 然后我的unit testing(我们在需要数据库时称之为集成testing),可以在每次testing开始时从XML文件中擦除和恢复。

我不确定这是否值得。 一个问题是依赖于其他表。 我们只保留静态引用表,并构build了一些工具来检测和提取所有子表以及所需的logging。 我读过某人的build议,禁用集成testing数据库中的所有外键。 这将使数据准备工作更容易,但是您不再检查testing中的任何参照完整性问题。

另一个问题是数据库模式更改。 我们编写了一些工具,可以为添加快照以来添加的列的默认值。

显然这些testing比纯unit testing得多。

当你试图testing一些遗留的代码,很难为单个类编写unit testing时,这种方法可能是值得的。

听起来你的问题实际上是两个问题。 你应该使用从testing中排除数据库吗? 你什么时候做一个数据库,那么你应该如何在数据库中生成数据呢?

如果可能,我更喜欢使用实际的数据库。 在遇到实际的数据库时,CRUD类中的查询(用SQL,HQL等编写)往往会返回令人惊讶的结果。 尽早把这些问题清理出去更好。 开发者通常会为CRUD编写非常细的unit testing; 只testing最温和的情况。 使用实际的数据库进行testing可以testing您可能还没有意识到的各种angular落案例。

这就是说可以有其他问题。 每次testing之后,您都希望将数据库返回到已知状态。 我目前的工作是通过执行所有DROP语句来核实数据库,然后从头开始完全重新创build所有的表。 这在Oracle上非常慢,但如果使用内存数据库(如HSQLDB),速度可能会非常快。 当我们需要清除Oracle特定的问题时,我们只需更改数据库URL和驱动程序属性,然后针对Oracle运行。 如果您没有这种数据库可移植性,那么Oracle也具有某种数据库快照function,可以专门用于此目的; 将整个数据库回滚到之前的状态。 我确定其他数据库有什么。

根据数据库中的数据types,API或加载方法可能会更好或更差。 当你有很多关系的高度结构化的数据时,API将会使你的数据之间的关系更明确。 创buildtesting数据集时,您会很难犯错误。 正如其他海报所提到的,重构工具可以自动处理数据结构的一些变化。 通常我觉得将API生成的testing数据视为组合场景是有用的; 当一个用户/系统已经完成了步骤X,YZ,然后testing将从那里进行。 这些状态可以实现,因为你可以写一个程序调用你的用户使用的相同的API。

当您需要大量数据时,加载数据变得更加重要,您的数据之间几乎没有关系,或者使用API​​或标准关系机制无法expression数据的一致性。 在我的团队工作的一项工作是撰写大型networking数据包检测系统的报告应用程序。 数据量在当时是相当大的。 为了触发testing用例的有用子集,我们确实需要嗅探器生成的testing数据。 这样,关于一个协议的信息之间的相关性将与关于另一个协议的信息相关联。 在API中很难捕捉到这一点。

大多数数据库都有工具来导入和导出表格的分隔文本文件。 但是通常你只需要它们的子集; 使使用数据转储更复杂。 在我目前的工作中,我们需要获取一些由Matlab程序生成并存储在数据库中的实际数据。 我们有一个可以转储数据库数据子集的工具,然后将其与“testing结果”进行比较。 看来我们的提取工具正在不断修改。

这可能不会回答你所有的问题,但是我决定在一个项目中对数据库进行unit testing。 我觉得在我的情况下,数据库结构也需要testing,即我的数据库devise提供了应用程序所需的东西。 后来当我觉得DB结构稳定的时候,我可能会离开这个。

为了生成数据,我决定创build一个用“随机”数据填充数据库的外部应用程序,我创build了一个人名和公司名称生成器等。

在外部程序中这样做的原因是:1.我可以通过testing修改后的数据重新运行testing,即确保我的testing能够运行多次,并且testing所做的数据修改是有效的修改。 2.如果需要,我可以清理数据库并重新开始。

我同意这种方法有一些失败的地方,但是就我而言,因为例如人员生成是业务逻辑的一部分,所以生成testing数据实际上也在testing那部分。