Cucumber 用黄瓜重复使用小黄瓜步骤

Cucumber 用黄瓜重复使用小黄瓜步骤,cucumber,cucumber-jvm,gherkin,Cucumber,Cucumber Jvm,Gherkin,据我了解,基于此,给定的步骤与应用程序交互以设置前提条件状态,当步骤与应用程序交互以尝试设置所需的测试新状态时,然后语句读取应用程序的状态而不修改它 当步骤作为给定的步骤用于后续状态时,重用是否是一个好主意 例如,在一个简单的购物车应用程序中,我可能会写: Given the user is interested in some item When the user adds the item to their cart Then the cart will include the item

据我了解,基于此,
给定的
步骤与应用程序交互以设置前提条件状态,
步骤与应用程序交互以尝试设置所需的测试新状态时,
然后
语句读取应用程序的状态而不修改它

步骤作为
给定的
步骤用于后续状态时,重用
是否是一个好主意

例如,在一个简单的购物车应用程序中,我可能会写:

Given the user is interested in some item
When the user adds the item to their cart
Then the cart will include the item

Given the user adds the item to their cart
When the user checks out
Then the user will see a summary of their purchase including the item

Given the user checks out
When the user cancels an item
Then the item should be canceled
And the user should be refunded

这里有一个类似的问题,但它似乎不同意,因为答案建议将步骤变得更不严格,而Bob叔叔暗示这些步骤应该足够严格,以便从中生成一个可理解的状态转换图。我完全接受删除所有用户界面行话的建议,只关注业务术语,但我在这里尝试过的逻辑连接业务术语和只通过“看不见”连接逻辑上不可连接的步骤之间似乎有区别粘贴代码。

所以这是一个有点奇怪的领域,因为这是一个你可以但你真的不应该做的事情。让我解释一下

正如你提到的:

给定的步骤与应用程序交互以设置前提条件状态

当步骤与应用程序交互以尝试设置所需的测试新状态时

让我们在看示例时记住这一点

当用户将商品添加到购物车时

这个步骤实际上相当不错,它缺少实现语言,并且描述了用户的行为。10/10

如果用户将商品添加到购物车中

这个步骤虽然在语法上起作用,但违反了我们设置的规则,即
给定的
步骤何时执行。当
用于交互时,我们已经建立了
,而
给定
用于先决条件。然而,给定的
描述的是正在采取的行动,而不是状态或先决条件。写这篇文章的更好方法可能是:

假设用户购物车中有商品

这是一个先决条件,而不是一个动作,因此它是正确的小黄瓜


所以现在您可能会想“但是代码重用呢!?!?!?”,这就是流和lib派上用场的地方。如果您发现自己经常重复使用代码,请将其移动到一个库中,您可以调用该库在stepdefs中引用该操作,这样您就可以将功能文件保存在适当的小黄瓜中,并在代码重复使用尽可能少的情况下保存stepdefs,并在被测试的应用程序中断言

Bob叔叔的有限状态机可以用小黄瓜来描述,如果你有足够的小黄瓜语句的话。不过,重要的是要记住,小黄瓜中的每个场景都从初始状态开始,而不是从功能文件中位于其上方的场景末尾的状态开始

换言之,每个场景都必须独立

测试步骤的潜在重复不如描述完整场景重要。一个原因是测试运行者可能会有选择地运行场景,如果没有执行前体场景,这将导致测试失败。其他测试运行者可能并行运行场景,如果允许这种依赖关系,这也会造成严重破坏

在几个场景中重复给定的步骤是完全可以接受的,也是常见的做法

您的示例更恰当地表述如下:

Given the user is interested in some item
When the user adds the item to their cart
Then the cart will include the item

Given the user has added an item to their cart
When the user checks out
Then the user will see a summary of their purchase including the item

Given the user purchases an item
When the user cancels the item
Then the item should be canceled

第三个给定语句可以在其定义中包含让用户将项目放入购物车并签出的步骤,尽管它也可以简单地从头创建发票。这就是小黄瓜的妙处:不管先决条件是如何实现的,验证的是行动是否会产生预期的结果。

我不认为你应该重复使用给定的步骤。相反,您应该在步骤与之交互的功能基础上创建Givens。通常,每个步骤都有可能在其功能的基础上构建多个给定步骤

在某些情况下,您将在每个步骤中执行完全相同的操作。例如登录

When "I login" do
  visit login_path
  fill_in id
  fill_in password
  ...
end

Given "I have logged in" do
  visit login_path
  fill_in
  ...
end
为了使这些步骤很好地工作,让我们引入一个helper方法

module LoginStepHelper
  def login(as: )
     visit ...
  end
end
World LoginStepHelper

When "I login" do
  login as: @i
end

Given "I have logged in" do
  login as: @i
end
现在,我们几乎不花任何代价就获得了一个给定的更好语法的好处,我们可以在此基础上进行其他有用的步骤

e、 g

在大多数情况下,你有机会为你的目标做一些不同的事情。假设我们想要注册一个用户。例如,我们将通过某种UI与表单交互。但是,对于给定的用户界面,我们可以绕过UI。在我们的实施过程中,我们将

When I register
  visit registration_path
  fill_in ...
  ...
  submit
end
而我们可以

Given I am registered
  register as: @i
end

module RegistrationStepHelper
  def register(as:)
    CreateRegistration.call( ...
  end
end
我们提供了几种创建注册的方法

  • 直接调用用于创建具有适当参数散列的注册的服务
  • 调用工厂/夹具创建者将注册记录直接写入数据库
  • 在这两种方法中,第一种方法优越得多


    现在,您的语法越来越好,运行时成本大大降低。当您想要进行涉及大量现有功能的复杂交互时,这一点尤为重要。例如,注册客户在电子商务网站上进行重新订购。

    如果您使用的是Javascript,我创建了一个名为“调用场景”的包,方法是:

    Given the scenario "@scenario_tag"
    

    或者创建小黄瓜变量

    Given the variable "$variable_name" is equal to
    """
    #JSON object
    """
    
    或者创建场景函数并通过执行以下操作调用它们

    Given the scenario "@$scenario_function_tag" where variable "$variable_name" is "value_to_replace"
    

    还有更多…

    关于语言的观点被很好地理解了。时态不正确,读起来不像过去时态的先决条件那么好。然而,我也关心我称之为“测试崩溃”的问题。在我的示例中,我希望cumber的天真实现实际执行“addanitem”三次,因为我在beha之间构建了依赖树
    Given the variable "$variable_name" is equal to
    """
    #JSON object
    """
    
    Given the scenario "@$scenario_function_tag" where variable "$variable_name" is "value_to_replace"