集成测试 - 可以做得对吗?

时间:2010-05-19 14:26:10

标签: unit-testing

在过去的两年里,我在一些项目中使用TDD作为开发风格,但我总是陷入同样的​​困境:如何测试程序各个部分的集成?

我目前正在做的是为每个类编写一个测试用例(这是我的经验法则:“单元”是一个类,每个类都有一个或多个测试用例)。我尝试通过使用模拟和存根来解决依赖关系,这非常有效,因为每个类都可以独立测试。经过一些编码后,所有重要的类都会进行测试然后我使用IoC容器将它们“连接”在一起。在这里,我陷入困境:如何测试布线是否成功,对象是否按照我想要的方式进行交互?

一个例子:想想一个Web应用程序。有一个控制器类,它接受一组id,使用存储库根据这些ID获取记录,然后迭代记录并将它们作为字符串写入outfile。

为简单起见,会有三个类:ControllerRepositoryOutfileWriter。他们每个人都是孤立地进行测试。

我要做的是测试“真正的”应用程序:使用数据库中的一些ID进行http请求(手动或自动),然后查看文件系统是否写入文件。当然,这个过程可以自动化,但仍然是:它不会复制测试逻辑吗?这是所谓的“集成测试”吗?在我最近阅读的关于单元测试的一本书中,在我看来,集成测试更像是一种反模式?

6 个答案:

答案 0 :(得分:4)

IMO,我没有文献可以支持我,但我们各种形式的测试之间的关键区别在于范围,

  • 单元测试是测试孤立的功能[通常是方法或有状态类]
  • 集成测试正在测试两个或多个相关部分的交互[通常是服务和消费者,甚至数据库连接,或与其他远程服务的连接]
  • 系统集成测试是端到端测试系统[集成测试的特例]

如果您熟悉单元测试,那么毫无疑问没有完美或“魔术子弹”测试。集成和系统集成测试非常类似于单元测试,因为每个测试都是为验证某种行为而设置的一套测试。

对于每个测试,您可以设置范围,然后决定输入和预期输出。然后执行测试,并将实际值评估为预期值。

在实践中,您可能很清楚系统的工作原理,因此编写典型的正面和负面路径测试将会很自然。但是,对于任何足够复杂的应用,期望对每种可能情况进行全面覆盖是不合理的。

不幸的是,这意味着在质量保证[QA],预生产[PP]和生产[产品]周期中会出现意外情况。此时,您尝试在dev中复制这些方案应该作为自动化测试进入集成和系统集成套件。

希望这会有所帮助,:))


ps:pet-peeve#1:管理员或开发人员调用集成和系统集成测试“单元测试”只是因为使用了nUnit或MsTest来自动化它...

答案 1 :(得分:3)

您所描述的确实是集成测试(或多或少)。不,它不是反模式,而是sw开发生命周期的必要部分。

任何相当复杂的程序都不仅仅是其各个部分的总和。所以无论你对它进行单元测试,你仍然没有太多关于整个系统是否按预期工作的线索<​​/ strong>。

为什么会出现以下几个方面:

  • 单元测试是在一个孤立的环境中进行的,因此他们无法说出程序各部分在现实生活中如何协同工作
  • “单位测试员帽子”很容易限制一个人的观点,因此有各种各样的因素,开发人员根本无法识别需要测试的因素*
  • 即使他们这样做,也有一些在单元测试中无法合理测试的东西 - 例如如何测试您的应用服务器是否在高负载下存活,或者在请求过程中数据库连接是否中断?

* 我刚从Luke Hohmann的书“Beyond Software Architecture”中读到的一个例子:在一个应用程序中,通过创建和维护实际机器中HW组件ID的“快照”来应用强大的反盗版防御,开发人员的代码非常适合单元测试。然后QA通过在没有网卡的机器上试用它,在10分钟内设法使应用程序崩溃。事实证明,由于开发人员正在开发Mac,他们理所当然地认为该机器有一个网卡,其MAC地址可以合并到快照中......

答案 2 :(得分:0)

  

我要做的是为了测试   “真正的”应用程序:制作http   请求(手动或自动)   与数据库中的一些ID和   如果是,请查看文件系统   文件写了。当然这个   流程可以自动化,但仍然:   不重复测试逻辑吗?

也许你是重复的代码,但你不是重复的努力。单元测试和集成测试有两个不同的目的,通常在SDLC中都需要这两个目的。如果可能,将用于单元/集成测试的代码分解为公共库。我还会尝试为您的单元/集成测试提供单独的项目b / c 您的单元测试应该单独运行(快速且无依赖性)。您的集成测试将更加脆弱并经常中断,因此您可能会有不同的策略来运行/维护这些测试。

  

这就是所谓的“整合   测试“?

确实是的。

答案 3 :(得分:0)

在集成测试中,就像在单元测试中一样,您需要验证测试中发生的情况。在您的示例中,您指定了OutfileWriter,您需要一些机制来验证文件和数据是否正常。你真的想要自动化这个,所以你可能想要一个:

Class OutFilevalidator {
    function isCorrect(fName, dataList) {
       // open file read data and
       // validation logic
}

答案 4 :(得分:0)

您可以查看“Taming the Beast”,这是Markus Clermont和John Thomas关于AJAX应用程序自动测试的演示文稿。 YouTube Video

相关文章的非常粗略的摘要:您希望使用最小的测试技术进行任何特定验证。以另一种方式拼写相同的想法,您试图最小化运行所有测试所需的时间,而不会牺牲任何信息。

因此,较大的测试主要是确保管道是正确的 - 实际上是插槽A中的标签A,而不是插槽B;这两个组成部分是否同意长度以米为单位,而不是以英尺为单位,等等。

执行代码路径会有重复,并且可能会重用一些设置和验证代码,但我通常不希望您的集成测试包含相同级别的组合爆炸,单位级别。

答案 5 :(得分:0)

使用BDD推动您的TDD将涵盖大部分内容。你可以使用Cucumber / SpecFlow和WatiR / WatiN。对于每个功能,它都有一个或多个场景,并且您一次处理一个场景(行为),当它通过时,您将转到下一个场景,直到该功能完成。

要完成一个场景,您必须使用TDD来驱动必要的代码,以使当前场景中的每个步骤都通过。这些方案对您的后端实现是不可知的,但是它们验证您的实现是否有效;如果在该应用程序的Web应用程序中存在某些不起作用,则该行为需要处于场景中。

正如其他人指出的那样,你当然可以使用集成测试。