【问题标题】:Efficiency pitfalls of doing both Integration and Acceptance testing (automated) [closed]进行集成和验收测试(自动化)的效率陷阱[关闭]
【发布时间】:2011-01-05 19:08:41
【问题描述】:

单元测试的优势对我来说是显而易见的,它们由开发人员自己完成(测试或代码优先)并且是自动化的。

我有点不确定的是,当团队已经由一名专门的测试人员组成时,开发人员是否也应该进行集成测试,他们尽可能地自动化并对整个系统进行黑盒测试(端到端测试或更常见的术语验收测试)。

有关简短背景的更多详细信息:

示例集成测试(MVC webapp)

  • 设置:只有控制器本身和控制器下面的层在测试设置期间被引导。没有任何东西被嘲笑或存根。
  • 测试入口:裸控制器,通常控制器入口点是带参数的方法(例如 Spring MVC),可以本地执行。测试夹具期间不涉及浏览器
  • 断言目标:模型数据和视图名称被断言为直接输出。也可以断言间接输出(例如写入数据库的数据)。渲染的有效负载(通常是 HTML)被完全忽略。

示例验收测试(MVC webapp)

  • 设置:整个 web 应用程序都是自举的(就像从最终用户看到的那样)。
  • 测试条目:HTTP 调用本身。浏览器可以作为测试执行者参与(例如Selenium
  • 断言目标:测试输出是完整呈现的响应(HTML 和其他工件,如 javascript)。也可以包括数据库上的断言(例如插入的数据)。

双重测试的陷阱(集成 + 验收)

当同时包含这两种测试样式时,我发现了主要问题:

  • 控制器测试接近一般系统行为(例如提交登录表单、密码验证、成功登录)。这与验收测试所做的非常接近。最终可能会发生“双重测试”,这是非常低效的。
  • 控制器是更多的白盒测试并且往往很脆弱,因为它们依赖于较低层的许多依赖项(与非常细粒度的单元测试不同)。由于这种设置维护控制器测试的工作量很大,整个应用程序作为黑盒启动的验收测试更简单,并且更接近生产。

以上两点使我得出结论,如果您的测试人员有良好的自动化策略,您应该跳过开发人员完成的集成测试。他们应该更多地关注单元测试。

你怎么看?你能解释一下你的测试策略吗?您是否有包括两种测试方式在内的好/坏经历?

感谢您阅读我的长问题;)

编辑:验收测试似乎更常见的术语是端到端,所以我改变了术语。

【问题讨论】:

  • “集成测试”一词可以涵盖多种不同类型的测试。这可能有助于澄清在这种情况下所说的“集成测试”是什么意思。
  • 嗯,虽然我在上面举了一个例子(webapp控制器测试)...
  • 在我的示例中,我的集成测试正在接触一个将参数传递给控制器​​的测试。下面的所有服务都没有被嘲笑或存根。

标签: unit-testing testing tdd integration-testing


【解决方案1】:

我们在我的工作中进行验收 TDD。

当我刚开始工作时,有人告诉我,只要工作能够及时且可预测地完成,我就可以实施任何我想要的政策。过去做过单元测试,我意识到我们经常遇到的问题之一是集成错误。有些可能需要很长时间才能修复,而且往往是一个惊喜。在扩展应用程序的功能时,我们会遇到我们引入的细微错误。

我决定通过更多地关注我们应该提供的最终结果功能来避免我过去遇到的那些问题。我们将编写测试来测试验收行为,不仅在单元级别,而且在整个系统级别。我想这样做是因为归根结底我并不关心设备是否正常工作,我关心的是整个系统是否正常工作。我们发现进行自动化验收测试有以下好处。

  • 我们从不回归最终用户功能,因为它已经过明确测试。
  • 重构更容易,因为我们不必更新一堆单元测试。我们只需要确保我们的验收测试仍然通过。
  • 隐含地涵盖了“单元”的集成。
  • 这些测试非常明确地定义了所需的最终用户功能。
  • 集成问题较早暴露,不足为奇。

这样做的一些权衡

  • 就模拟、存根、固定装置等的使用而言,测试可能更复杂。
  • 测试对于缩小哪个“单元”存在缺陷的用处不大。

我们还使我们的测试套件可通过持续集成服务器运行,该服务器为部署添加标签和包。它与大多数 CI 设置一样在每次提交时运行。

关于您的观点/疑虑:

设置:整个 webapp 是 自举(就像它会被看到 来自最终用户)。

我们倾向于做出的一种妥协是在相同的进程空间中运行测试,例如单元测试。我们的入口点是应用程序堆栈的顶部。我们不会费心尝试将应用程序作为服务器运行,因为这会增加复杂性并且不会增加太多覆盖范围。

测试条目:HTTP 调用本身。浏览器 可以作为测试执行者参与(例如 硒)

我们所有的自动化测试都是由模拟 HTTP GET、POST、PUT 或 DELETE 驱动的。不过,我们实际上并没有为此使用浏览器,以特定 HTTP 调用 get 映射的方式调用应用程序堆栈的顶部就可以了。

断言目标:测试输出是 完整呈现的响应(HTML 和 其他工件,如 javascript)。 数据库上的断言(例如数据得到 插入) 也可以包含在内。

我认为这是自动化验收测试真正大放异彩的地方。你断言的是你想要保证你正在实现的最终用户功能。

控制器测试接近一般 系统行为(例如提交登录 表单,密码验证,成功 登录)。这是非常接近的 端到端测试可以。到底 可能会发生“双重测试”,这 效率极低。

我们实际上做的单元测试很少,几乎完全依赖于我们的自动化验收测试。因此,我们没有太多的双重测试方式。

控制器是更多的白盒测试 并且往往很脆,因为它们 依赖于许多较低的依赖项 层(区别非常精细 粒度单元测试)。正因为如此 设置维护控制器 测试很费力,端到端测试 整个应用程序的启动位置 因为黑匣子比较琐碎并且有 更接近生产的优势。

它们可能有更多的依赖关系,但可以通过使用模拟和固定装置来减轻这些依赖关系。我们通常还使用 2 种执行模式来实现我们的测试。测试运行完全连接到网络、dbs 等的非托管模式。以及测试在模拟非托管资源的情况下运行的托管模式。尽管您的断言是正确的,即测试可以花费更多的精力来创建和维护。

【讨论】:

  • 单元测试应该通过。如果他们不这样做,那么你就没有在做 TDD。
  • @VJo:TDD 的唯一标准是您首先编写测试并实施以履行测试所体现的契约。您通常从小处着手,然后继续改进代码和测试。我们只是将它发展到完整的堆栈。另一种思考方式是,我们将整个堆栈视为我们的“单元”。
  • @dietbuddha 这是一种非常奇怪的单元测试方式。
  • @VJo:是的,显然我在滥用“单位”的概念:)。然而,我一直在乎最终的结果。而且我可以毫不含糊地说,根据我在 Web 应用程序开发方面的经验,验收 TDD 比单元测试 + 集成测试具有更好的投资回报率,特别是因为所概述的好处。
  • 谢谢。因此,您更进一步跳过单元测试并依赖自动化验收测试。有趣的是,这对你有用。我不会走那么远来避免单元测试,我发现它们对开发人员测试系统的较小部分非常有帮助,而且它们执行得更快。
【解决方案2】:

开发人员应对他更改/实现的部分进行集成测试。在集成测试中,我的意思是他们应该看看他们实现的功能是否真的按预期工作。如果你不这样做,你怎么知道你刚刚完成的工作真的有效?单元测试本身并不是最终目标——重要的是产品。

应该这样做是为了加快错误发现。毕竟,集成测试需要很长时间才能执行(至少在我的公司,因为复杂性,执行所有集成测试需要 1-2 天)。越早发现错误越晚。

【讨论】:

  • 谢谢。我知道集成测试需要更长的时间,应该提供反馈。我的问题是关于进行自动化端到端测试和集成测试的效率问题。
【解决方案3】:

通过集成测试(实际上是单元测试)来测试也由系统测试测试的行为,通过缩小缺陷的位置来帮助调试。如果您的系统有组件 A-B-C 并且未通过系统测试用例,但程序集 A-B 通过了类似的集成测试用例,则缺陷可能在组件 C

【讨论】:

    【解决方案4】:

    考虑到这篇文章是关于测试陷阱的,我想让您了解我最近出版的一本书,Common System and Software Testing Pitfalls,该书由 Addison Wesley 于上个月出版。它记录了 92 个测试陷阱,分为 14 个类别。每个陷阱都包括描述、潜在适用性、特征性症状、潜在负面后果、潜在原因以及避免陷阱并在您已经陷入困境时爬出的建议。在 Amazon.com 上查看:http://www.amazon.com/Common-System-Software-Testing-Pitfalls/dp/0133748553/ref=la_B001HQ006A_1_1?s=books&ie=UTF8&qid=1389613893&sr=1-1

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-09-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-01-05
      • 1970-01-01
      • 2010-11-26
      相关资源
      最近更新 更多