本地化
Gherkin 已针对多种 口语 进行本地化;每种语言都有其自己的本地化关键字等效项。
Gherkin 使用一组特殊的 关键字 来为可执行规范提供结构和含义。每个关键字都被翻译成多种口语;在本参考中,我们将使用英语。
Gherkin 文档中的大多数行都以一个 关键字 开头。
注释只能放在新行的开头,特征文件中的任何位置。它们以零个或多个空格开头,后面跟着一个井号 (#
) 和一些文本。
Gherkin 目前不支持块注释。
可以使用空格或制表符进行缩进。建议的缩进级别为两个空格。以下是一个示例
Feature: Guess the word
# The first example has two steps
Scenario: Maker starts a game
When the Maker starts a game
Then the Maker waits for a Breaker to join
# The second example has three steps
Scenario: Breaker joins a game
Given the Maker has started a game with the word "silky"
When the Breaker joins the Maker's game
Then the Breaker must guess a word with 5 characters
每个步骤的尾部(关键字之后的部分)与一个称为 步骤定义 的代码块匹配。
请注意,有些关键字后面有冒号 (:
),而有些则没有。如果您在不应该有冒号的关键字后面添加冒号,您的测试将被忽略。
每一行,除了空行,都必须以 Gherkin 关键字 开头,后面跟着任何您喜欢的文本。唯一的例外是放在 Example
/Scenario
、Background
、Scenario Outline
和 Rule
行下的自由格式描述。
主要关键字是
Feature
Rule
(从 Gherkin 6 开始)Example
(或 Scenario
)Given
、When
、Then
、And
、But
用于步骤 (或 *
)Background
Scenario Outline
(或 Scenario Template
)Examples
(或 Scenarios
)还有一些次要关键字
"""
(文档字符串)|
(数据表)@
(标签)#
(注释)Feature
关键字的目的是提供软件功能的高级描述,并对相关场景进行分组。
Gherkin 文档中的第一个主要关键字必须始终是 Feature
,后面跟着一个 :
和描述该功能的简短文本。
您可以在 Feature
下面添加自由格式文本以添加更多描述。
这些描述行在运行时被 Cucumber 忽略,但可用于报告 (它们被像官方 HTML 格式化程序这样的报告工具包含在内)。
Feature: Guess the word
The word guess game is a turn-based game for two players.
The Maker makes a word for the Breaker to guess. The game
is over when the Breaker guesses the Maker's word.
Example: Maker starts a game
名称和可选描述对 Cucumber 没有特殊意义。它们的目的是为您提供一个地方来记录功能的重要方面,例如简要说明和业务规则列表 (一般验收标准)。
Feature
的自由格式描述在您开始使用 Background
、Rule
、Example
或 Scenario Outline
(或它们的别名关键字) 关键字的行时结束。
您可以在 Feature
上方放置 标签 以对相关功能进行分组,而与文件和目录结构无关。
您只能在一个 .feature
文件中包含一个 Feature
。
自由格式描述 (如上所述,用于 Feature
) 也可以放在 Example
/Scenario
、Background
、Scenario Outline
和 Rule
下面。
您可以编写任何您喜欢的内容,只要没有行以关键字开头即可。
描述可以采用 Markdown 格式 - 包括官方 HTML 格式化程序在内的格式化程序支持这一点。
(可选) Rule
关键字自 v6 起成为 Gherkin 的一部分。
Rule
关键字的目的是表示应实现的一项业务规则。它为功能提供了更多信息。Rule
用于对属于此业务规则的多个场景进行分组。Rule
应包含一个或多个阐明特定规则的场景。
例如
# -- FILE: features/gherkin.rule_example.feature
Feature: Highlander
Rule: There can be only One
Example: Only One -- More than one alive
Given there are 3 ninjas
And there are more than one ninja alive
When 2 ninjas meet, they will fight
Then one ninja dies (but not me)
And there is one ninja less alive
Example: Only One -- One alive
Given there is only 1 ninja alive
Then he (or she) will live forever ;-)
Rule: There can be Two (in some cases)
Example: Two -- Dead and Reborn as Phoenix
...
这是一个具体示例,用于说明业务规则。它包含一个 步骤 列表。
关键字 Scenario
是 Example
关键字的同义词。
您可以添加任意数量的步骤,但建议每个示例有 3-5 步。如果步骤过多,示例将失去其作为规范和文档的表达能力。
除了作为规范和文档外,示例还是一个测试。总的来说,您的示例是系统的一个可执行规范。
示例遵循以下模式
Given
步骤)When
步骤)Then
步骤)每个步骤都以 Given
、When
、Then
、And
或 But
开头。
Cucumber 按您编写的顺序逐个执行场景中的每个步骤。当 Cucumber 尝试执行步骤时,它会查找匹配的步骤定义以执行。
在查找步骤定义时,不会考虑关键字。这意味着您不能有一个 Given
、When
、Then
、And
或 But
步骤与另一个步骤具有相同的文本。
Cucumber 认为以下步骤是重复的
Given there is money in my account
Then there is money in my account
这看起来可能是一个限制,但它迫使您想出一个更清晰、更明确的领域语言
Given my account has a balance of £430
Then my account should have a balance of £430
Given
步骤用于描述系统的初始上下文 - 场景的场景。通常这是发生在过去的事情。
当 Cucumber 执行 Given
步骤时,它将配置系统以处于定义良好的状态,例如创建和配置对象或将数据添加到测试数据库。
Given
步骤的目的是在用户 (或外部系统) 开始与系统交互 (在 When
步骤中) 之前,将系统置于已知状态。避免在 Given
中谈论用户交互。如果您要创建用例,Given
将是您的先决条件。
可以有多个 Given
步骤 (使用 And
或 But
用于 2 号及更高版本以使其更易读)。
示例
When
步骤用于描述事件或操作。这可以是个人与系统交互,也可以是另一个系统触发的事件。
示例
Then
步骤用于描述预期的结果。
Then
步骤的 步骤定义 应使用断言来比较实际结果 (系统实际执行的操作) 与预期结果 (步骤中描述的系统应执行的操作)。
一个结果应该是可观察的输出。也就是说,从系统中输出的东西(报告、用户界面、消息),而不是系统内部深埋的行为(比如数据库中的记录)。
示例
虽然在数据库中实现Then
步骤可能很诱人,但要抵制这种诱惑!
你应该只验证对用户(或外部系统)可观察的结果,而数据库的更改通常不可观察。
如果你有连续的Given
或Then
,你可以这样写
Example: Multiple Givens
Given one thing
Given another thing
Given yet another thing
When I open my eyes
Then I should see something
Then I shouldn't see something else
或者,你可以通过将连续的Given
或Then
替换为And
和But
,使示例的结构更流畅。
Example: Multiple Givens
Given one thing
And another thing
And yet another thing
When I open my eyes
Then I should see something
But I shouldn't see something else
Gherkin 还支持使用星号 (*
) 来代替任何正常的步骤关键字。当你有一些实际上是事情清单的步骤时,这很有用,这样你就可以用更像项目符号的方式来表达它,否则And
等的自然语言可能读起来不太优雅。
例如
Scenario: All done
Given I am out shopping
And I have eggs
And I have milk
And I have butter
When I check my list
Then I don't need anything
可以表达为
Scenario: All done
Given I am out shopping
* I have eggs
* I have milk
* I have butter
When I check my list
Then I don't need anything
有时你会发现自己在Feature
中所有场景中重复相同的Given
步骤。
由于它在每个场景中都被重复,因此这表明这些步骤对描述场景来说不是必要的;它们是附带细节。你可以将这些Given
步骤直接移到背景中,方法是在Background
部分下将它们分组。
Background
允许你为后面的场景添加一些上下文。它可以包含一个或多个Given
步骤,这些步骤在每个场景之前执行,但在任何Before hooks之后执行。
Background
放在第一个Scenario
/Example
之前,缩进级别相同。
例如
Feature: Multiple site support
Only blog owners can post to a blog, except administrators,
who can post to all blogs.
Background:
Given a global administrator named "Greg"
And a blog named "Greg's anti-tax rants"
And a customer named "Dr. Bill"
And a blog named "Expensive Therapy" owned by "Dr. Bill"
Scenario: Dr. Bill posts to his own blog
Given I am logged in as Dr. Bill
When I try to post to "Expensive Therapy"
Then I should see "Your article was published."
Scenario: Dr. Bill tries to post to somebody else's blog, and fails
Given I am logged in as Dr. Bill
When I try to post to "Greg's anti-tax rants"
Then I should see "Hey! That's not your blog!"
Scenario: Greg posts to a client's blog
Given I am logged in as Greg
When I try to post to "Expensive Therapy"
Then I should see "Your article was published."
Background
也支持在Rule
级别,例如
Feature: Overdue tasks
Let users know when tasks are overdue, even when using other
features of the app
Rule: Users are notified about overdue tasks on first use of the day
Background:
Given I have overdue tasks
Example: First use of the day
Given I last used the app yesterday
When I use the app
Then I am notified about overdue tasks
Example: Already used today
Given I last used the app earlier today
When I use the app
Then I am not notified about overdue tasks
...
你每个Feature
或Rule
只能有一组Background
步骤。如果你需要为不同的场景使用不同的Background
步骤,请考虑将你的场景集分解为更多Rule
或更多Feature
。
有关Background
的更不明确的替代方法,请查看条件钩子.
Background
来设置复杂的狀態,除非这种状态是客户实际上需要知道的。Given I am logged in as a site owner
。Background
部分简短。Background
超过 4 行,请考虑将一些无关的细节移到更高级别的步骤中。Background
部分生动。"User A"
、"User B"
、"Site 1"
这样的名称更容易记住故事。Background
部分已滚动出屏幕,则读者不再能全面了解正在发生的事情。考虑使用更高级别的步骤,或拆分*.feature
文件。Scenario Outline
关键字可用于多次运行相同的Scenario
,但使用不同的值组合。
关键字Scenario Template
是关键字Scenario Outline
的同义词。
复制和粘贴场景以使用不同的值很快就会变得单调乏味且重复。
Scenario: eat 5 out of 12
Given there are 12 cucumbers
When I eat 5 cucumbers
Then I should have 7 cucumbers
Scenario: eat 5 out of 20
Given there are 20 cucumbers
When I eat 5 cucumbers
Then I should have 15 cucumbers
我们可以将这两个类似的场景折叠成一个Scenario Outline
。
场景大纲允许我们通过使用带< >
分隔的参数的模板来更简洁地表达这些场景。
Scenario Outline: eating
Given there are <start> cucumbers
When I eat <eat> cucumbers
Then I should have <left> cucumbers
Examples:
| start | eat | left |
| 12 | 5 | 7 |
| 20 | 5 | 15 |
Scenario Outline
必须包含一个或多个Examples
(或Scenarios
)部分。它的步骤被解释为一个模板,该模板永远不会直接运行。相反,Scenario Outline
在它下面的Examples
部分中的每一行都运行一次(不包括第一行标题行)。
步骤可以使用<>
分隔的参数,这些参数引用示例表中的标题。Cucumber 会用表中的值替换这些参数,然后它会尝试将步骤与步骤定义匹配。
你也可以在多行步骤参数中使用参数。
在某些情况下,你可能想要传递给步骤的数据比单行容纳的更多。为此,Gherkin 有Doc Strings
和Data Tables
。
Doc Strings
对于将较大的文本块传递给步骤定义很有用。
文本应由三对双引号分隔符偏移,这些分隔符位于它们自己的行上。
Given a blog post named "Random" with Markdown body
"""
Some Title, Eh?
===============
Here is the first paragraph of my blog post. Lorem ipsum dolor sit amet,
consectetur adipiscing elit.
"""
在步骤定义中,无需查找此文本并在模式中匹配它。它将自动作为步骤定义中的最后一个参数传递。
"""
的缩进无关紧要,虽然常见的做法是从封闭步骤缩进两个空格。但是,三引号内部的缩进很重要。Doc String 的每一行都将根据打开的"""
取消缩进。因此,超过打开的"""
列的缩进将保留。
Doc Strings 也支持使用三个反引号作为分隔符。
Given a blog post named "Random" with Markdown body
```
Some Title, Eh?
===============
Here is the first paragraph of my blog post. Lorem ipsum dolor sit amet,
consectetur adipiscing elit.
```
对于那些习惯使用 Markdown 编写的人来说,这可能很熟悉。
可以为 DocString 添加注释,说明它包含的内容类型。你可以在三引号后指定内容类型,如下所示。
Given a blog post named "Random" with Markdown body
"""markdown
Some Title, Eh?
===============
Here is the first paragraph of my blog post. Lorem ipsum dolor sit amet,
consectetur adipiscing elit.
"""
Data Tables
对于将值列表传递给步骤定义很有用。
Given the following users exist:
| name | email | twitter |
| Aslak | [email protected] | @aslak_hellesoy |
| Julien | [email protected] | @jbpros |
| Matt | [email protected] | @mattwynne |
就像Doc Strings
一样,Data Tables
将作为最后一个参数传递给步骤定义。
如果你想在表格单元格中使用换行符,可以将其写为\n
。如果你需要|
作为单元格的一部分,可以将其转义为\|
。最后,如果你需要\
,可以将其转义为\\
。
Cucumber 提供了丰富的 API 用于在步骤定义中操作表格。有关更多详细信息,请参阅数据表 API 参考参考。
你为 Gherkin 选择的语言应该与你的用户和领域专家在谈论该领域时使用的语言相同。应避免在两种语言之间进行翻译。
这就是为什么 Gherkin 被翻译成70 多种语言。
这是一个用挪威语编写的 Gherkin 场景
# language: no
Funksjonalitet: Gjett et ord
Eksempel: Ordmaker starter et spill
Når Ordmaker starter et spill
Så må Ordmaker vente på at Gjetter blir med
Eksempel: Gjetter blir med
Gitt at Ordmaker har startet et spill med ordet "bløtt"
Når Gjetter blir med på Ordmakers spill
Så må Gjetter gjette et ord på 5 bokstaver
特征文件第一行上的# language:
标题告诉 Cucumber 使用什么口语——例如,法语为# language: fr
。如果你省略此标题,Cucumber 将默认为英语 (en
)。
一些 Cucumber 实现也允许你在配置中设置默认语言,这样你就不需要在每个文件中放置# language
标题。
你可以帮助我们改进此文档。编辑此页面.