58 testing integration-testing unit-testing mocking
这个问题或多或少与编程语言无关.然而,由于我现在主要使用Java,所以我将从中绘制示例.我也在考虑OOP的情况,所以如果你想测试一个方法,你需要一个该方法类的实例.
一个核心规则的单元测试是,他们应该是自主的,并且可以通过从它的依赖隔离一个类来实现.有几种方法可以做到这一点,这取决于你是否使用IoC注入依赖项(在Java世界中我们有Spring,EJB3和其他提供注入功能的框架/平台)和/或如果你模拟对象(对于Java你有JMock和EasyMock)将正在测试的类与其依赖项分开.
如果我们需要测试不同类中的方法组*并看到它们是很好的集成,我们编写集成测试.这是我的问题!
当您需要时,如何确保测试所需的数据库数据?你为什么选择你选择的方法?
请提供一个动机的答案,因为这是有趣的部分所在的动机.请记住,只是说"这是最好的做法!" 这不是一个真正的动机,它只是重复你从别人那里读过或听过的东西.对于这种情况,请解释为什么这是最佳做法.
*我在单元测试的定义中包含一个在同一个类的(相同或其他)实例中调用其他方法的方法,即使它在技术上可能不正确.请随意纠正我,但让我们把它作为一个侧面问题.
Esk*_*ola 51
我更喜欢使用API调用创建测试数据.
在测试开始时,您将创建一个空数据库(内存中或生产中使用的相同),运行安装脚本以初始化它,然后创建数据库使用的任何测试数据.可以例如利用对象母模式来组织测试数据的创建,使得可以在许多测试中重用相同的数据,可能具有微小的变化.
您希望在每次测试之前使数据库处于已知状态,以便具有可重复的测试而没有副作用.因此,当测试结束时,您应该删除测试数据库或回滚事务,以便下一个测试可以始终以相同的方式重新创建测试数据,无论先前的测试是通过还是失败.
我之所以要避免导入数据库转储(或类似),是因为它会将测试数据与数据库模式耦合在一起.当数据库架构发生更改时,您还需要更改或重新创建测试数据,这可能需要手动操作.
如果在代码中指定了测试数据,那么您将掌握IDE的重构工具的强大功能.当您进行影响数据库架构的更改时,它可能也会影响API调用,因此您无论如何都需要使用API重构代码.通过几乎相同的工作,您还可以重构测试数据的创建 - 特别是如果重构可以自动化(重命名,引入参数等).但是,如果测试依赖于数据库转储,除了重构使用API的代码之外,还需要手动重构数据库转储.
与集成测试数据库相关的另一件事是测试从先前的数据库模式升级是否正常.为此,您可能需要阅读" 重构数据库:进化数据库设计 "一书或本文:http://martinfowler.com/articles/evodb.html
听起来你的问题实际上是两个问题。您应该从测试中排除数据库吗?当你做数据库的时候,那么数据库中的数据应该如何生成呢?
如果可能的话,我更喜欢使用实际的数据库。当面对实际数据库时,CRUD 类中的查询(用 SQL、HQL 等编写)通常会返回令人惊讶的结果。最好尽早解决这些问题。通常,开发人员会为 CRUD 编写非常薄的单元测试;只测试最良性的病例。使用实际的数据库进行测试可以测试您可能不知道的各种极端情况。
话虽如此,可能还有其他问题。每次测试后,您希望将数据库返回到已知状态。在我当前的工作中,我们通过执行所有 DROP 语句来破坏数据库,然后从头开始完全重新创建所有表。这在 Oracle 上非常慢,但如果您使用 HSQLDB 等内存数据库,则速度会非常快。当我们需要解决 Oracle 特定问题时,我们只需更改数据库 URL 和驱动程序属性,然后针对 Oracle 运行。如果您没有这种数据库可移植性,那么 Oracle 还具有某种数据库快照功能,可以专门用于此目的;将整个数据库回滚到之前的某个状态。我确定其他数据库也有。
根据数据库中的数据类型,API 或加载方法可能会工作得更好或更差。当您拥有具有多种关系的高度结构化数据时,API 将使数据之间的关系变得明确,从而使您的生活变得更轻松。创建测试数据集时,您将更难犯错误。正如其他海报所提到的,重构工具可以自动处理数据结构的一些更改。我经常发现将 API 生成的测试数据视为构成场景很有用;当用户/系统完成步骤 X、YZ 后,测试将从那里开始。可以实现这些状态,因为您可以编写一个程序来调用用户将使用的相同 API。
当您需要大量数据、数据之间几乎没有关系或者数据存在无法使用 API 或标准关系机制表示的一致性时,加载数据就变得更加重要。我团队的一项工作是为大型网络数据包检查系统编写报告应用程序。当时的数据量相当大。为了触发有用的测试用例子集,我们确实需要嗅探器生成的测试数据。这样,有关一个协议的信息之间的相关性将与有关另一协议的信息相关联。在 API 中很难捕捉到这一点。
大多数数据库都有用于导入和导出表的分隔文本文件的工具。但通常您只需要其中的子集;使使用数据转储变得更加复杂。在我目前的工作中,我们需要转储一些由 Matlab 程序生成并存储在数据库中的实际数据。我们有工具可以转储数据库数据的子集,然后将其与“基本事实”进行比较以进行测试。看来我们的提取工具正在不断修改。
为什么这两种方法被定义为完全不同的?
对于不使用预先存在的数据集,尤其是过去造成问题的特定数据,我看不出任何可行的论据 。
我看不到任何可行的论据,即不以 编程方式扩展该数据的所有可能条件,您可以想象会导致问题,甚至是一些用于集成测试的随机数据。
在现代敏捷方法中,单元测试是每次运行相同测试真正重要的地方。这是因为单元测试的目的不是发现错误,而是在开发应用程序时保留应用程序的功能,允许开发人员根据需要进行重构。
另一方面,集成测试旨在发现您没有预料到的错误。在我看来,每次运行一些不同的数据甚至可能是好的。如果失败,您只需要确保您的测试保留失败的数据。请记住,在正式的集成测试中,除了错误修复之外,应用程序本身将被冻结,因此您可以更改测试以测试最大可能数量和类型的错误。在集成中,您可以而且应该将厨房水槽扔到应用程序上。
正如其他人所指出的那样,当然,所有这些自然取决于您正在开发的应用程序类型以及您所在的组织类型等。
在集成测试中,您需要使用真实数据库进行测试,因为您必须验证您的应用程序是否可以实际与数据库通信.将数据库隔离为依赖关系意味着您推迟了对数据库是否已正确部署的真实测试,您的架构是否符合预期,并且您的应用程序配置了正确的连接字符串.部署到生产环境时,您不希望发现这些问题.
您还希望使用预先创建的数据集和空数据集进行测试.您需要使用仅包含默认初始数据的空数据库测试应用程序启动的路径,并开始创建和填充数据,还需要定义明确定义的数据集,这些数据集针对您要测试的特定条件,如压力,性能和等等.
另外,在每个州之前,让您拥有一个众所周知的数据库.您不希望在集成测试之间存在依赖关系.