是的,当实际场景需要时,在 Gherkin 场景中可以使用多个 When/Then 循环。
SaxonMatt's answer 提出了一个很好的观点,即最好用利益相关者的语言而不是 UI 操作语言编写场景,这样做通常会缩短场景的长度,但这会错过问题的确切要点。让我们抓住公牛的角。
Gherkin 专为验收测试而设计:测试利益相关者级别的要求是否已完全实现,即软件是否确实为利益相关者提供了价值。有时提供价值需要不止一个行动-响应周期。考虑以下场景:
Scenario: Guest buys a product
# This scenario starts with the user not logged in, which doesn't require a step
Given there is a product named "Elliptical Juicer"
When I go to the product page for "Elliptical Juicer"
And I add the product to my shopping cart
Then I should see 1 product in my shopping cart
When I request to check out
Then I should see the account creation form
When I create an account
Then I should see the checkout form with 1 product, "Elliptical Juicer"
When I check out
Then I should see the checkout success page with 1 product, "Elliptical Juicer"
And I should receive a checkout confirmation email with 1 product, "Elliptical Juicer"
(请注意,当我在一个场景中有多个When/Then 循环时,我喜欢用空行分隔它们,以便它们突出。)
这个场景最好用多个When/Then循环来编写有几个原因:
-
在用户结帐之前,他们应该会在他们的购物车中看到一件产品(仅作为网站标题中的一个数字,因此该步骤不会提及产品名称)。在场景结束时无法测试此要求。 (好吧,测试可以在用户将产品添加到他们的购物车后立即收集信息,并在场景结束时断言预期的计数,但这将毫无意义地偷偷摸摸和混淆。)相反,在自然状态下断言正确的计数放置在场景中,只要它对用户可见。
同样,Then I should see the account creation form 和 Then I should see the checkout form with 1 product, "Elliptical Juicer" 可以在场景中很自然地对其进行测试的点上测试重要需求。
-
假设我们不关心用户在这个过程中看到了什么,只关心他们是否带着他们的产品到达场景的结尾。然后我们可能会省略中间的Then 步骤:
Given there is a product named "Elliptical Juicer"
When I go to the product page for "Elliptical Juicer"
And I add the product to my shopping cart
And I request to check out
And I create an account
And I check out
Then I should see the checkout success page with 1 product, "Elliptical Juicer"
And I should receive a checkout confirmation email with 1 product, "Elliptical Juicer"
And I create an account 令人惊讶,不是吗?它要求读者推断访客用户在结账时被要求创建一个帐户。像我给出的场景的第一个版本一样,明确地说出来会更清楚。
-
假设上述担忧都不能说服我们,并且我们为需要断言满足要求的整体场景中的每个点编写了单独的 Gherkin 场景:
Scenario: Guest adds a product to their shopping cart
Given there is a product named "Elliptical Juicer"
When I go to the product page for "Elliptical Juicer"
And I add the product to my shopping cart
Then I should see 1 product in my shopping cart
Scenario: Guest with a product in their shopping cart attempts to check out
Given I have a product in my shopping cart
When I request to check out
Then I should see the account creation form
Scenario: Guest creates an account
Given I have a product named "Elliptical Juicer" in my shopping cart
And I am on the account creation form
When I create an account
Then I should see the checkout form with 1 product, "Elliptical Juicer"
Scenario: Newly registered user checks out
Given I am a user
And I have a product named "Elliptical Juicer" in my shopping cart
And I am on the checkout form
When I check out
Then I should see the checkout success page with 1 product, "Elliptical Juicer"
And I should receive a checkout confirmation email with 1 product, "Elliptical Juicer"
太可怕了!首先,没有一个场景是利益相关者认为的场景。其次,当中间状态之一改变时,两个步骤将不得不改变:断言中间状态的步骤和为下一个场景设置中间状态的Given 步骤。每个Given 步骤都是设置错误状态的机会,即产生集成错误。这组场景作为集成测试套件的价值远低于单一场景。您可能几乎已经编写了一系列单元测试。
确实,端到端编写每个场景可能会导致一些重复。正如您在单元测试中比在常规代码中更能容忍重复一样,在 Gherkin 场景中比在单元测试中更能容忍重复。不要在可理解性上妥协。分解场景并仅在关键点使用Givens(例如在上面的示例中创建产品),并且这样做知道您正在削弱场景的集成测试能力。
另外,请记住,验收测试应该只是自动化测试套件的一部分。只编写足够的验收测试来覆盖关键场景,并用单元测试覆盖细节。通常情况下,验收测试重复的解决方案是用单元测试替换一个。