Gherkin 使用一組特殊的關鍵字來為可執行的規格提供結構和意義。每個關鍵字都被翻譯成多種口語語言;在本參考中,我們將使用英文。

Gherkin 文件中的大多數行都以關鍵字開頭。

註解僅允許在新行的開頭,在功能檔案中的任何位置。它們以零個或多個空格開始,後跟一個井號 (#) 和一些文字。

Gherkin 目前不支援區塊註解。

空格或 Tab 皆可用於縮排。建議的縮排級別為兩個空格。以下是一個範例

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/ScenarioBackgroundScenario OutlineRule 行下的自由格式描述。

主要關鍵字是

還有一些次要關鍵字

  • """ (Doc Strings (文件字串))
  • | (Data Tables (資料表))
  • @ (Tags (標籤))
  • # (Comments (註解))

本地化

Gherkin 已本地化為許多口語語言;每種語言都有其自己的本地化關鍵字。

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 沒有特殊意義。它們的目的是為您提供一個記錄功能重要方面的場所,例如簡短說明和業務規則列表(一般接受標準)。

當您以關鍵字 BackgroundRuleExampleScenario Outline(或其別名關鍵字)開始一行時,Feature 的自由格式描述將結束。

您可以在 Feature 上方放置標籤以分組相關功能,而與您的檔案和目錄結構無關。

在一個 .feature 檔案中,您只能有一個 Feature

描述

自由格式描述(如上述 Feature 所述)也可以放置在 Example/ScenarioBackgroundScenario OutlineRule 下方。

只要沒有任何行以關鍵字開頭,您就可以撰寫任何您喜歡的內容。

描述可以是 Markdown 格式 - 包括官方 HTML 格式化器在內的格式化器都支援此格式。

Rule (規則)

(可選)Rule 關鍵字自 v6 起已成為 Gherkin 的一部分。

Cucumber 對規則的支援

Rule 關鍵字仍然很新。它已經移植到許多 Cucumber 實作中。但是,如果您遇到問題,請檢查 Cucumber 實作的文件,以確保它支援它。

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
      ...

Example (範例)

這是一個具體的範例說明了一個業務規則。它包含一個步驟列表。

關鍵字 Scenario 是關鍵字 Example 的同義詞。

您可以擁有任意多個步驟,但我們建議每個範例有 3-5 個步驟。步驟太多會導致範例失去其作為規格和文件的表達能力。

除了作為規格和文件之外,範例也是一個測試。總的來說,您的範例是系統的可執行規格

範例遵循相同的模式

  • 描述初始上下文 (Given 步驟)
  • 描述一個事件 (When 步驟)
  • 描述預期的結果 (Then 步驟)

步驟

每個步驟都以 GivenWhenThenAndBut 開頭。

Cucumber 會一次執行情境中的每個步驟,按照您撰寫它們的順序。當 Cucumber 嘗試執行步驟時,它會尋找符合的步驟定義來執行。

尋找步驟定義時不會考慮關鍵字。這表示您不能有與另一個步驟具有相同文字的 GivenWhenThenAndBut 步驟。

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 步驟(使用 AndBut 作為第 2 個及以上,使其更具可讀性)。

範例

  • 米奇和米妮已經開始玩遊戲
  • 我已登入
  • Joe 的餘額為 42 英鎊

When (當)

When 步驟用於描述事件或動作。這可以是與系統互動的人,也可以是另一個系統觸發的事件。

範例

  • 猜一個單字
  • 邀請朋友
  • 提款

想像一下現在是 1922 年

大多數軟體所做的事情,人們都可以手動完成(只是效率沒那麼高)。

盡力想出一些範例,這些範例不對技術或使用者介面做任何假設。想像一下現在是 1922 年,那時還沒有電腦。

實作細節應該隱藏在步驟定義中。

然後

Then 步驟用於描述預期的結果或輸出。

Then 步驟的步驟定義應該使用斷言來比較實際的結果(系統實際執行的)和預期的結果(步驟所說系統應該執行的)。

結果應該可觀察的輸出。也就是說,從系統輸出的東西(報告、使用者介面、訊息),而不是深埋在系統內部的行為(例如資料庫中的記錄)。

範例

  • 查看猜測的單字是否錯誤
  • 收到邀請
  • 卡片應該被吞下

雖然實作 Then 步驟來查看資料庫可能很吸引人 - 請抵制這種誘惑!

您應該只驗證使用者(或外部系統)可觀察到的結果,而對資料庫的變更通常不可觀察。

而且、但是

如果您有連續的 GivenThen,您可以寫成

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

或者,您可以通過將連續的 GivenThen 替換為 AndBut 來使範例的結構更流暢。

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
  ...

每個 FeatureRule 只能有一組 Background 步驟。如果您需要針對不同情境使用不同的 Background 步驟,請考慮將您的情境集拆分為更多 Rule 或更多 Feature

對於 Background 的較不明確的替代方案,請查看條件掛鉤

使用背景的提示

  • 不要使用 Background 來設定複雜的狀態,除非該狀態實際上是客戶需要知道的內容。
    • 例如,如果使用者和網站名稱對客戶來說並不重要,請使用更高級的步驟,例如 Given 我以網站擁有者身分登入
  • 保持您的 Background 區塊簡短
    • 客戶在閱讀情境時確實需要記住這些內容。如果 Background 超過 4 行,請考慮將一些不相關的詳細資訊移至更高級的步驟。
  • 使您的 Background 區塊生動
    • 使用豐富多彩的名稱,並嘗試講述一個故事。人腦追蹤故事的能力遠勝於追蹤像 "使用者 A""使用者 B""網站 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 StringsData 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.
  """

在您的步驟定義中,無需尋找此文字並在您的模式中匹配它。它會自動作為步驟定義中的最後一個引數傳遞。

開頭 """ 的縮排並不重要,儘管常見的做法是從封閉步驟縮排兩個空格。但是,三引號內的縮排很重要。文件字串的每一行都會根據開頭的 """ 進行 dedent。因此,超出開頭 """ 欄位的縮排將會保留。

文件字串也支援使用三個反引號作為分隔符號

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 編寫的人來說,這可能很熟悉。

對反引號的工具支援

雖然目前所有版本的 Cucumber 都支援反引號作為分隔符號,但許多工具(如文字編輯器)尚不支援。

可以使用它包含的內容類型來註釋 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.
  """

對內容類型的工具支援

雖然目前所有版本的 Cucumber 都支援內容類型作為分隔符號,但許多工具(如文字編輯器)尚不支援。

資料表

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 Strings 一樣,Data Tables 將作為最後一個引數傳遞給步驟定義。

表格儲存格跳脫

如果您想在表格儲存格中使用換行字元,可以將其寫為 \n。如果您需要將 | 作為儲存格的一部分,可以將其跳脫為 \|。最後,如果您需要 \,可以使用 \\ 跳脫它。

資料表 API

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 標頭。

您可以幫助我們改進此文件。編輯此頁面