从单元测试到集成测试的有效过渡

时间:2013-04-02 13:14:55

标签: c# java unit-testing testing

我目前正在研究如何在即将开展的项目中执行测试。为了在开发过程的早期发现错误,开发人员将在实际代码(TDDish)之前编写单元测试。单元测试将单独关注单元(在这种情况下是一种方法),因此依赖性将被模拟等等。

现在,我还想在与其他单位互动时对这些单元进行测试,我认为应该有一个有效的最佳实践,因为已经编写了单元测试。我的想法是单元测试将被重用,但被模拟的对象将被删除并替换为真实的对象。我现在的不同想法是:

  • 在每个测试类中使用全局标志,该标志决定是否应使用模拟对象。这种方法需要多个if语句
  • 使用创建“instanceWithMocks”或“instanceWithoutMocks”的工厂类。对于新开发人员来说,这种方法可能很麻烦,并且需要一些额外的类
  • 将集成测试与不同类中的单元测试分开。但是,这将需要大量冗余代码,并且维护测试用例将是工作的两倍

我认为所有这些方法都有利有弊。哪个是首选,为什么?有没有更好的方法从单元测试到集成测试的有效过渡?或者这通常以其他方式完成?

6 个答案:

答案 0 :(得分:5)

我会选择第三个选项

  • 从单元测试中分离出不同的集成测试 类。然而,这将需要许多冗余代码和 维护测试用例将是工作的两倍

这是因为单元测试和集成测试有不同的用途。单元测试表明,单独的功能单独工作。集成测试表明,当它们彼此交互时,不同的功能仍然有效。

因此,对于单元测试,您希望模拟事物,以便您只测试一个功能。

尽可能少地进行集成测试模拟。

我会将它们放在不同的项目中。在我的地方运作良好的是使用NUnit和Moq进行单元测试项目。编写代码时写入TDD。集成测试是Specflow / Selenium,功能文件是在计划会话中借助产品所有者编写的,因此我们可以验证我们是否提供了所有者想要的内容。

这确实可以在短期内创造额外的工作,但可以减少错误,更轻松的维护和交付匹配要求。

答案 1 :(得分:1)

像Ninject / Autofac / StructureMap这样的IoC容器可能对您有用。单元测试可以通过容器解决被测系统,只需注册是否有注册的模拟或真实对象。与您的工厂方法类似,但IoC容器是工厂。新开发人员需要一些培训才能理解,但任何复杂系统都是如此。这样做的缺点是注册场景可能会变得相当复杂,但是对于任何给定的系统来说,如果没有尝试它们,它们是否复杂很难说。我怀疑这是你没有找到任何看似确定的答案的原因。

答案 2 :(得分:1)

由于您正在测试不同的行为,因此集成测试应该是与单元测试不同的类。我认为集成测试的方式是,它们是您在尝试确保所有内容协同工作时执行的。他们将使用输入部分应用程序并确保返回预期的输出。

答案 3 :(得分:1)

我认为你搞砸了单元测试和集成测试的目的。 单元测试用于测试单个类 - 这是低级API。 集成测试正在测试类的协作方式。这是另一个更高级别的API。 通常,您不能在集成测试中重用单元测试,因为它们代表不同级别的系统视图。 使用spring上下文可能有助于为集成测试设置环境。

答案 4 :(得分:1)

我不确定将单元测试重用于真实对象而不是模拟是实现集成测试的正确方法。

单元测试的目的是验证与外界隔离的对象的基本正确性。模拟是为了确保隔离。如果你用真正的实现代替它们,你实际上最终会测试完全不同的东西 - 同一对象链的大部分的正确性,并且你多次对它进行冗余测试

通过使集成测试与单元测试不同,您将能够选择要验证的系统部分 - 通常,测试暗示配置,I / O,与第三个的交互的部分是个好主意。派对系统,用户界面或单元测试难以覆盖的任何其他内容。

答案 5 :(得分:1)

我同意大多数其他答案,单元测试应该与集成测试分离(选项3)

但我不同意你的反对意见:

  

[...]然而,这将是集成测试的分离单元   需要大量冗余代码,并且维护测试用例将是工作的两倍

使用测试数据生成对象可能需要做很多工作,但这可以重构为可以从中使用的测试助手clases ObjectMother 单元和集成测试,因此不需要冗余

在单元测试中,您可以检查测试类的不同条件。

对于集成测试,不需要重新检查每个特殊情况。 而是检查组件是否一起工作。

示例

您可能会针对引发异常的4种不同情况进行单元测试。 对于集成,不需要重新测试所有4个条件 一个与异常相关的集成测试足以验证集成系统是否可以处理异常。