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

单元测试如何测试任何东西?

  •  -1
  • Kingamere  · 技术社区  · 6 年前

    我不明白我是如何用单元测试来测试任何东西的。

    假设我正在测试我的知识库类是否能够正确地从数据库中检索值。正确的方法是实际调用实际的数据库并检索和检查这些值。

    但是单元测试背后的思想是应该隔离地进行,并且连接到正在运行的数据库不是隔离的。所以通常的做法是 嘲弄 树桩 数据库。

    但是,为什么在一个带有硬编码数据和硬编码返回值的假数据库上进行测试甚至可以测试任何东西呢?这似乎是重复的,浪费时间。

    或者我不理解如何正确地进行单元测试?

    是否有一个甚至单元测试数据库调用?

    3 回复  |  直到 6 年前
        1
  •  2
  •   VoiceOfUnreason    6 年前

    我不明白我是如何用单元测试来测试任何东西的。

    简短回答:您正在测试逻辑,而忽略了 副作用 .

    你不是在测试 一切 但是你在测试什么。

    此外,如果你记住你不是 真的? 测试带有副作用的代码,然后您有动机安排代码,以便实际依赖副作用的部分很小。大数据块实际上并不关心数据的来源,对于那些容易测试的数据来说。

    所以“某物”可以是“大多数事物”。

    那里 一个阻抗问题——如果你的测试不充分地模仿原始产品,那么你的一些测试结果将是不准确的。

    我的理念是尽可能少地测试以达到给定的信心水平

    Kent Beck, 2008

    想象“尽可能少”的一种方法是从成本的角度来思考——我们的目标是一个给定的置信水平,因此我们希望尽可能多地利用廉价的单元测试来获得这种置信,然后用更昂贵的技术来弥补差异。

    科里·本菲尔德的演讲 Building Protocol Libraries the Right Way 描述了一个我们在这里讨论的分离的例子。如何解析HTTP消息的逻辑与读取字节的问题是分离的。如果你使复杂的部分容易测试,而难测试的部分太简单而不能失败,你成功的机会就相当大。

        2
  •  1
  •   bcarlso    6 年前

    我认为你的担心是正确的。对我来说,TDD更像是一种进化的设计实践,而不是单元测试实践,但我将把它留作另一个讨论。

    在您的示例中,我们真正测试的是您的单个类中包含的逻辑是合理的。通过截取来自数据库的数据,您就有了一个可控制的场景,您可以确保代码在该特定场景下正常工作。这使得确保所有数据场景的完整测试覆盖更容易。你说得对,这真的不是 测试 整个系统端到端,但重点是要降低总体测试维护成本,实现更快的反馈。

    我的方法是在单元测试级别模拟大多数合作者,然后在集成测试级别编写验收测试,这将使用实际数据验证您的系统。因为使用模拟数据的单元测试允许您测试各种数据场景,所以您只需要使用集成测试测试来测试其中的一些场景,以确信您的代码将按预期执行。

        3
  •  0
  •   Fabio    6 年前

    您可以根据实际的数据库单独测试代码。只需为每个测试创建新的数据库实例,或者逐个同步执行测试,并在下一个测试之前清理数据库。

    但是使用实际的数据库会使您的测试变慢,这会使您的工作变慢,因为您需要对正在做的事情进行快速反馈。

    不要测试每个类-测试主要特性逻辑,因为它可以使用许多不同的类和仅模拟/存根依赖项,这会使测试变慢。

    找到应用程序边界,在它们之间测试逻辑,而不进行模拟。
    例如,在普通的Web API中,应用程序边界可以是:
    -控制器操作-请求(输入)
    -控制器操作-响应(输出)
    -数据库->收到请求的副作用。

    假设我们生活在一个完美的世界中,新的数据库和Web服务器的安装需要几毫秒的时间。然后您将测试应用程序的整个管道:
    1。为测试配置数据库
    2。向Web API服务器发送请求
    三。断言响应包含预期数据
    4。断言数据库状态按预期更改

    但在当今世界,您的边界将是控制器操作和抽象的数据库访问点。这使您的测试看起来如下:
    1。配置模拟数据库访问点(存储库)
    2。使用给定参数调用控制器操作
    三。断言操作返回预期结果
    4。可能断言模拟存储库收到了预期的更新参数。

    如果您的应用程序没有逻辑,只需从数据库读取/更新数据—使用实际的数据库进行测试,或者,如果您的数据库框架允许,使用内存中的数据库。