代码之家  ›  专栏  ›  技术社区  ›  CodeGrue

如果我可以只使用集成测试,为什么我要费心进行单元测试呢?

  •  26
  • CodeGrue  · 技术社区  · 15 年前

    好吧,我知道我要冒险发表这样的声明,所以我的问题是让每个人都相信我是错的。以这种情况为例:

    我有方法A,它调用方法B,它们在不同的层中。

    所以我对B进行单元测试,结果是它提供了空值。所以我测试返回空值,并且单元测试通过。很好。

    然后我对测试A进行单元测试,它期望从B返回一个空字符串。所以我模拟了层B在其中,返回一个空字符串,测试通过。又好了。(假设我没有意识到A和B的关系,或者可能是两个不同的人在构建这些方法)

    我担心的是,直到我们一起测试A和B,即集成测试,我们才发现真正的问题。因为集成测试提供了对单元测试区域的覆盖,所以构建所有这些真正不告诉我们任何(或非常多)有意义的单元测试似乎是一种浪费。

    为什么我错了?

    12 回复  |  直到 13 年前
        1
  •  21
  •   Samuel Carrijo    15 年前

    这里是 an article on test categorization 带着一些论点

    一旦我们将单元测试与功能测试进行比较,我就不会提到整体测试的好处:

    • 单元测试有助于减少出错时要查看的范围。 -让我们在这个场景中包括类C、D、E、…、Z。 如果您只有集成测试,但它失败了,那么您从哪里开始寻找呢? 如果你没有单元测试, 您需要查看每个类的内部以及这些类之间的“连接”。 (范围更窄)。如果您进行了单元测试,那么您只需要检查接线。在这种情况下,没有一些较小的集成测试也是一件糟糕的事情,比如只测试A、B、C和D(所以您已经知道这些测试之间的“连接”是否有效)。
    • 通过单元测试,你的失败速度更快。 . 如果你是TDD的话,这就更真实了。您可能在创建完所有的A和B类之后编写测试。当您运行测试时,A和B的工作方式在您的头脑中并不是那么新鲜(也许您在前一周编写了测试——希望您不会只在产品“完成”时才开始测试)。然后你必须记住你写这些东西时的想法。此外,单元测试速度更快,因此您更有可能更频繁地运行它们(可能每次保存时都自动运行它们?)
    • 单元测试提供了一个更好的文档,说明类应该如何工作。 . 如果你是一个“普通的程序员”,你可能讨厌写文档。这迫使您在编程时编写文档,以及 强制文档永不过时 (如果是,则测试失败)。和 当您需要更改其他人的代码时,它也会有所帮助

    理想的 世界上,当测试失败时,您不需要超过2分钟的时间来了解要查看的内容(不需要调试)。拥有所有大小的测试的想法只是实现这个目标的一个指导方针,而不是花费数小时/数天/数周的调试时间。

        2
  •  9
  •   Otávio Décio    15 年前

    单元测试不是为了测试应该在集成中测试的内容——它们是互补的测试集。单元测试保证 单元 代码本身执行它的设计任务,而不是其他任务。集成测试确保 单位 通力合作,完成总体要求。

        3
  •  5
  •   ryeguy    15 年前

    单元测试的粒度更细,允许您精确定位错误。如果A或B失败怎么办?如果集成测试失败,您如何知道哪个失败?这仅仅是两种方法——想象一下,如果您正在集成测试一个Web应用程序的前控制器,它加载一些模型并调用一组方法。这将是一个噩梦,试图追查到底出了什么问题。

        4
  •  5
  •   Mark Bessey    15 年前

    我认为主要原因是:

    1:单元级测试为您提供了有关失败内容的更多信息。

    2:在集成组件之前,不能运行集成测试。你越早发现一个bug,修复它就越容易/越便宜。

        5
  •  4
  •   yamspog    15 年前

    我同意你的观点,在简单的情况下,不需要单元测试。测试(单元测试、集成测试、功能测试、回归测试)都取决于项目的规模、参与人员的数量以及每个参与人员的经验水平。

    随着这些因素中的任何一个的增加(好吧,最后一个必须减少),测试的需求就增加了。您需要找到一个适合并适用于特定项目的解决方案。

    我非常喜欢单元测试,相信所有开发人员都应该编写和自动化它们,不管项目的大小。它们将确保您的代码是无缺陷的,并且在您几个月后返回项目时,它们将真正起到帮助作用。

    我还认为,由于在一段较长的时间内有多个人在项目上工作(阅读除废弃项目以外的任何内容),因此您还需要自动集成测试,以确保各个组件协同工作。

        6
  •  4
  •   HLGEM    15 年前

    好吧,单元测试不会发现所有的问题,这就是为什么我们也有集成测试的原因!

    但是假设您有一个方法,它必须返回1到9之间的值,然后您为它编写一个测试,并发现它返回的值为空或10,那么在进行集成测试之前,您就知道代码早就被破坏了。

        7
  •  3
  •   Jim Kiley    15 年前

    单元测试不是在初始开发期间进行调试。它们是关于设计的,它们是关于适应变化的。当我第一次通过一大块代码时,我的单元测试几乎从不告诉我bug在哪里。当六个月后出现一个bug时,我的测试会警告我,因为有人(可能是我自己)修改了一个他们不完全理解其关系的对象。

    说单元测试在最初的开发过程中是浪费时间的,就像抱怨我的车在驶出我的车道时跑得很糟糕。

        8
  •  3
  •   Michael Borgwardt    15 年前

    集成测试的一种形式是 combinatorial explosion :假设方法A有5种不同的行为方式(不同的边缘情况等),方法B也有。如果您一起测试,理论上现在有25种不同的情况需要测试!是的,它们中的许多可能最终是相同的,或者由于一个或另一个原因而不能发生,但是基本上,你一起测试的东西越多,就越不可能测试所有的边缘情况。

        9
  •  2
  •   elduff    15 年前

    另一个我没看到其他地址的原因是: 您并不总是维护您编写的代码的人。 假设我已经在单独的模块中编写了A&B,这样每个模块都在单独的JAR中,并且有自己的maven构建文件。让我们进一步假设A是DAO方法,B是某种服务层。如果我为DAO编写了一个基本的单元测试(甚至可能使用测试驱动开发!),我更相信将来对数据库结构和查询所做的可能影响我的DAO的更改会很早被捕获。例如,如果在我的团队中,另一个开发人员需要将列添加到我的DAO使用的数据库表中,我当然希望他们马上知道这样做是否会破坏我的DAO方法。如果他们必须等待构建所有层并运行一个集成测试来验证这一点,我认为他们只是在浪费宝贵的开发时间。作为一个开发人员,我宁愿运行10秒的单元测试10次来修复和测试我发现的任何中断,也不愿多次运行2分钟的集成构建和集成测试。显然,时间会根据项目的大小(以及您的硬件)而变化很大,但这些是我在当前项目中处理的时间类型。

        10
  •  2
  •   phlip    15 年前

    加强(希望)塞缪尔卡里约的职位…


    在以下两者之间选择时: 1)单元测试和小型集成测试 VS 2)只是集成测试 你在下一个有计算的赌注。如果集成组件很复杂,那么在没有单元测试的情况下,很难找到集成测试中的任何失败。有时我会出错,在集成测试中测试失败,然后开始编写单元测试而不尝试调试。 如果你打赌不需要单元测试就赢了,你可以节省你自己相当多的时间,并且仍然对你的代码有信心,但是你没有得到单元测试为下一个接触到你的代码的人提供的“规范”好处。

        11
  •  1
  •   Jerry Coffin    15 年前

    大多数问题都是在你提出的场景中——根据你的描述, 全部的 b dos返回空值。单元测试一些琐碎的东西可能是没有意义的——但它正在编写代码以开始。如果您只需要一个空值,直接使用空值并完全消除b。如果B通过实际做一些不返回空值的事情来证明它的存在,那么您描述的单元测试是不完整的,您需要测试其他B应该做的事情。

        12
  •  0
  •   brydgesk    15 年前

    如果A是一个运行2小时的查询,并为B准备数据,这是另一个运行2小时的查询,为什么我要等4小时才能找到一个问题,而我要等2小时呢?这不是一个新想法。你认为汽车公司在看发动机是否工作之前就组装了整个汽车吗?