この記事は
Gherkin Referenceを抜粋して日本語訳したもの+個人的に追加したサンプル。
Karateをやってみようと思うので、まずはGherkinに慣れる必要あるかなと思った次第。
多分日本語のドキュメントもどっかにあると思うんだけど、備忘録的とか勉強的な意味合いなので自分で翻訳してみることにする。
また、Gherkin ReferenceはCucumber向けのドキュメントであるため、本記事を読む際はそこだけちょっと気を付ける必要がある。
知りたいことはいろいろあるが、現在はデモ用の.featureファイルを読めない程度の理解度であるから、これを理解できるようにすることを第一目標とする:
Feature: sample karate test script
for help, see: https://github.com/intuit/karate/wiki/IDE-Support
Background:
* url 'https://jsonplaceholder.typicode.com'
Scenario: get all users and then get the first user by id
Given path 'users'
When method get
Then status 200
* def first = response[0]
Given path 'users', first.id
When method get
Then status 200
Scenario: create a user and then get it by id
* def user =
"""
{
"name": "Test User",
"username": "testuser",
"email": "test@user.com",
"address": {
"street": "Has No Name",
"suite": "Apt. 123",
"city": "Electri",
"zipcode": "54321-6789"
}
}
"""
Given url 'https://jsonplaceholder.typicode.com/users'
And request user
When method post
Then status 201
* def id = response.id
* print 'created id is: ', id
Given path id
# When method get
# Then status 200
# And match response contains user
Gherkin記法
Keywords
空行でないすべての行は、以下のGherkinキーワードから始める必要があります。ただし、Feature
とScinario
に対してdescriptionsを記述する場合はその限りではありません。
プライマリキーワードの一覧:
- Feature
- Rule (as of Gherkin 6)
- Example (or Scenario)
- Given, When, Then, And, But for steps (or *)
- Background
- Scenario Outline (or Scenario Template)
- Examples (or Scenarios)
セカンダリキーワードの一覧:
Feature
Feature
キーワードは、ソフトウェアの機能や関連するシナリオへの抽象度の高い説明を提供します。
Gherkinドキュメントにおける最初のキーワードはFeature
でなければならず、そのあとには:
を付与しなければなりません(要はFeature:
)。このあとに、機能を説明する短いテキストが記載されます(例:Feature: my first API test
)。
更に説明が必要である場合は、改行してテキストを追加することができます。
追加したテキストはCucumber実行時に無視されますが、レポートには記載されます(例えば公式のHTMLフォーマッタ)。
Feature: sample karate test script
for help, see: https://github.com/intuit/karate/wiki/IDE-Support
As you know, this is a sample description.
I do this for checking how the description will be expressed in HTML report.
Descriptionsについて
Feature
に追加でテキストを記載できると説明しましたが、Example
, Scenario
, Background
, Scenario Outline
, Rule
に対しても同じことができます。
基本的には自由にテキストを記述できますが、キーワードを行頭に記述してはいけません(=Feature, Example, Scenarioといったワードが、その行の最初に記述されてはいけない)
Descriptionsは、Markdown形式で記述することができます。official HTML formatterを含むフォーマッタも、これをサポートしています。
Rule
(optional) Rule
キーワードはv6からGherkinの一部になりました。
Rule
キーワードの目的は、実装されるべきビジネスルールを表現することです。これは、featureに追加の情報を提供します。Rule
は、そのルールに所属する幾つかのシナリオに対してまとめて使用されます。ルールは、特定のルールを説明する1つ以上のシナリオから構成されます。
例:
# -- 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
これはビジネスルールを説明する具体的な例です。これは、ステップのリストから構成されます。
Scenario
キーワードは、Example
キーワードの同意語です。
あなたは好きなだけステップを記述することができますが、exampleごとに3-5ステップとすることを推奨します。ステップが増えすぎると、仕様やドキュメントとしての表現力を失う原因になるからです。
Example
は仕様やドキュメントのほか、テストにもなります。全体として、あなたが作成するExample
はシステムの実行可能仕様となるでしょう。
Example
は、以下のパターンに従います:
- 初期コンテキストの説明 (
Given
steps) - イベントの説明 (
When
steps) - 期待される出力の説明 (
Then
steps)
Steps
それぞれのステップは、Given
, When
, Then
, And
, またはBut
から始まります。
Cucumberはシナリオ内のステップを1つずつ実行します。実行順序は、あなたが記述した順序です。Cucumberがステップを実行するとき、Cucumberは実行するステップの定義を探します。
ステップの定義を探す際、キーワードは考慮されません。これは、あなたがGiven
, When
, Then
, And
, またはBut
と同じテキストをを持つステップを別のステップとして保持することができないことを意味します。
Cucumberは、以下のステップを複製であると認識します:
Given there is money in my account
Then there is money in my account
以下の場合は制約に引っかかりそうですが、Cucumberはあなたにより曖昧でない、よりクリアなdomain languageを提案するよう強制するでしょう:
Given my account has a balance of £430
Then my account should have a balance of £430
Given
Given
ステップはシステムの初期コンテキスト(シナリオのシーン)を説明するために使われます。典型的には、過去に発生した何かです。
Cucumber がGiven
ステップを実行する際には、オブジェクトを生成・設定したりデータをテスト用データベースに追加するなど、システムをwell-definedな状態に設定します。
Given
ステップの目的は、ユーザー(または外部システム)がシステムと交信する前にシステムをknown stateにすることです。
Given
ステップは複数記述することができます(可読性を上げるため、2番目以降はAnd
またはBut
を使用してください)。
例:
- Mickey and Minnie have started a game
- I am logged in
- Joe has a balance of £42
When
When
ステップはイベントやアクションを説明するために使われます。これはシステムと交信する個人や、他のシステムからトリガーされるイベントのことでもあります。
1つのシナリオには、1つのWhen
ステップのみ記述することを強く推奨します。無理にWhen
ステップを追加することは、通常シナリオをより小さい複数のシナリオに分割する必要があることを示唆します。
例:
- Guess a word
- Invite a friend
- Withdraw money
Then
Then
ステップは期待される出力や結果を説明します。
Then
ステップの定義は、actual outcome(システムの実挙動)とexpected outcome(システムがするはずの挙動)の比較をするアサーションであるべきです。
outcomeは、観測できる出力であるべきです。それは、システムから出てくるもの(レポート、ユーザーインターフェース、メッセージ)で、システムに深く埋め込まれた振る舞いではありません(データベースのレコードのようなもの)。
例:
- See that the guessed word was wrong
- Receive an invitation
- Card should be swallowed
- While it might be tempting to implement Then steps to look in the database - resist that temptation!
あなたは、ユーザー(または外部システム)から観測できるoutcomeだけを検証するべきであり、通常はこれをデータベースにはしません。
And, But
あなたがもし、Given
, When
, 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
, When
, Then
をAnd
, But
に置換して、Example
をfluidly structuredな形にすることもできます:
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
Background
時折、Feature
内のすべてのシナリオで同じGiven
ステップを繰り返ていることに気づくでしょう。
これはすべてのシナリオで繰り返されるものであるため、つまりそのステップはシナリオに記述する必要があるとは言えません。それらはすべて同一の内容だからです。このような場合、これらのGiven
ステップをBackground
セクションに移動することができます。
Background
は、シナリオがフォローすべき文脈を追加します。Background
には1つ以上のGiven
ステップを追加することができ、これらはシナリオの最初に実行されます(より正確には、Before
ホック→Background
キーワード内のGiven
ステップ→シナリオ内のステップの順で実行されます)。
Background
は最初のScenario
またはExample
の前に記述されます。インデントのレベルはどれも同じです。
【参考】Before
ホックの説明と、Background
キーワードとの違い:Cucumber | @Before hook Vs Background | Usage
サンプル:
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
...
Background
は、Feature
またはRule
ごとに1つだけ定義することができます。異なるシナリオに異なるBackground
が必要な場合は、シナリオをより細かいRule
やFeature
に分解することを考えた方が良いでしょう。
より明示的でないBackground
の代替物に関しては、conditionalホックをチェックするとよいです。
Backgroundを使う際のTips
-
Background
を複雑な状態で使用しない、クライアントがその状態を知る必要がない限りは - 例えば、もしユーザー名とサイト名がクライアントにとって問題でなければ、
Given I am logged in as a site owner
のようなハイレベルなステップを使用します -
Background
セクションを短くする - クライアントはシナリオを読むとき、バックグラウンドの内容を覚えておく必要があります。もし
Background
が4行以上で構成されている場合は、関連しないものをハイレベルのステップに移動することを検討したほうがよいでしょう -
Background
セクションを鮮明にする - カラフルな名前を使い、ストーリーを伝えるように努めます。人間の脳は"User A", "User B", "Site 1"のような名前よりも、ストーリーのほうが覚えやすいからです
- シナリオを短くし、あまり多すぎるようにはしない
-
Background
セクションがスクリーン外になるまでスクロールされると、読み手はBackground
セクションで何が起きるのかすべて把握できなくなります。この場合、ハイレベルなステップを利用するか、*.feature ファイルに分割することを検討するとよいでしょう
Scenario Outline
Scenario Outline
キーワードは、同じシナリオを別々の値を使って実行したいときに使用します。
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
このとき、私たちは2つの似通ったシナリオを1つのScenario Outline
にcollapseすることができます。
Scenario Outline
では< >-delimited parameterを使用したtemplateを記述することができ 、これによって複数のシナリオを簡潔に表現することができます:
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
は、Example
(またはScenario
)セクションを含まなければなりません。ステップは直接実行されることのないtemplateとして解釈されます。その代わり、Scenario Outline
はExample
セクションの行数の分だけ実行されます(ヘッダー行を除く)。
ステップでは、Example
テーブルのヘッダー行を参照する<> delimited parametersを使用することができます。Cucumber では、ステップとstep definitionをマッチする前にこれらのパラメータをテーブルの値に置換します。
また、パラメータをmultiline step argumentsで使用することもできます。
Step Arguments
幾つかのケースでは、あなたはステップに対して1行では収まらないデータを渡す必要があるかもしれない。この目的のため、GherkinにはDoc Strings
とData Tables
がある。
Doc Strings
Doc Strings
は大きな量のテキストをstep definitionに渡すときに便利です。
テキストは、3つのダブルクオーテーションで区切る必要があります:
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.
"""
step definitionにおいて、このテキストを見つける必要もなければあなたのパターンにマッチする必要もありません。自動的に、step definitionの最後の引数として渡されます。
最初の"""
のインデントは重要ではないものの、一般的にはenclosing stepからスペース2つ分インデントします。しかし、"""
の内側に関しては、インデントは重要です。Doc String
のそれぞれの行は、開始の"""
を参考にしてdedented されます。したがって、開始の"""
以降の行のインデントは保存されます。
また、Doc strings
はデリミタとして3つのbackticks をサポートしています:
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.
```
Data Tables
Data Tables
は、step definitionに値の一覧を渡すときに便利です:
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
は最後の引数としてstep definitionに渡されます。
Cucumberは、テーブルをstep definitions内から操作するAPIを提供しています。詳細についてはData Table API referenceを参照してください。
Spoken Languages
Gherkinで使用する言語は、あなたのユーザーやdomain expertsがドメインについて会話するときに用いる言語であるべきです。2つの言語を翻訳しなければならなない状態は避けるべきでしょう。
そのため、Gherkinは70を超える言語に翻訳されています。
以下に示すのは、シナリオをノルウェー語で記載したものです:
# 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
1行目の# language:
ヘッダが、Cucumberに使用する言語を伝えます。例えば、# language: fr
はフランス語です。# language:
ヘッダを記述しなかった場合は、Cucumberはデフォルト設定の英語を使用します。
いくつかのCucumber implementationsは設定でデフォルト言語を決めることができます。その際は、すべてのファイルで# language:
ヘッダを記述する必要はありません。