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关键字开头,然后是您喜欢的任何文本。唯一的例外是特性和场景描述。
主要关键词有:
Feature
-
Rule
(as of Gherkin 6)
-Example
(orScenario
) -
Given, When, Then, And, But
(steps) Background
-
Scenario Outline
(orScenario Template
) Examples
也有一些次要的关键字:
-
"""
(Doc Strings) -
|
(Data Tables) -
@
(Tags) -
#
(Comments)
本地化
小黄瓜被许多语言本地化;每一个都有自己的本地对应的这些关键字。
Feature
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
的重要方面,例如一个简短的说明和一组业务规则(一般接受标准)。
当您使用关键字Rule
、 Example
或Scenario Outline
(或它们的别名)开始一行时,Feature
的自由格式描述文本将结束。
您可以将标记置于Feature
之上,以独立于文件和目录结构对相关特性进行分组。
Descriptions
自由形式的描述(如上所述的Feature
)也可以放在Example
/Scenario
、Background
、Background
, Scenario Outline
和 Rule
下面。
你可以写任何你喜欢的东西,只要没有以关键字开头的行。
Rule
在Gherkin v6中添加了(可选的)Rule
关键字。(注意,Gherkin 6还没有包含到Cucumber的所有实现中!)Rule
关键字的目的是表示应该实现的一个业务规则。它为特性提供了附加信息。Rule
用于将属于此业务规则的多个场景组合在一起。Rule
应该包含一个或多个描述特定规则的场景。Rule
不能包含Background
。
例如:
# -- 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
...
Example
这是一个说明业务规则的具体示例。它由一系列步骤组成。
关键字Scenario
是关键字 Example
的同义词。
您可以有任意多的步骤,但是我们建议您将每个示例的步骤数量保持在3-5个。如果它们变得更长,就会失去作为规范和文档的表达能力。
除了作为规范和文档之外,示例也是一个测试。总的来说,您的示例是系统的可执行规范。
Examples 遵循相同的模式:
- Describe an initial context (
Given
steps) - Describe an event (
When
steps) - Describe an expected outcome (
Then
steps)
Steps
每个step都以关键字 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
Given
步骤用于描述系统的初始上下文—场景。这通常发生在过去。
当Cucumber执行 Given
步骤时,它将把系统配置为处于定义良好的状态,例如创建和配置对象或者向测试数据库添加数据
Given
步骤的目的是在用户(或外部系统)开始与系统交互之前(在 When
步骤中)将系统置于已知状态。避免讨论用户在Given
步骤中交互。如果您正在创建用例,Given
将是您的先决条件。
有几个Given
步骤是可以的(对于2个及以上的步骤,只需使用And
或But
使其更具可读性)。
举几个Given
的例子:
- Mickey and Minnie have started a game
- I am logged in
- Joe has a balance of £42
When
When
步骤用于描述事件或动作。这可以是与系统交互的人,也可以是由另一个系统触发的事件
强烈建议每个场景只有一个When
步骤。如果你觉得有必要添加更多,这通常是一个信号,表明你应该将场景分成多个场景。
例子:
- Guess a word
- Invite a friend
- Withdraw money
Then
Then
步骤用于描述预期的结果
Then
步骤应该使用一个断言来比较实际的结果(系统实际做了什么)和预期的结果(这个步骤说明了系统应该做什么)
观察应该在可观测的输出上。也就是说,系统输出的东西(报告、用户界面、消息),而不是深藏其中的东西(如数据库)。
例子:
- See that the guessed word was wrong
- Receive an invitation
- Card should be swallowed
虽然很容易实现只需查看数据库的Then
步骤—但是要抵制这种诱惑!
您应该只验证对用户(或外部系统)可见的结果,而数据库通常不可见。
And, But
如果你有几个Given
’s, When
’s, 或 Then
s,你可以这样写:
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
或者,你可以让它阅读更流畅:
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
Background
有时候,您会发现自己在某个特性的所有场景中重复相同的Given
步骤。
由于它在每个场景中都是重复的,这表明这些步骤对于描述场景并不重要;这些都是偶然的细节。您可以通过将这些Given
步骤分组到一个背景部分中,将它们移动到Background
中。
Background
允许您向特性中的场景添加一些上下文。它可以包含一个或多个Given
步骤。
Background
在每个场景之前运行,并在任何Before hooks之后运行。在feature 文件中,将Background
放在第一个Scenario
之前。
每个特性只能有一组Background
步骤。如果您需要针对不同的场景使用不同的Background
步骤,则需要将它们拆分为不同的功能文件。
例如:
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."
Tips for using Background
- 不要使用
Background
设置复杂的状态,除非该状态实际上是客户端需要知道的。
例如,如果用户名和站点名对客户机不重要,请使用更高级别的步骤,比如Given I am logged in as a site owner
。
- 保持你的
Background
部分简短。
客户在阅读场景时需要记住这些内容。如果Background
超过4行,考虑将一些不相关的细节移动到更高级别的步骤。
- 让你的
Background
部分生动。
使用色彩鲜艳的名字,试着讲述一个故事。人类的大脑跟踪故事比像“用户A”、“用户B”、“网站1”之类的名字。
- 保持你的场景简短,不要太多。
如果Background
部分已经从屏幕上滚动,读者就不再对发生的事情有一个完整的概述了。考虑使用高级步骤,或者拆分*.feature
文件
Scenario Outline
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 cucumbers
When I eat cucumbers
Then I should have cucumbers
Examples:
| start | eat | left |
| 12 | 5 | 7 |
| 20 | 5 | 15 |
Scenario Outline
必须包含Examples
(或Scenarios
)部分。它的步骤被解释为一个从不直接运行的模板。相反,在它下面的Examples
部分中,Scenario Outline
对每一行运行一次(不包括第一个标题行)。
这些步骤可以使用<>
分隔参数引用样例表中的头。Cucumber将使用表中的值替换这些参数,然后根据步骤定义匹配步骤。
Step Arguments(步骤参数)
在某些情况下,您可能希望将更多的数据传递给一个步骤,而不是一行。为此,Gherkin具有Doc Strings
和Data Tables
。
Doc Strings
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
的每一行都将按照开头的"""
缩进。因此,开孔"""
栏外的压痕将被保留。
Data Tables
Data Tables
可以方便地将值列表传递到步骤定义:
Given the following users exist:
| name | email | twitter |
| Aslak | [email protected] | @aslak_hellesoy |
| Julien | [email protected] | @jbpros |
| Matt | [email protected] | @mattwynne |
就像Doc字符串一样,数据表将作为最后一个参数传递给步骤定义。
Spoken Languages (语言/口语)
你选择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
: header告诉Cucumber使用什么口语—例如# language: fr
表示法语。如果省略此标题,Cucumber将默认为English (en
)。
一些Cucumber实现还允许在配置中设置默认语言,因此不需要在每个文件中都放置# language
头。
Gherkin Dialects(小黄瓜方言)
为了让小黄瓜可以用多种语言写,关键字已经被翻译成多种语言。为了提高可读性和流,一些语言可能对任何给定的关键字有多个翻译。
List translation options(翻译选项列表)
您可以从命令行获取有关翻译的信息。
查看可用语言的列表:
cucumber --i18n help
要列出特定语言的关键字,请使用语言代码:
cucumber --i18n
例如,查看法语中的关键词:
cucumber --i18n fr
链接
https://cucumber.io/docs/gherkin/reference/