Gherkin使用一組特殊的關鍵字來為可執(zhí)行規(guī)范賦予結構和意義。每個關鍵詞都被翻譯成多種語言;在這篇參考文獻中,我們將使用英語。
Gherkin文檔中的大多數(shù)行都以某個關鍵字作為開頭。
注釋行在文件的任何地方都是允許的。它們以零或多個空格開始,然后是一個散列符號(#)和一些文本。注釋必須從新的一行開始。
可以使用空格或制表符進行縮進。推薦的縮進級別是兩個空格。舉個例子:
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的重要方面,例如一個簡短的說明和一組業(yè)務規(guī)則(一般接受標準)。
當您使用關鍵字Rule、 Example或Scenario Outline(或它們的別名)開始一行時,Feature的自由格式描述文本將結束。
您可以將標記置于Feature之上,以獨立于文件和目錄結構對相關特性進行分組。
Descriptions
自由形式的描述(如上所述的Feature)也可以放在Example/Scenario、Background、Background, Scenario Outline 和 Rule下面。
你可以寫任何你喜歡的東西,只要沒有以關鍵字開頭的行。
Rule
在Gherkin v6中添加了(可選的)Rule關鍵字。(注意,Gherkin 6還沒有包含到Cucumber的所有實現(xiàn)中!)Rule 關鍵字的目的是表示應該實現(xiàn)的一個業(yè)務規(guī)則。它為特性提供了附加信息。Rule用于將屬于此業(yè)務規(guī)則的多個場景組合在一起。Rule應該包含一個或多個描述特定規(guī)則的場景。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
這是一個說明業(yè)務規(guī)則的具體示例。它由一系列步驟組成。
關鍵字Scenario是關鍵字 Example 的同義詞。
您可以有任意多的步驟,但是我們建議您將每個示例的步驟數(shù)量保持在3-5個。如果它們變得更長,就會失去作為規(guī)范和文檔的表達能力。
除了作為規(guī)范和文檔之外,示例也是一個測試。總的來說,您的示例是系統(tǒng)的可執(zhí)行規(guī)范。
Examples 遵循相同的模式:
- Describe an initial context (
Givensteps) - Describe an event (
Whensteps) - Describe an expected outcome (
Thensteps)
Steps
每個step都以關鍵字 Given, When, Then, And或 But 開頭。
Cucumber按您編寫的順序執(zhí)行場景中的每個步驟,每次執(zhí)行一個。當Cucumber嘗試執(zhí)行一個步驟時,它會尋找一個匹配的步驟定義來執(zhí)行。
在尋找步驟定義時,沒有考慮關鍵字。這意味著您不能使用與另一個步驟相同的文本執(zhí)行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 步驟用于描述系統(tǒng)的初始上下文—場景。這通常發(fā)生在過去。
當Cucumber執(zhí)行 Given步驟時,它將把系統(tǒng)配置為處于定義良好的狀態(tài),例如創(chuàng)建和配置對象或者向測試數(shù)據(jù)庫添加數(shù)據(jù)
Given 步驟的目的是在用戶(或外部系統(tǒng))開始與系統(tǒng)交互之前(在 When 步驟中)將系統(tǒng)置于已知狀態(tài)。避免討論用戶在Given步驟中交互。如果您正在創(chuàng)建用例,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 步驟用于描述事件或動作。這可以是與系統(tǒng)交互的人,也可以是由另一個系統(tǒng)觸發(fā)的事件
強烈建議每個場景只有一個When步驟。如果你覺得有必要添加更多,這通常是一個信號,表明你應該將場景分成多個場景。
例子:
- Guess a word
- Invite a friend
- Withdraw money
Then
Then 步驟用于描述預期的結果
Then 步驟應該使用一個斷言來比較實際的結果(系統(tǒng)實際做了什么)和預期的結果(這個步驟說明了系統(tǒng)應該做什么)
觀察應該在可觀測的輸出上。也就是說,系統(tǒng)輸出的東西(報告、用戶界面、消息),而不是深藏其中的東西(如數(shù)據(jù)庫)。
例子:
- See that the guessed word was wrong
- Receive an invitation
- Card should be swallowed
雖然很容易實現(xiàn)只需查看數(shù)據(jù)庫的Then 步驟—但是要抵制這種誘惑!
您應該只驗證對用戶(或外部系統(tǒng))可見的結果,而數(shù)據(jù)庫通常不可見。
And, But
如果你有幾個Given’s, When’s, 或 Thens,你可以這樣寫:
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
有時候,您會發(fā)現(xiàn)自己在某個特性的所有場景中重復相同的Given步驟。
由于它在每個場景中都是重復的,這表明這些步驟對于描述場景并不重要;這些都是偶然的細節(jié)。您可以通過將這些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設置復雜的狀態(tài),除非該狀態(tài)實際上是客戶端需要知道的。
例如,如果用戶名和站點名對客戶機不重要,請使用更高級別的步驟,比如Given I am logged in as a site owner。
- 保持你的
Background部分簡短。
客戶在閱讀場景時需要記住這些內(nèi)容。如果Background超過4行,考慮將一些不相關的細節(jié)移動到更高級別的步驟。
- 讓你的
Background部分生動。
使用色彩鮮艷的名字,試著講述一個故事。人類的大腦跟蹤故事比像“用戶A”、“用戶B”、“網(wǎng)站1”之類的名字。
- 保持你的場景簡短,不要太多。
如果Background部分已經(jīng)從屏幕上滾動,讀者就不再對發(fā)生的事情有一個完整的概述了。考慮使用高級步驟,或者拆分*.feature文件
Scenario Outline
Scenario Outline關鍵字可用于多次運行相同的Scenario,不同的值組合。關鍵字Scenario Template是關鍵字Scenario Outline的同義詞。
復制和粘貼場景來使用不同的值會很快變得單調(diào)和重復:
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。
場景大綱允許我們通過使用帶有< >-分隔符參數(shù)的模板更簡潔地表達這些場景:
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)部分。它的步驟被解釋為一個從不直接運行的模板。相反,在它下面的Examples部分中,Scenario Outline對每一行運行一次(不包括第一個標題行)。
這些步驟可以使用<>分隔參數(shù)引用樣例表中的頭。Cucumber將使用表中的值替換這些參數(shù),然后根據(jù)步驟定義匹配步驟。
Step Arguments(步驟參數(shù))
在某些情況下,您可能希望將更多的數(shù)據(jù)傳遞給一個步驟,而不是一行。為此,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.
"""
在您的步驟定義中,不需要找到此文本并將其匹配到您的模式中。它將自動傳遞作為步驟定義的最后一個參數(shù)。
開孔的縮進"""并不重要,雖然通常的做法是在兩個空間內(nèi)從封閉的步驟。然而,三引號內(nèi)的縮進非常重要。Doc String的每一行都將按照開頭的"""縮進。因此,開孔"""欄外的壓痕將被保留。
Data Tables
Data Tables可以方便地將值列表傳遞到步驟定義:
Given the following users exist:
| name | email | twitter |
| Aslak | aslak@cucumber.io | @aslak_hellesoy |
| Julien | julien@cucumber.io | @jbpros |
| Matt | matt@cucumber.io | @mattwynne |
就像Doc字符串一樣,數(shù)據(jù)表將作為最后一個參數(shù)傳遞給步驟定義。
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實現(xiàn)還允許在配置中設置默認語言,因此不需要在每個文件中都放置# language頭。
Gherkin Dialects(小黃瓜方言)
為了讓小黃瓜可以用多種語言寫,關鍵字已經(jīng)被翻譯成多種語言。為了提高可讀性和流,一些語言可能對任何給定的關鍵字有多個翻譯。
List translation options(翻譯選項列表)
您可以從命令行獲取有關翻譯的信息。
查看可用語言的列表:
cucumber --i18n help
要列出特定語言的關鍵字,請使用語言代碼:
cucumber --i18n <language_code>
例如,查看法語中的關鍵詞:
cucumber --i18n fr