【问题标题】:Why is cucumber considered an integration testing tool instead of a unit testing tool?为什么黄瓜被认为是集成测试工具而不是单元测试工具?
【发布时间】:2010-11-17 05:40:50
【问题描述】:

这一直困扰着我。为什么人们说在 rspec 中进行单元测试而在 cucumber 中进行集成测试?我不是在问为什么这些测试是必要的——我知道集成和单元测试之间的区别。我只是不明白为什么 cucumber 完全可定制的语法不用于单元测试?

在我看来,为 cucumber 和 rspec 编写了相同数量的代码,唯一的区别是对于 cucumber,您将测试逻辑与测试编写分开。

【问题讨论】:

  • JBehave 1.0 最先出现 - 最初为类示例/测试和场景提供单独的机制。这是 JUnit 3.8 的时代 - JUnit 4.4 使类示例变得不必要。 Dan North(BDD 和 JBehave 创始人)开发了 RBehave,然后 RSpec 团队将其集成,然后 David Chelimsky 使用纯文本并将其拆分回一个单独的库中——我认为 Aslak Hellesoy 领导了这个。然后我们基于 Cucumber 重写了 JBehave 2.0。对于历史兴趣:blog.davidchelimsky.net/2007/10/25/plain-text-stories-part-iii
  • 哦,Cucumber 写起来有点慢。请参阅我的回答,了解框架解决的原因和问题。

标签: ruby unit-testing cucumber


【解决方案1】:

使用 cucumber 进行单元测试有很多开销。您不仅要编写功能,还要使用单独的代码将它们映射到实现。

单元测试旨在快速编写和执行。自然,cucumber 侧重于最终用户体验,这主要是由于编写功能时使用的语言。

只是为了刷新,功能将包含以下内容:

作为系统的一些利益相关者
我想进行一项活动
这样我就可以从中得到一些好处

Given a precondition
When I perform an action
Then something should happen

通常被忽略的开头段落非常重要,因为它为操作设置了上下文并解释了为什么会发生某些事情。由于使用了自然语言,这些东西很容易展示给非程序员以获得一些反馈。

现在,将这些用于单元测试似乎很尴尬。首先,最终用户的关注点提出了一种更加集成的方法,因为该功能没有提及模拟和 UI/逻辑分离。 IE。像下面这样的功能看起来很奇怪:

Given a that a database mock is configured with the following data
| ID  | Username |
| 0   | igor     |
When call FindAll on User Repository
Then I get the following user back
| ID  | Username |
| 0   | igor     |

此外,随着您的 SUT 变小(即类),操作的上下文不再那么重要。用户存储库不关心上下文,例如它不关心它的消费者是普通用户还是VIP用户。一个简单的组件(它应该是,遵循 SRP),是完全基于其输入的确定性的。

因此,单元测试用于验证您编写的内容是否正确,而黄瓜测试用于通过将系统的行为置于上下文中来验证您编写的内容是否满足更高的目的。

【讨论】:

  • 如何通过编写步骤定义重用测试代码?没关系吗?
  • 我可以想象这样的事情:Feature users are persisted by the user repository Scenario finding users with the repository Given that the storage contains only user igor When I ask the repository to find all users Then I get only user igor back - 这更抽象,但很难将这些术语映射到 UserRepository.FindAll 和 MockDatabase
【解决方案2】:

Cucumber 解决了一组特定的问题 - 让无法轻松阅读代码并且肯定不会编写代码的业务利益相关者参与进来,并在自动化场景中的步骤之间提供重用。这些场景通常还涵盖不止一个方面的行为,记录整个系统的功能,并且通常涵盖跨多个组件的整个用户旅程。 Cucumber 提倡的基于步骤的架构非常适合处理这些场景。

它还引入了一整套其他问题。首先,您需要将 Cucumber 场景绑定到一组固定装置,因此还有另一层抽象,这使得它们编写起来更慢。其次,英语比代码更难重构——即使是像 Ruby 这样的动态语言(在 C# 和 Java 变体中,如 JBehave、SpecFlow、Cuke4Nuke 和 Cuke4Duke 的差异仍然更加明显)。很难判断步骤是否仍在使用,也更难维护场景。管理各个步骤之间的状态也更加困难。

对于单元测试,受众是技术人员。理想情况下,类具有单一职责,几乎没有重复,因此步骤的重用并不重要。当我们想要更改代码元素时,我们倾向于寻找命名约定与文件或类匹配的测试,因此与它们进行一对一映射是理想的。

由于 Cucumber 的间接费用,并且由于我们没有从 Cucumber 提供的收益作为其间接费用的回报中获得价值,因此 RSpec 更适合单位级别的行为。 (JUnit、NUnit 等也是如此)

如果您缺少 Cucumber 的“Given, When, Then”,请尝试将它们添加为 cmets。这对我很有效。

【讨论】:

    【解决方案3】:

    总体思路是,Cucumber 测试的编写水平高于传统的单元测试。例如,当您对特定模块进行单元测试时,您只专注于测试与系统其余部分隔离的模块功能。到系统其他部分的接口通常应该用模拟对象来表示。

    另一方面,Cucumber 专注于从 UI 一直到数据持久层的系统测试。

    单元测试 = 机械工程师在安装在安全带上的实验室环境中测试他的新引擎。

    黄瓜测试 = 测试车手将它放在赛道上旋转。

    【讨论】:

    • 但这就是问题所在。你说的没有什么是 rspec 特有的,也没有什么是 cucumber 做不到的。在这些场景之下,cucumber 只是普通的 ruby​​ 代码,它可以包括模拟和类级别的测试。那为什么不呢?
    • 当然,你是对的,它只是下面的代码。只要有代码,只要有足够的持久性,就有可能做任何你想做的事情。但是,这种测试模型不是 Cucumber 的意图,如果您要开始模拟对象,它将违背全栈系统测试的目的。听起来你想用螺丝刀钉钉子。
    • 你还是不够具体。为什么 exactly rspec 更适合这个?仅仅因为我正在做两种不同风格的测试并不意味着我必须使用两种不同的框架。有很多解耦的模拟框架可以在 Cucumber 中轻松使用。使用 rspec 和 cucumber 都可以编写描述性的测试名称,那么它有什么不同呢?归根结底,不同之处在于黄瓜的场景在一个单独的文件中。不要只是说“没有什么能阻止你”。我知道。我只是想知道为什么每个人都认为它是错误的。
    【解决方案4】:

    单元测试用于单独测试特定的单元代码。通常的粒度是类中的一个方法(或几个交互方法)。

    集成测试的重点是测试应用程序堆栈的许多层。例如,您可以运行一个集成测试来检查您的代码与数据库的交互。大多数集成测试侧重于两层或三层对象。

    Cucumber 测试尤其倾向于关注完整的应用程序堆栈,因为它们通过在界面和应用程序的所有层(从 UI 到后端服务(数据库、文件系统、网络等)已到位并已使用。

    底线:

    单元测试检查特定代码是否遵守其与世界其他地方的合同...

    而黄瓜测试检查几段代码的交互(有些人可能会说是垂直切片),而测试本身读起来就像简单的英语一样具有额外的美感。

    【讨论】:

      【解决方案5】:

      根据 Aslak Hellesøy 的说法,Cucumber 不是一个测试工具,而是一个协作工具(用于 BDD)。他最近发布了这个明显的误解:

      https://cucumber.pro/blog/2014/03/03/the-worlds-most-misunderstood-collaboration-tool.html

      也就是说,有很多低于接受水平的测试会落在集成测试层周围。即,

      Given a user at 123 Evergreen Terrace
      When I lookup their name
      Then I get Homer Simpson
      

      而不是

      Given an address
      When I lookup a name
      Then the home owner name is displayed
      

      cukes.info 显示为命令式示例(而不是声明式)并没有帮助。

      与 Rspec 或 Test::Unit 或 MiniTest 单元测试相比,Cucumber 测试运行缓慢。它们有很多开销(加载环境可能需要几分钟,包括所有页面对象类、解析功能文件和实际执行测试)。只运行 Cucumber 单元测试会比运行集成等效测试更快,但不如运行更轻量级的东西(例如上面提到的三个)。

      (我正在回答这个老问题,因为它是我在寻找 Cucumber 的替代品进行集成测试时得到的第一个命中)

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-07-22
        • 1970-01-01
        • 2010-12-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多