2

我有我的单元测试。每种测试方法都在我的系统中测试功能的逻辑单元。在我的单元测试中,外部依赖项(db、文件等)是通过使用 Mocks 和 Fakes 来处理的。

现在我不是 100% 确定我应该如何进行集成测试。我应该重复单元测试并用实际资源(数据库、文件等)替换,还是应该测试更低级别的东西,例如:

1) 可以 ping 数据库
2) 可以检索一条记录
3) 文件是否存在
等...

我的直觉是我应该在这个阶段避免商业逻辑,因为大部分应该在 Unit 中完成,对吧?

谢谢

编辑:我在撰写问题时有点懒惰,我还想知道的是,如果我需要在集成阶段测试 biz 逻辑,那么我应该如何设置我的测试套件以最大限度地减少测试代码重复。举个例子:

[TestMethod] //Unit Tests
public void CanGetData()
{
IRepository rep = new MockRepository();
var result = rep.GetData();
Assert.IsTrue(result != null)
}

[TestMethod] //Integration Test
public void CanGetData()
{
IRepository rep = new Repository(); //real repository
var result = rep.GetData();
Assert.IsTrue(result != null)
}

哪种测试结构适合您?您是否直接在集成项目中使用单元测试程序集并注入正确的资源?

4

5 回答 5

4

集成测试不应回避任何业务逻辑。集成测试的重点是验证您的应用程序域的不同部分的行为,它们紧密地协同工作。这包括您的业务逻辑。

单元测试验证单个工作单元在特定条件下是否正确运行。但是,这并不能保证所述“工作单元”将与您系统中的其他“工作单元”一起正确运行。这就是集成测试在您的测试套件中发挥关键作用的地方。

系统的实际资源(数据库、文件等)应该在某个时候引入到您的测试套件中,尽管不是在您的单元测试中。大多数人发现集成测试是包含您的资源的合适位置。请注意,将环境资源包含到您的测试套件中可能是一项艰巨的任务。此外,它肯定会减慢您的集成测试。

我还将我的单元测试和集成测试分开。我更喜欢单独的程序集。这样我就可以通过我的测试器分别运行每个套件并获得每个套件的结果。再次,这里的原因是因为您的集成测试通常需要比单元测试更长的时间来运行。

于 2009-06-08T15:16:54.297 回答
3

好吧,不要害羞,但在您的集成测试中,您应该测试集成。您需要更广泛的测试来展示组件协同工作,而不是测试单个单元。在某些时候,您通常还希望证明您的系统可以使用真实资源而不是模拟。

所以,是的,通常你应该用真实的数据库等进行测试。你还应该测试业务逻辑,即使它已经过单元测试。您基本上应该最终运行场景以从头到尾测试每个用户可访问的功能,并确认结果(包括数据库的内容)符合预期。

于 2009-06-08T15:17:38.617 回答
2

YMMV 在这里有很大的定义。恕我直言,“单元测试”一词已经受到语言漂移的影响。(有关更多信息,请参阅我的博客文章)。

听起来您对单元测试是什么有了很好的理解。在这种情况下,通过解释它不是什么来定义它是什么可能会更容易。集成测试实际上是一种自动化测试,它不是单元测试(提供您的定义)。我相信集成测试是一个相互排斥的类别,它包含了我们用于自动化测试的所有其他技术,其中系统中的组件实际上是相互通信的。正如您所说,这意味着任何外部依赖项都存在于您的测试上下文中。

其他人可能同意也可能不同意,但重要的一点是,给定测试的可维护性会随着测试上下文大小的增加而增加。上下文越大,测试就越慢且可维护性越差。

正因为如此,你真的要考虑在这个级别的测试中你会得到什么。您确实需要持续集成来维护集成测试,并且如果它们需要很长时间运行,则可能需要安排它们以间隔运行。通常,当它们中断时,它们将更难诊断故障(因为它们更复杂),因此如果要在您的测试套件中连续运行,您将希望确保该测试提供明确的业务价值。另一种说法是,有不好的测试比没有测试更糟糕。这就是为什么单元测试对于作为开发人员的你来说真的是最重要的。在高于隔离单元/组件的水平上进行测试提供的成本更低。

命名和记录在这里可以有很大帮助,但要小心。编写直接针对需求/功能或回归/错误的集成测试。如果是“冒烟测试”,则测试您最关心的东西,或者最容易破坏的东西。你需要务实。

希望这可以帮助。

于 2009-06-08T15:44:25.320 回答
1

单元测试检查单个组件是否工作。“组件”就像“您可以构建的最小的东西并且可以做某事”。这些验证组件的内部工作。

集成测试验证组件之间的接口。示例:我的班级可以将数据写入真实数据库吗?它是否正确处理来自数据库的错误?当我将这些数据放入数据库时​​,我会在 webapp 中看到它吗?

通常,两者之间的界限有点​​流畅。您将在单元测试中放置“X 类是否可以持久化”(尽管这实际上是一个集成测试)。

大多数项目通过努力将测试分开:如果大多数开发人员无需设置即可运行它们,他们会说“单元测试”。如果您需要准备几台计算机(加载数据,启动程序,确保它所属的版本正确),那么这就是我所说的“集成测试”。

请注意,这两个测试都可以(并且应该)自动化。

于 2009-06-08T15:17:58.083 回答
0

要回答您编辑的问题,(您可能想重新表述或将其完全分解为单独的问题......)您肯定想要分离关注点,并且肯定想要使用依赖注入。隔离依赖并使用配置注入它们;这允许您交换配置中的对象而不是代码。这样,您就可以将对象的初始化完全排除在测试代码之外。(您还可以将配置用于登台和生产环境......)

我通常为此使用 Spring,但任何 DI/IoC 容器都会为您提供此功能。这是最可配置的方法,如果您已经在进行依赖注入,则效果很好。它也非常符合将两个套件分开的想法。

于 2009-06-08T16:18:46.033 回答