自动化的单元测试,集成测试或验收测试


29

目前,TDD和单元测试似乎很受欢迎。但是,与其他形式的自动化测试相比,它真的有用吗?

凭直觉,我猜想自动化集成测试比单元测试有用。以我的经验,大多数错误似乎都在于模块之间的交互,而不是每个单元的实际(通常是有限的)逻辑。此外,由于模块之间的接口发生更改(以及更改的前后条件),经常发生回归。

我是在误解什么,还是与集成测试相比,单元测试为什么会引起更多关注?仅仅是因为假设您已经拥有集成测试,而单元测试又是我们需要学习以开发人员身份应用的下一件事?

还是与自动化的复杂性相比,单元测试仅能带来最高的收益?

您在自动化的单元测试,自动化的集成测试和自动化的验收测试中有什么经验,而在您的经验中,哪些产生了最高的投资回报率?为什么?

如果您只需要选择一种测试形式就可以在下一个项目中实现自动化,那会是什么?

提前致谢。


我只想向JB Rainsberger的“ 集成测试是骗局”添加一个迟来的链接。它强调了集成测试是虚假经济的许多原因。
蒂姆(Tim)


6
这是关闭三年前在此站点上完全正常的问题的另一个示例!为一个规则不断变化的社区做贡献真是烦人,而您只是扔掉所有旧的东西!
Bjarke Freund-Hansen

Answers:


34

使单元测试变得极为有用的一个重要因素是快速反馈

考虑一下当您的应用程序完全被集成/系统/功能测试所覆盖时会发生什么(这已经是理想的情况了,在大多数开发商店中还远远没有实现)。这些通常由专门的测试团队来管理。

  • 您对SCM存储库进行了更改,
  • 某个时候(可能几天后),测试人员会获得一个新的内部版本并开始对其进行测试,
  • 他们找到错误并提交错误报告,
  • (在理想情况下)有人将错误报告分配给您。

这可能需要几天甚至几周的时间。到这时,您已经在从事其他任务,因此您不会早先想到代码的详细信息。而且,您通常甚至没有任何直接证据来证明错误的实际位置,因此查找和修复错误需要花费大量时间。

而在单元测试(TDD)中

  • 你写一个测试,
  • 您编写一些代码来满足测试要求,
  • 测试仍然失败,
  • 您看一下代码,通常会在几秒钟内有“糟糕”的体验(例如“糟糕,我忘记检查这种情况!”),然后
  • 立即修复错误。

这一切都在几分钟之内完成

这并不是说集成/系统测试没有用。它们只是出于不同的目的。借助编写良好的单元测试,您可以在代码进入集成阶段之前发现其中的大部分错误,该阶段发现和修复它们的成本已经非常高。正确的是,需要集成测试来捕获单元测试难以或不可能捕获的那些类型的错误。但是,以我的经验,那是比较罕见的一种。我见过的大多数错误都是由方法内部某些简单甚至琐碎的遗漏引起的。

更不用说单元测试还会测试您的接口的可用性/安全性等,从而为您提供至关重要的反馈,以改善您的设计和API。哪种IMHO可以大大减少模块/主机系统集成错误的可能性:API越容易清洁,误解或遗漏的机会就越少。

您在自动化的单元测试,自动化的集成测试和自动化的验收测试中有什么经验,而在您的经验中,哪些产生了最高的投资回报率?为什么?

投资回报率取决于许多因素,其中最重要的因素可能是您的项目是未开发的项目还是旧项目。对于未开发的项目,我的建议(到目前为止的经验)是从一开始就进行TDD样式的单元测试。我相信这是这种情况下最具成本效益的方法。

但是,在旧项目中,建立足够的单元测试覆盖范围是一项艰巨的任务,而获得收益的过程将非常缓慢。如果可能的话,尝试通过UI进行系统/功能测试来涵盖最重要的功能更为有效。(尽管自动化测试支持工具正在逐步完善,但桌面GUI应用程序可能难以通过GUI进行自动测试...)。这样可以快速为您提供一个粗略但有效的安全网。然后,您可以开始围绕应用程序的最关键部分逐步建立单元测试。

如果您只需要在下一个项目中选择一种测试形式进行自动化,那会是什么?

这是一个理论问题,我认为毫无意义。各种测试都可以在高级软件工程师的工具箱中使用,并且所有这些测试都具有无法替代的场景。


2
+1用于单元测试的“快速反馈”。另外,在持续集成服务器上作为提交后运行非常方便。
Frank Shearar 2011年

1
“各种测试都可以在高级软件工程师的工具箱中使用,并且所有这些测试都有不可替代的场景。” -我希望我可以为此投票几次!认为自己只能找到一种理想的测试工具/方法并将其应用到任何地方的人们使我感到沮丧。
ptyx 2012年

8

所有类型的测试都非常重要,并确保系统的各个方面都符合规范。因此,倒退,“如果我必须选择一种测试类型……”,我不会。单元测试为我提供的反馈不同于集成测试或人工交互测试。

这是我们进行测试的类型/优势:

  • 单元测试-确保单元按照我们的期望进行工作。我们对每个接口都同时测试了提供商合同和消费者合同-这相当容易实现自动化。我们还会检查边界条件等。
  • 集成测试-确保各个单元协同工作。这主要是为了测试我们的设计。如果这里出现问题,我们必须调整单元测试以确保不会再次发生。
  • 系统测试-确保系统符合要求/规格。通常人们会进行这种类型的测试。
  • 验收测试-客户这样做是为了验证最终产品是否符合广告要求。

可选但推荐的测试:

  • 用户体验测试:尽管我们从系统测试中获得了不错的反馈,但是让客户端中的人员预览某些预发布版本确实可以帮助我们确定是否需要为时已晚进行更改。

仅为了了解为什么单元测试比集成测试具有优势,您必须了解需要进行全面测试的数量级附加测试。对于单元A的每种可能结果,都需要进行测试。B单元也是如此。现在,如果两者一起工作以提供更完整的解决方案,则测试的数量是组合的。简而言之,要测试单元A和单元B之间相互作用的每个排列,都需要A * B测试。加C单元,三项测试的次数为A * B * C。

在这里,接口和对象边界的概念变得非常重要。接口代表一定的契约。接口的实现者同意它将以某种方式运行。同样,接口的使用者也同意它将以某种方式使用实现。通过编写收集每个实现接口的类的测试,您可以轻松测试每个实现是否遵守接口协定。那是等式的一半。另一半是测试用户端-这是模拟对象发挥作用的地方。模拟被配置为确保交互始终符合规范。此时,所需要做的就是一些集成测试,以确保我们正确地实现了实施者/消费者合同。


“系统测试-确保系统符合要求/规格通常是人们进行此类测试”。系统/ aka功能/ aka“端到端” / aka高级集成测试也很适合自动化。
MiFreidgeim如此制止邪恶,2013年

3

这些是具有不同目标的不同工具:

  • 单元测试是一种设计工具(TDD),几乎是重构的前提。

  • 集成测试对于可视化项目进度非常有用,也可以避免回归错误。

要记住的一点是,您不能真正使用集成测试进行设计,也无法使用单元测试找到回归。


@您不能真正使用集成测试进行设计,也不会使用单元测试找到回归。究竟!
2011年

单元测试可以发现由于重构(例如更改的共享帮助程序方法)导致的回归。集成测试对此要好得多。
StuperUser 2011年

关于集成测试的第二点包括“系统/功能”(也称为“端到端”)测试
MiFreidgeim SO停止变得邪恶

完全同意;几年前,史蒂夫·桑德森(Steve Sanderson)也提出了类似的观点。请参阅他2009年博客文章中的“目标-最强技术”表,网址blog.stevensanderson.com/2009/08/24/…,这里有些与您自己的想法互补的想法。
马克·菲茨杰拉德

1

我已经广泛使用Selenium进行健全性检查。

在一家大型网络发布公司中,发布新版本时,通常需要大约3个测试人员大约一两个小时才能访问所有网站系列,并确保每个测试脚本都正常。使用Selenium,我们能够自动化测试,并将其分发到多台机器和浏览器上。当前,运行测试脚本时,需要3台PC大约10分钟才能自动执行相同的操作并发出漂亮的报告。

硒的优点在于您可以将其与XUnit,TestNG或MSTest等单元测试框架绑定在一起。

以我的经验,它非常有价值,但是类似的设置实际上取决于您的项目和团队,因此ROI肯定会有所不同。


1

最好的投资回报率通常是最早的测试,可以发现这种类型的错误。

单元测试应该发现大多数错误只是一种方法或一个组件。它查找通常可以在几分钟内解决的错误,总周转时间不到一小时。非常便宜的测试,非常便宜的bug可以查找和修复!如果这些错误将其纳入集成测试,则假设该错误不会被其他错误所遮盖,则转换时间可能更像一天(测试运行通常在夜间进行)。另外,由于其他代码是针对最初的错误代码编写的,因此可能还会引入更多错误;加上任何重新设计都会影响更多的代码段。另外,通过更多的错误意味着必须完成更多的测试运行才能完成集成测试。不良的单元测试通常是长期,繁重且昂贵的核心测试集成周期。跳过单元测试可能会使开发时间减少一半,但是测试至少需要三到四倍的时间,整个项目的长度将增加一倍,并且与单元测试IME相比,您的质量仍然较低。

集成测试通常是最早的可以发现集成错误的实际测试(尽管检查过程可以在编写软件之前或在代码进行测试之前找到一些错误)。您希望在开始向用户展示或发布软件之前找到这些错误,因为在最后一刻修正错误(或热修复!)非常昂贵。您很难找到这些bug,因为这些bug的修复成本较低,因为您需要集成多个工作组件(根据定义)。当与交互部分无关的错误(例如小错别字)需要首先解决,而更有趣的测试甚至可以开始之前,集成测试就会变慢。

用户验收测试可确保软件能够满足客户的需求(尽管希望客户一直参与其中,以降低在项目结束时发现期望值与实际软件之间存在巨大差距的风险-非常昂贵!)。到进行此测试阶段时,您应该真正相信与至少相比于规范而言,产品中的大多数bug已经被发现。用户验收测试更多的是确保产品符合客户的需求,而不是确保与规范相比没有错误。

如果我只打算自动化一种类型的测试,那将是单元测试。集成测试可以手动完成,并且许多大型公司已经这样做了多年。一遍又一遍地手动完成计算机可以完成的工作,这将耗费更多时间,而且对于大多数项目而言,这更昂贵,更不用说无聊且容易出错了,但是可以做到。用户验收测试通常是手动的,因为用户经常不知道如何自动化测试,而仍然在测试他们关心的东西。单元测试必须是自动化的。您需要能够按需在几秒钟之内每隔几分钟就运行一次所有的单元测试。人类甚至无法接近手动测试。更不用说单元测试在代码中,并且不通过代码调用即自动执行就无法执行。

要记住的一件事是,这是一个主要面向开发人员而非测试人员的论坛。集成测试主要由测试人员实施。单元测试由开发人员实施。自然,与其他类型的测试相比,开发人员对单元测试的讨论更多。这并不意味着他们认为其他测试不重要。这只是意味着他们实际上并没有这样做(或减少了这样做的频率)。


特别感谢最后一段,我没有想到这一点。
Bjarke Freund-Hansen

仅供参考,我更新了答案,因为你读它-意识到我没有看过原著的问题不够紧密
埃塞尔·埃文斯

@EthelEvans,关于单元测试优先级的原因对于新项目是正确的。对于遗留项目,在编写这些代码时并没有考虑到自动化的测试范围,系统/ aka功能/ aka高级集成测试是最重要的。见的最后一部分programmers.stackexchange.com/a/39370/31574答案。
MiFreidgeim SO停止变得邪恶

@MichaelFreidgeim,它最终取决于接口的稳定性。如果自动化的高水平测试过时很快,则很快会招致高昂的维护成本。在这种情况下,请降低自动化级别以帮助建立稳定性,并针对E2E和集成测试使用探索性测试(可能基于会话或清单),以避免产生令人讨厌的自动化维护成本。但是,并非所有旧项目都具有稳定的接口-尤其是在对其进行积极重构或重构时。
Ethel Evans

1

我觉得在这种情况下验收测试是最重要的。

如果提交违反了验收测试,则需要对其进行整理。

验收测试告诉您软件在哪里,而单元测试则不在。

因此,单元测试会提供非常错误的安全感。


0

问题不是什么更重要,而是什么可以自动化并快速运行。

单元测试表明小型组件是否适合特定用途,并且通常很小且可以快速运行。体积小,它们通常很容易实现自动化。

集成测试表明组件是否可以协同工作。它们通常更大,并且可能不容易自动化。他们可能需要更长的时间才能运行。能够自动运行它们是有价值的,但是这是一个更大的任务,而且它们也不会经常运行。

验收测试表明项目是否可以接受。这通常是不可能完全自动化的(尽管自动化测试可能会起作用),因为通常不可能在形式上比源代码本身复杂得多的条件下确定确切和完整的要求。验收测试通常包括潜在用户使用该系统并观察到各个方面的结果令人满意,这通常是部分主观的。由于验收测试通常只运行一次(不同的客户通常会希望做他们自己的单独验收测试),因此实际上不值得自动化。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.